/**
 * @license Angular v9.1.7
 * (c) 2010-2020 Google LLC. https://angular.io/
 * License: MIT
 */

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('rxjs'), require('rxjs/operators')) :
  typeof define === 'function' && define.amd ? define('@angular/core', ['exports', 'rxjs', 'rxjs/operators'], factory) :
  (global = global || self, factory((global.ng = global.ng || {}, global.ng.core = {}), global.rxjs, global.rxjs.operators));
}(this, (function (exports, rxjs, operators) { 'use strict';

  /*! *****************************************************************************
  Copyright (c) Microsoft Corporation. All rights reserved.
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  this file except in compliance with the License. You may obtain a copy of the
  License at http://www.apache.org/licenses/LICENSE-2.0

  THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  MERCHANTABLITY OR NON-INFRINGEMENT.

  See the Apache Version 2.0 License for specific language governing permissions
  and limitations under the License.
  ***************************************************************************** */
  /* 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 (b.hasOwnProperty(p)) d[p] = b[p]; };
      return extendStatics(d, b);
  };

  function __extends(d, b) {
      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 };
      }
  }

  function __exportStar(m, exports) {
      for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = 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;
  }

  function __spread() {
      for (var ar = [], i = 0; i < arguments.length; i++)
          ar = ar.concat(__read(arguments[i]));
      return ar;
  }

  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 __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;
  };

  function __importStar(mod) {
      if (mod && mod.__esModule) return mod;
      var result = {};
      if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
      result.default = 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;
  }

  /**
   * @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
   */
  /**
   * 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 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
   */
  var ANNOTATIONS = '__annotations__';
  var PARAMETERS = '__parameters__';
  var PROP_METADATA = '__prop__metadata__';
  /**
   * @suppress {globalThis}
   */
  function makeDecorator(name, props, parentClass, additionalProcessing, typeFn) {
      return noSideEffects(function () {
          var metaCtor = makeMetadataCtor(props);
          function DecoratorFactory() {
              var _a;
              var args = [];
              for (var _i = 0; _i < arguments.length; _i++) {
                  args[_i] = arguments[_i];
              }
              if (this instanceof DecoratorFactory) {
                  metaCtor.call.apply(metaCtor, __spread([this], args));
                  return this;
              }
              var annotationInstance = new ((_a = DecoratorFactory).bind.apply(_a, __spread([void 0], args)))();
              return function TypeDecorator(cls) {
                  if (typeFn)
                      typeFn.apply(void 0, __spread([cls], args));
                  // Use of Object.defineProperty is important since it creates non-enumerable property which
                  // prevents the property is copied during subclassing.
                  var 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() {
          var args = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              args[_i] = arguments[_i];
          }
          if (props) {
              var values = props.apply(void 0, __spread(args));
              for (var propName in values) {
                  this[propName] = values[propName];
              }
          }
      };
  }
  function makeParamDecorator(name, props, parentClass) {
      return noSideEffects(function () {
          var metaCtor = makeMetadataCtor(props);
          function ParamDecoratorFactory() {
              var _a;
              var args = [];
              for (var _i = 0; _i < arguments.length; _i++) {
                  args[_i] = arguments[_i];
              }
              if (this instanceof ParamDecoratorFactory) {
                  metaCtor.apply(this, args);
                  return this;
              }
              var annotationInstance = new ((_a = ParamDecoratorFactory).bind.apply(_a, __spread([void 0], 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.
                  var 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(function () {
          var metaCtor = makeMetadataCtor(props);
          function PropDecoratorFactory() {
              var _a;
              var args = [];
              for (var _i = 0; _i < arguments.length; _i++) {
                  args[_i] = arguments[_i];
              }
              if (this instanceof PropDecoratorFactory) {
                  metaCtor.apply(this, args);
                  return this;
              }
              var decoratorInstance = new ((_a = PropDecoratorFactory).bind.apply(_a, __spread([void 0], args)))();
              function PropDecorator(target, name) {
                  var constructor = target.constructor;
                  // Use of Object.defineProperty is important since it creates non-enumerable property which
                  // prevents the property is copied during subclassing.
                  var 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.apply(void 0, __spread([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 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
   */
  var ɵ0 = function (token) { return ({ token: token }); };
  /**
   * Inject decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Inject = makeParamDecorator('Inject', ɵ0);
  /**
   * Optional decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Optional = makeParamDecorator('Optional');
  /**
   * Self decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Self = makeParamDecorator('Self');
  /**
   * SkipSelf decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var SkipSelf = makeParamDecorator('SkipSelf');
  /**
   * Host decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Host = makeParamDecorator('Host');
  var ɵ1 = function (attributeName) { return ({ attributeName: attributeName }); };
  /**
   * Attribute decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Attribute = makeParamDecorator('Attribute', ɵ1);

  /**
   * @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
   */
  (function (InjectFlags) {
      // TODO(alxhub): make this 'const' 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";
  })(exports.InjectFlags || (exports.InjectFlags = {}));

  /**
   * @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
   */
  function getClosureSafeProperty(objWithPropertyToExtract) {
      for (var 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 (var key in source) {
          if (source.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
              target[key] = source[key];
          }
      }
  }

  /**
   * @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
   */
  /**
   * Construct an `InjectableDef` 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
   */
  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 be generated code, and that
   * code should now use ɵɵdefineInjectable instead.
   * @publicApi
   */
  var 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:
   *
   * * `factory`: an `InjectorType` is an instantiable type, so a zero argument `factory` function to
   *   create the type must be provided. If that factory function needs to inject arguments, it can
   *   use the `inject` function.
   * * `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.
   *
   * @publicApi
   */
  function ɵɵdefineInjector(options) {
      return {
          factory: options.factory,
          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, type[NG_PROV_DEF]) ||
          getOwnDefinition(type, type[NG_INJECTABLE_DEF]);
  }
  /**
   * Return `def` only if it is defined directly on `type` and is not inherited from a base
   * class of `type`.
   *
   * The function `Object.hasOwnProperty` is not sufficient to distinguish this case because in older
   * browsers (e.g. IE10) static property inheritance is implemented by copying the properties.
   *
   * Instead, the definition's `token` is compared to the `type`, and if they don't match then the
   * property was not defined directly on the type itself, and was likely inherited. The definition
   * is only returned if the `type` matches the `def.token`.
   */
  function getOwnDefinition(type, def) {
      return def && def.token === type ? def : 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 v10, where an error will occur in the scenario if we find the
   * `ɵprov` on an ancestor only.
   */
  function getInheritedInjectableDef(type) {
      // See `jit/injectable.ts#compileInjectable` for context on NG_PROV_DEF_FALLBACK.
      var def = type &&
          (type[NG_PROV_DEF] || type[NG_INJECTABLE_DEF] ||
              (type[NG_PROV_DEF_FALLBACK] && type[NG_PROV_DEF_FALLBACK]()));
      if (def) {
          var 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 v10. 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;
      }
      var 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;
  }
  var NG_PROV_DEF = getClosureSafeProperty({ ɵprov: getClosureSafeProperty });
  var NG_INJ_DEF = getClosureSafeProperty({ ɵinj: getClosureSafeProperty });
  // On IE10 properties defined via `defineProperty` won't be inherited by child classes,
  // which will break inheriting the injectable definition from a grandparent through an
  // undecorated parent class. We work around it by defining a fallback method which will be
  // used to retrieve the definition. This should only be a problem in JIT mode, because in
  // AOT TypeScript seems to have a workaround for static properties. When inheriting from an
  // undecorated parent is no longer supported in v10, this can safely be removed.
  var NG_PROV_DEF_FALLBACK = getClosureSafeProperty({ ɵprovFallback: getClosureSafeProperty });
  // We need to keep these around so we can read off old defs if new defs are unavailable
  var NG_INJECTABLE_DEF = getClosureSafeProperty({ ngInjectableDef: getClosureSafeProperty });
  var NG_INJECTOR_DEF = getClosureSafeProperty({ ngInjectorDef: getClosureSafeProperty });

  /**
   * @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
   */
  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;
      }
      var res = token.toString();
      if (res == null) {
          return '' + res;
      }
      var 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 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
   */
  var __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 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
   */
  var __globalThis = typeof globalThis !== 'undefined' && globalThis;
  var __window = typeof window !== 'undefined' && window;
  var __self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
      self instanceof WorkerGlobalScope && self;
  var __global = typeof global !== 'undefined' && global;
  // 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.
  var _global = __globalThis || __global || __window || __self;

  /**
   * @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
   */
  var R3ResolvedDependencyType;
  (function (R3ResolvedDependencyType) {
      R3ResolvedDependencyType[R3ResolvedDependencyType["Token"] = 0] = "Token";
      R3ResolvedDependencyType[R3ResolvedDependencyType["Attribute"] = 1] = "Attribute";
      R3ResolvedDependencyType[R3ResolvedDependencyType["ChangeDetectorRef"] = 2] = "ChangeDetectorRef";
      R3ResolvedDependencyType[R3ResolvedDependencyType["Invalid"] = 3] = "Invalid";
  })(R3ResolvedDependencyType || (R3ResolvedDependencyType = {}));
  var R3FactoryTarget;
  (function (R3FactoryTarget) {
      R3FactoryTarget[R3FactoryTarget["Directive"] = 0] = "Directive";
      R3FactoryTarget[R3FactoryTarget["Component"] = 1] = "Component";
      R3FactoryTarget[R3FactoryTarget["Injectable"] = 2] = "Injectable";
      R3FactoryTarget[R3FactoryTarget["Pipe"] = 3] = "Pipe";
      R3FactoryTarget[R3FactoryTarget["NgModule"] = 4] = "NgModule";
  })(R3FactoryTarget || (R3FactoryTarget = {}));
  var ViewEncapsulation;
  (function (ViewEncapsulation) {
      ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
      ViewEncapsulation[ViewEncapsulation["Native"] = 1] = "Native";
      ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
      ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
  })(ViewEncapsulation || (ViewEncapsulation = {}));

  /**
   * @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
   */
  function getCompilerFacade() {
      var globalNg = _global['ng'];
      if (!globalNg || !globalNg.ɵcompilerFacade) {
          throw new Error("Angular JIT compilation failed: '@angular/compiler' not loaded!\n" +
              "  - JIT compilation is discouraged for production use-cases! Consider AOT mode instead.\n" +
              "  - Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?\n" +
              "  - Alternatively provide the compiler with 'import \"@angular/compiler\";' before bootstrapping.");
      }
      return globalNg.ɵcompilerFacade;
  }

  /**
   * @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
   */
  var NG_COMP_DEF = getClosureSafeProperty({ ɵcmp: getClosureSafeProperty });
  var NG_DIR_DEF = getClosureSafeProperty({ ɵdir: getClosureSafeProperty });
  var NG_PIPE_DEF = getClosureSafeProperty({ ɵpipe: getClosureSafeProperty });
  var NG_MOD_DEF = getClosureSafeProperty({ ɵmod: getClosureSafeProperty });
  var NG_LOC_ID_DEF = getClosureSafeProperty({ ɵloc: getClosureSafeProperty });
  var 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.
  var NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });

  /**
   * @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
   */
  function ngDevModeResetPerfCounters() {
      var locationString = typeof location !== 'undefined' ? location.toString() : '';
      var 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.
      var 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 using 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 !!ngDevMode;
      }
      return false;
  }

  /**
   * @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
   */
  /**
   * 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 additional level of type safety.
   *
   * ```
   * interface MyInterface {...}
   * var 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. See below for an example.
   *
   * 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 Example
   *
   * ### Plain InjectionToken
   *
   * {@example core/di/ts/injector_spec.ts region='InjectionToken'}
   *
   * ### Tree-shakable InjectionToken
   *
   * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
   *
   *
   * @publicApi
   */
  var InjectionToken = /** @class */ (function () {
      function InjectionToken(_desc, options) {
          this._desc = _desc;
          /** @internal */
          this.ngMetadataName = 'InjectionToken';
          this.ɵprov = undefined;
          if (typeof options == 'number') {
              // This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
              // __NG_ELEMENT_ID__ is Used by Ivy to determine bloom filter id.
              // We are using it to assign `-1` which is used to identify `Injector`.
              this.__NG_ELEMENT_ID__ = options;
          }
          else if (options !== undefined) {
              this.ɵprov = ɵɵdefineInjectable({
                  token: this,
                  providedIn: options.providedIn || 'root',
                  factory: options.factory,
              });
          }
      }
      InjectionToken.prototype.toString = function () {
          return "InjectionToken " + this._desc;
      };
      return InjectionToken;
  }());

  /**
   * @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
   */
  /**
   * 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
   */
  var INJECTOR = new InjectionToken('INJECTOR', -1 // `-1` is used by Ivy DI system as special value to recognize it as `Injector`.
  );
  var _THROW_IF_NOT_FOUND = {};
  var THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
  var NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
  var NG_TOKEN_PATH = 'ngTokenPath';
  var NEW_LINE = /\n/gm;
  var NO_NEW_LINE = 'ɵ';
  var SOURCE = '__source';
  var ɵ0$1 = getClosureSafeProperty;
  var USE_VALUE = getClosureSafeProperty({ provide: String, useValue: ɵ0$1 });
  /**
   * 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.
   */
  var _currentInjector = undefined;
  function setCurrentInjector(injector) {
      var former = _currentInjector;
      _currentInjector = injector;
      return former;
  }
  /**
   * 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.
   */
  var _injectImplementation;
  /**
   * Sets the current inject implementation.
   */
  function setInjectImplementation(impl) {
      var previous = _injectImplementation;
      _injectImplementation = impl;
      return previous;
  }
  function injectInjectorOnly(token, flags) {
      if (flags === void 0) { flags = exports.InjectFlags.Default; }
      if (_currentInjector === undefined) {
          throw new Error("inject() must be called from an injection context");
      }
      else if (_currentInjector === null) {
          return injectRootLimpMode(token, undefined, flags);
      }
      else {
          return _currentInjector.get(token, flags & exports.InjectFlags.Optional ? null : undefined, flags);
      }
  }
  function ɵɵinject(token, flags) {
      if (flags === void 0) { flags = exports.InjectFlags.Default; }
      return (_injectImplementation || injectInjectorOnly)(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 ɵɵinvalidFactoryDep(index) {
      var msg = ngDevMode ?
          "This constructor is not compatible with Angular Dependency Injection because its dependency at index " + index + " of the parameter list is invalid.\nThis can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.\n\nPlease 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." :
          'invalid';
      throw new Error(msg);
  }
  /**
   * Injects a token from the currently active injector.
   *
   * Must be used in the context of a factory function such as one defined for an
   * `InjectionToken`. Throws an error if not called from such a context.
   *
   * Within such a factory function, using this function to request injection of a dependency
   * is faster and more type-safe than providing an additional array of dependencies
   * (as has been common with `useFactory` providers).
   *
   * @param token The injection token for the dependency to 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 True if injection is successful, null otherwise.
   *
   * @usageNotes
   *
   * ### Example
   *
   * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
   *
   * @publicApi
   */
  var inject = ɵɵinject;
  /**
   * 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
   * `InjectableDef`.
   */
  function injectRootLimpMode(token, notFoundValue, flags) {
      var injectableDef = getInjectableDef(token);
      if (injectableDef && injectableDef.providedIn == 'root') {
          return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :
              injectableDef.value;
      }
      if (flags & exports.InjectFlags.Optional)
          return null;
      if (notFoundValue !== undefined)
          return notFoundValue;
      throw new Error("Injector: NOT_FOUND [" + stringify(token) + "]");
  }
  function injectArgs(types) {
      var args = [];
      for (var i = 0; i < types.length; i++) {
          var arg = resolveForwardRef(types[i]);
          if (Array.isArray(arg)) {
              if (arg.length === 0) {
                  throw new Error('Arguments array must have arguments.');
              }
              var type = undefined;
              var flags = exports.InjectFlags.Default;
              for (var j = 0; j < arg.length; j++) {
                  var meta = arg[j];
                  if (meta instanceof Optional || meta.ngMetadataName === 'Optional' || meta === Optional) {
                      flags |= exports.InjectFlags.Optional;
                  }
                  else if (meta instanceof SkipSelf || meta.ngMetadataName === 'SkipSelf' || meta === SkipSelf) {
                      flags |= exports.InjectFlags.SkipSelf;
                  }
                  else if (meta instanceof Self || meta.ngMetadataName === 'Self' || meta === Self) {
                      flags |= exports.InjectFlags.Self;
                  }
                  else if (meta instanceof Inject || meta === Inject) {
                      type = meta.token;
                  }
                  else {
                      type = meta;
                  }
              }
              args.push(ɵɵinject(type, flags));
          }
          else {
              args.push(ɵɵinject(arg));
          }
      }
      return args;
  }
  var NullInjector = /** @class */ (function () {
      function NullInjector() {
      }
      NullInjector.prototype.get = function (token, notFoundValue) {
          if (notFoundValue === void 0) { notFoundValue = THROW_IF_NOT_FOUND; }
          if (notFoundValue === THROW_IF_NOT_FOUND) {
              // Intentionally left behind: With dev tools open the debugger will stop here. There is no
              // reason why correctly written application should cause this exception.
              // TODO(misko): uncomment the next line once `ngDevMode` works with closure.
              // if (ngDevMode) debugger;
              var error = new Error("NullInjectorError: No provider for " + stringify(token) + "!");
              error.name = 'NullInjectorError';
              throw error;
          }
          return notFoundValue;
      };
      return NullInjector;
  }());
  function catchInjectorError(e, token, injectorErrorName, source) {
      var 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) {
      if (source === void 0) { source = null; }
      text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE ? text.substr(2) : text;
      var context = stringify(obj);
      if (Array.isArray(obj)) {
          context = obj.map(stringify).join(' -> ');
      }
      else if (typeof obj === 'object') {
          var parts = [];
          for (var key in obj) {
              if (obj.hasOwnProperty(key)) {
                  var 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 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
   */
  /**
   * 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.
   */
  var angularCoreDiEnv = {
      'ɵɵdefineInjectable': ɵɵdefineInjectable,
      'ɵɵdefineInjector': ɵɵdefineInjector,
      'ɵɵinject': ɵɵinject,
      'ɵɵgetFactoryOf': getFactoryOf,
      'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
  };
  function getFactoryOf(type) {
      var typeAny = type;
      if (isForwardRef(type)) {
          return (function () {
              var factory = getFactoryOf(resolveForwardRef(typeAny));
              return factory ? factory() : null;
          });
      }
      var def = getInjectableDef(typeAny) || getInjectorDef(typeAny);
      if (!def || def.factory === undefined) {
          return null;
      }
      return def.factory;
  }

  /**
   * @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
   */
  /**
   * Represents an instance of an NgModule created via a {@link NgModuleFactory}.
   *
   * `NgModuleRef` provides access to the NgModule Instance as well other objects related to this
   * NgModule Instance.
   *
   * @publicApi
   */
  var NgModuleRef = /** @class */ (function () {
      function NgModuleRef() {
      }
      return NgModuleRef;
  }());
  /**
   * @publicApi
   */
  var NgModuleFactory = /** @class */ (function () {
      function NgModuleFactory() {
      }
      return NgModuleFactory;
  }());

  /**
   * @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
   */
  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 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.
      assertEqual((typeof Node !== 'undefined' && node instanceof Node) ||
          (typeof node === 'object' && node != null &&
              node.constructor.name === 'WebWorkerRenderNode'), true, "The provided value must be an instance of a DOM Node but got " + stringify(node));
  }
  function assertDataInRange(arr, index) {
      var maxLen = arr ? arr.length : 0;
      assertLessThan(index, maxLen, "Index expected to be less than " + maxLen + " but got " + index);
  }

  /**
   * @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
   */
  /**
   * 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 (var i = 0; i < items.length; i++) {
          arr.push(items[i]);
      }
  }
  /**
   * Flattens an array.
   */
  function flatten(list, dst) {
      if (dst === undefined)
          dst = list;
      for (var i = 0; i < list.length; i++) {
          var 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(function (value) { return 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) {
      var list = [];
      for (var 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) {
      var 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.');
      var end = array.length;
      while (end > index) {
          var 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.');
      var 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) {
              var 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) {
      var 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) {
      var 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) {
      var 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) {
      var 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) {
      var 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');
      var start = 0;
      var end = array.length >> shift;
      while (end !== start) {
          var middle = start + ((end - start) >> 1); // find the middle.
          var 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 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
   */
  (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";
  })(exports.ChangeDetectionStrategy || (exports.ChangeDetectionStrategy = {}));
  (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";
  })(exports.ɵChangeDetectorStatus || (exports.ɵ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 === exports.ChangeDetectionStrategy.Default;
  }

  /**
   * @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
   */
  (function (ViewEncapsulation) {
      /**
       * Emulate `Native` scoping of styles by adding an attribute containing surrogate id to the Host
       * Element and pre-processing the style rules provided via {@link Component#styles styles} or
       * {@link Component#styleUrls styleUrls}, and adding the new Host Element attribute to all
       * selectors.
       *
       * This is the default option.
       */
      ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
      /**
       * @deprecated v6.1.0 - use {ViewEncapsulation.ShadowDom} instead.
       * Use the native encapsulation mechanism of the renderer.
       *
       * For the DOM this means using the deprecated [Shadow DOM
       * v0](https://w3c.github.io/webcomponents/spec/shadow/) and
       * creating a ShadowRoot for Component's Host Element.
       */
      ViewEncapsulation[ViewEncapsulation["Native"] = 1] = "Native";
      /**
       * Don't provide any template or style encapsulation.
       */
      ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
      /**
       * Use Shadow DOM to encapsulate styles.
       *
       * For the DOM this means using modern [Shadow
       * DOM](https://w3c.github.io/webcomponents/spec/shadow/) and
       * creating a ShadowRoot for Component's Host Element.
       */
      ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
  })(exports.ViewEncapsulation || (exports.ViewEncapsulation = {}));

  /**
   * @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
   */
  /**
   * 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.
   */
  var EMPTY_OBJ = {};
  var 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 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
   */
  var _renderCompCount = 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(function () {
          // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent.
          // See the `initNgDevMode` docstring for more information.
          (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
          var type = componentDefinition.type;
          var typePrototype = type.prototype;
          var declaredInputs = {};
          var 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,
              onChanges: null,
              onInit: typePrototype.ngOnInit || null,
              doCheck: typePrototype.ngDoCheck || null,
              afterContentInit: typePrototype.ngAfterContentInit || null,
              afterContentChecked: typePrototype.ngAfterContentChecked || null,
              afterViewInit: typePrototype.ngAfterViewInit || null,
              afterViewChecked: typePrototype.ngAfterViewChecked || null,
              onDestroy: typePrototype.ngOnDestroy || null,
              onPush: componentDefinition.changeDetection === exports.ChangeDetectionStrategy.OnPush,
              directiveDefs: null,
              pipeDefs: null,
              selectors: componentDefinition.selectors || EMPTY_ARRAY,
              viewQuery: componentDefinition.viewQuery || null,
              features: componentDefinition.features || null,
              data: componentDefinition.data || {},
              // TODO(misko): convert ViewEncapsulation into const enum so that it can be used directly in
              // the next line. Also `None` should be 0 not 2.
              encapsulation: componentDefinition.encapsulation || exports.ViewEncapsulation.Emulated,
              id: 'c',
              styles: componentDefinition.styles || EMPTY_ARRAY,
              _: null,
              setInput: null,
              schemas: componentDefinition.schemas || null,
              tView: null,
          };
          var directiveTypes = componentDefinition.directives;
          var feature = componentDefinition.features;
          var pipeTypes = componentDefinition.pipes;
          def.id += _renderCompCount++;
          def.inputs = invertObject(componentDefinition.inputs, declaredInputs),
              def.outputs = invertObject(componentDefinition.outputs),
              feature && feature.forEach(function (fn) { return fn(def); });
          def.directiveDefs = directiveTypes ?
              function () { return (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
                  .map(extractDirectiveDef); } :
              null;
          def.pipeDefs = pipeTypes ?
              function () { return (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef); } :
              null;
          return def;
      });
  }
  /**
   * @codeGenApi
   */
  function ɵɵsetComponentScope(type, directives, pipes) {
      var def = type.ɵcmp;
      def.directiveDefs = function () { return directives.map(extractDirectiveDef); };
      def.pipeDefs = function () { return pipes.map(extractPipeDef); };
  }
  function extractDirectiveDef(type) {
      var def = getComponentDef(type) || getDirectiveDef(type);
      if (ngDevMode && !def) {
          throw new Error("'" + type.name + "' is neither 'ComponentType' or 'DirectiveType'.");
      }
      return def;
  }
  function extractPipeDef(type) {
      var def = getPipeDef(type);
      if (ngDevMode && !def) {
          throw new Error("'" + type.name + "' is not a 'PipeType'.");
      }
      return def;
  }
  var autoRegisterModuleById = {};
  /**
   * @codeGenApi
   */
  function ɵɵdefineNgModule(def) {
      var 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,
      };
      if (def.id != null) {
          noSideEffects(function () {
              autoRegisterModuleById[def.id] = def.type;
          });
      }
      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(function () {
          var 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;
      var newLookup = {};
      for (var minifiedKey in obj) {
          if (obj.hasOwnProperty(minifiedKey)) {
              var publicName = obj[minifiedKey];
              var 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
   */
  var ɵɵ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,
          onDestroy: pipeDef.type.prototype.ngOnDestroy || null
      };
  }
  /**
   * The following getter methods retrieve the definition form 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(type) {
      return type[NG_PIPE_DEF] || null;
  }
  function getFactoryDef(type, throwNotFound) {
      var hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF);
      if (!hasFactoryDef && throwNotFound === true && ngDevMode) {
          throw new Error("Type " + stringify(type) + " does not have '\u0275fac' property.");
      }
      return hasFactoryDef ? type[NG_FACTORY_DEF] : null;
  }
  function getNgModuleDef(type, throwNotFound) {
      var ngModuleDef = type[NG_MOD_DEF] || null;
      if (!ngModuleDef && throwNotFound === true) {
          throw new Error("Type " + stringify(type) + " does not have '\u0275mod' property.");
      }
      return ngModuleDef;
  }
  function getNgLocaleIdDef(type) {
      return type[NG_LOC_ID_DEF] || null;
  }

  /**
   * @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
   */
  // 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.
  var HOST = 0;
  var TVIEW = 1;
  var FLAGS = 2;
  var PARENT = 3;
  var NEXT = 4;
  var TRANSPLANTED_VIEWS_TO_REFRESH = 5;
  var T_HOST = 6;
  var CLEANUP = 7;
  var CONTEXT = 8;
  var INJECTOR$1 = 9;
  var RENDERER_FACTORY = 10;
  var RENDERER = 11;
  var SANITIZER = 12;
  var CHILD_HEAD = 13;
  var CHILD_TAIL = 14;
  var DECLARATION_VIEW = 15;
  var DECLARATION_COMPONENT_VIEW = 16;
  var DECLARATION_LCONTAINER = 17;
  var PREORDER_HOOK_FLAGS = 18;
  var QUERIES = 19;
  /** Size of LView's header. Necessary to adjust for it when setting slots.  */
  var HEADER_OFFSET = 20;
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd = 1;

  /**
   * @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
   */
  /**
   * 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`.
   */
  var 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.
   */
  var ACTIVE_INDEX = 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.
  var NATIVE = 7;
  var VIEW_REFS = 8;
  var 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.
   */
  var CONTAINER_HEADER_OFFSET = 10;
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$1 = 1;

  /**
   * @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
   */
  /**
   * 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 /* hasContentQuery */) !== 0;
  }
  function isComponentHost(tNode) {
      return (tNode.flags & 2 /* isComponentHost */) === 2 /* isComponentHost */;
  }
  function isDirectiveHost(tNode) {
      return (tNode.flags & 1 /* isDirectiveHost */) === 1 /* isDirectiveHost */;
  }
  function isComponentDef(def) {
      return def.template !== null;
  }
  function isRootView(target) {
      return (target[FLAGS] & 512 /* IsRoot */) !== 0;
  }

  /**
   * @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
   */
  // [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) {
      tNode.hasOwnProperty('tView_') &&
          assertEqual(tNode.tView_, lView[TVIEW], 'This TNode does not belong to this LView.');
  }
  function assertComponentType(actual, msg) {
      if (msg === void 0) { msg = 'Type passed in is not ComponentType, it does not have \'ɵcmp\' property.'; }
      if (!getComponentDef(actual)) {
          throwError(msg);
      }
  }
  function assertNgModuleType(actual, msg) {
      if (msg === void 0) { msg = 'Type passed in is not NgModuleType, it does not have \'ɵmod\' property.'; }
      if (!getNgModuleDef(actual)) {
          throwError(msg);
      }
  }
  function assertPreviousIsParent(isParent) {
      assertEqual(isParent, true, 'previousOrParentTNode should be a parent');
  }
  function assertHasParent(tNode) {
      assertDefined(tNode, 'previousOrParentTNode should exist!');
      assertDefined(tNode.parent, 'previousOrParentTNode 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.");
      }
  }

  /**
   * @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
   */
  var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
  var MATH_ML_NAMESPACE = 'http://www.w3.org/1998/MathML/';

  /**
   * @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
   */
  /**
   * This property will be monkey-patched on elements, components and directives
   */
  var MONKEY_PATCH_KEY_NAME = '__ngContext__';

  /**
   * @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
   */
  /**
   * 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.
   */
  var 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 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
   */
  // TODO: cleanup once the code is merged in angular/angular
  var RendererStyleFlags3;
  (function (RendererStyleFlags3) {
      RendererStyleFlags3[RendererStyleFlags3["Important"] = 1] = "Important";
      RendererStyleFlags3[RendererStyleFlags3["DashCase"] = 2] = "DashCase";
  })(RendererStyleFlags3 || (RendererStyleFlags3 = {}));
  /** Returns whether the `renderer` is a `ProceduralRenderer3` */
  function isProceduralRenderer(renderer) {
      return !!(renderer.listen);
  }
  var ɵ0$2 = function (hostElement, rendererType) {
      return getDocument();
  };
  var domRendererFactory3 = {
      createRenderer: ɵ0$2
  };
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$2 = 1;

  /**
   * @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
   */
  /**
   * 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) {
      return unwrapRNode(lView[index + HEADER_OFFSET]);
  }
  /**
   * 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 && assertDataInRange(lView, tNode.index);
      var node = unwrapRNode(lView[tNode.index]);
      ngDevMode && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
      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) {
      var index = tNode.index;
      if (index !== -1) {
          ngDevMode && assertTNodeForLView(tNode, lView);
          var node = unwrapRNode(lView[index]);
          ngDevMode && node !== null && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
          return node;
      }
      return null;
  }
  function getTNode(tView, index) {
      ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
      ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
      return tView.data[index + HEADER_OFFSET];
  }
  /** Retrieves a value from any `LView` or `TData`. */
  function load(view, index) {
      ngDevMode && assertDataInRange(view, index + HEADER_OFFSET);
      return view[index + HEADER_OFFSET];
  }
  function getComponentLViewByIndex(nodeIndex, hostView) {
      // Could be an LView or an LContainer. If LContainer, unwrap to find LView.
      ngDevMode && assertDataInRange(hostView, nodeIndex);
      var slotValue = hostView[nodeIndex];
      var lView = isLView(slotValue) ? slotValue : slotValue[HOST];
      return lView;
  }
  /**
   * 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');
      return target[MONKEY_PATCH_KEY_NAME] || null;
  }
  function readPatchedLView(target) {
      var value = readPatchedData(target);
      if (value) {
          return Array.isArray(value) ? value : value.lView;
      }
      return null;
  }
  /** Checks whether a given view is in creation mode */
  function isCreationMode(view) {
      return (view[FLAGS] & 4 /* CreationMode */) === 4 /* 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] & 128 /* Attached */) === 128 /* Attached */;
  }
  /** Returns a boolean for whether the view is attached to a container. */
  function viewAttachedToContainer(view) {
      return isLContainer(view[PARENT]);
  }
  /** Returns a constant from `TConstants` instance. */
  function getConstant(consts, index) {
      return consts === null || index == null ? null : 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;
  }
  function getLContainerActiveIndex(lContainer) {
      return lContainer[ACTIVE_INDEX] >> 1 /* SHIFT */;
  }
  function setLContainerActiveIndex(lContainer, index) {
      lContainer[ACTIVE_INDEX] = index << 1 /* SHIFT */;
  }
  /**
   * 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;
      var viewOrContainer = lContainer;
      var 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 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
   */
  var instructionState = {
      lFrame: createLFrame(null),
      bindingsEnabled: true,
      checkNoChangesMode: false,
  };
  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.
   *
   * @codeGenApi
   */
  function ɵɵrestoreView(viewToRestore) {
      instructionState.lFrame.contextLView = viewToRestore;
  }
  function getPreviousOrParentTNode() {
      return instructionState.lFrame.previousOrParentTNode;
  }
  function setPreviousOrParentTNode(tNode, isParent) {
      instructionState.lFrame.previousOrParentTNode = tNode;
      instructionState.lFrame.isParent = isParent;
  }
  function getIsParent() {
      return instructionState.lFrame.isParent;
  }
  function setIsNotParent() {
      instructionState.lFrame.isParent = false;
  }
  function setIsParent() {
      instructionState.lFrame.isParent = true;
  }
  function getContextLView() {
      return instructionState.lFrame.contextLView;
  }
  function getCheckNoChangesMode() {
      // TODO(misko): remove this from the LView since it is ngDevMode=true mode only.
      return instructionState.checkNoChangesMode;
  }
  function setCheckNoChangesMode(mode) {
      instructionState.checkNoChangesMode = mode;
  }
  // top level variables should not be exported for performance reasons (PERF_NOTES.md)
  function getBindingRoot() {
      var lFrame = instructionState.lFrame;
      var 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) {
      var lFrame = instructionState.lFrame;
      var index = lFrame.bindingIndex;
      lFrame.bindingIndex = lFrame.bindingIndex + count;
      return index;
  }
  /**
   * 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) {
      var 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) {
      var currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex;
      return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex];
  }
  function getCurrentQueryIndex() {
      return instructionState.lFrame.currentQueryIndex;
  }
  function setCurrentQueryIndex(value) {
      instructionState.lFrame.currentQueryIndex = value;
  }
  /**
   * This is a light weight version of the `enterView` which is needed by the DI system.
   * @param newView
   * @param tNode
   */
  function enterDI(newView, tNode) {
      ngDevMode && assertLViewOrUndefined(newView);
      var newLFrame = allocLFrame();
      instructionState.lFrame = newLFrame;
      newLFrame.previousOrParentTNode = tNode;
      newLFrame.lView = newView;
  }
  /**
   * 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
   * @param tNode Element to which the View is a child of
   * @returns the previously active lView;
   */
  function enterView(newView, tNode) {
      ngDevMode && assertLViewOrUndefined(newView);
      var 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, 0, '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.currentSanitizer, null, 'Expected clean LFrame');
          assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame');
          assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame');
      }
      var tView = newView[TVIEW];
      instructionState.lFrame = newLFrame;
      newLFrame.previousOrParentTNode = tNode;
      newLFrame.lView = newView;
      newLFrame.tView = tView;
      newLFrame.contextLView = newView;
      newLFrame.bindingIndex = tView.bindingStartIndex;
  }
  /**
   * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.
   */
  function allocLFrame() {
      var currentLFrame = instructionState.lFrame;
      var childLFrame = currentLFrame === null ? null : currentLFrame.child;
      var newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;
      return newLFrame;
  }
  function createLFrame(parent) {
      var lFrame = {
          previousOrParentTNode: null,
          isParent: true,
          lView: null,
          tView: null,
          selectedIndex: 0,
          contextLView: null,
          elementDepthCount: 0,
          currentNamespace: null,
          currentSanitizer: null,
          currentDirectiveIndex: -1,
          bindingRootIndex: -1,
          bindingIndex: -1,
          currentQueryIndex: 0,
          parent: parent,
          child: null,
      };
      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 `previousOrParentTNode` 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() {
      var oldLFrame = instructionState.lFrame;
      instructionState.lFrame = oldLFrame.parent;
      oldLFrame.previousOrParentTNode = 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.
   */
  var 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() {
      var oldLFrame = leaveViewLight();
      oldLFrame.isParent = true;
      oldLFrame.tView = null;
      oldLFrame.selectedIndex = 0;
      oldLFrame.contextLView = null;
      oldLFrame.elementDepthCount = 0;
      oldLFrame.currentDirectiveIndex = -1;
      oldLFrame.currentNamespace = null;
      oldLFrame.currentSanitizer = null;
      oldLFrame.bindingRootIndex = -1;
      oldLFrame.bindingIndex = -1;
      oldLFrame.currentQueryIndex = 0;
  }
  function nextContextImpl(level) {
      var 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) {
      instructionState.lFrame.selectedIndex = index;
  }
  /**
   * Gets the `tNode` that represents currently selected element.
   */
  function getSelectedTNode() {
      var 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() {
      return instructionState.lFrame.currentNamespace;
  }
  function setCurrentStyleSanitizer(sanitizer) {
      instructionState.lFrame.currentSanitizer = sanitizer;
  }
  function resetCurrentStyleSanitizer() {
      setCurrentStyleSanitizer(null);
  }
  function getCurrentStyleSanitizer() {
      // TODO(misko): This should throw when there is no LView, but it turns out we can get here from
      // `NodeStyleDebug` hence we return `null`. This should be fixed
      var lFrame = instructionState.lFrame;
      return lFrame === null ? null : lFrame.currentSanitizer;
  }

  /**
   * @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
   */
  /**
   * 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);
      var onChanges = directiveDef.onChanges, onInit = directiveDef.onInit, doCheck = directiveDef.doCheck;
      if (onChanges) {
          (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, onChanges);
          (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, onChanges);
      }
      if (onInit) {
          (tView.preOrderHooks || (tView.preOrderHooks = [])).push(-directiveIndex, onInit);
      }
      if (doCheck) {
          (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, doCheck);
          (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, doCheck);
      }
  }
  /**
   *
   * 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 (var i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) {
          var directiveDef = tView.data[i];
          if (directiveDef.afterContentInit) {
              (tView.contentHooks || (tView.contentHooks = [])).push(-i, directiveDef.afterContentInit);
          }
          if (directiveDef.afterContentChecked) {
              (tView.contentHooks || (tView.contentHooks = [])).push(i, directiveDef.afterContentChecked);
              (tView.contentCheckHooks || (tView.contentCheckHooks = []))
                  .push(i, directiveDef.afterContentChecked);
          }
          if (directiveDef.afterViewInit) {
              (tView.viewHooks || (tView.viewHooks = [])).push(-i, directiveDef.afterViewInit);
          }
          if (directiveDef.afterViewChecked) {
              (tView.viewHooks || (tView.viewHooks = [])).push(i, directiveDef.afterViewChecked);
              (tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, directiveDef.afterViewChecked);
          }
          if (directiveDef.onDestroy != null) {
              (tView.destroyHooks || (tView.destroyHooks = [])).push(i, directiveDef.onDestroy);
          }
      }
  }
  /**
   * 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 /* 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 /* InitPhaseCompleted */, 'Init pre-order hooks should not be called more than once');
      if ((lView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
          callHooks(lView, hooks, initPhase, nodeIndex);
      }
  }
  function incrementInitPhaseFlags(lView, initPhase) {
      ngDevMode &&
          assertNotEqual(initPhase, 3 /* InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');
      var flags = lView[FLAGS];
      if ((flags & 3 /* InitPhaseStateMask */) === initPhase) {
          flags &= 2047 /* IndexWithinInitPhaseReset */;
          flags += 1 /* 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(getCheckNoChangesMode(), false, 'Hooks should never be run in the check no changes mode.');
      var startIndex = currentNodeIndex !== undefined ?
          (currentView[PREORDER_HOOK_FLAGS] & 65535 /* IndexOfTheNextPreOrderHookMaskMask */) :
          0;
      var nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;
      var lastNodeIndexFound = 0;
      for (var i = startIndex; i < arr.length; i++) {
          var hook = arr[i + 1];
          if (typeof hook === 'number') {
              lastNodeIndexFound = arr[i];
              if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) {
                  break;
              }
          }
          else {
              var isInitHook = arr[i] < 0;
              if (isInitHook)
                  currentView[PREORDER_HOOK_FLAGS] += 65536 /* NumberOfInitHooksCalledIncrementer */;
              if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {
                  callHook(currentView, initPhase, arr, i);
                  currentView[PREORDER_HOOK_FLAGS] =
                      (currentView[PREORDER_HOOK_FLAGS] & 4294901760 /* 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) {
      var isInitHook = arr[i] < 0;
      var hook = arr[i + 1];
      var directiveIndex = isInitHook ? -arr[i] : arr[i];
      var directive = currentView[directiveIndex];
      if (isInitHook) {
          var indexWithintInitPhase = currentView[FLAGS] >> 11 /* IndexWithinInitPhaseShift */;
          // The init phase state must be always checked here as it may have been recursively
          // updated
          if (indexWithintInitPhase <
              (currentView[PREORDER_HOOK_FLAGS] >> 16 /* NumberOfInitHooksCalledShift */) &&
              (currentView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
              currentView[FLAGS] += 2048 /* IndexWithinInitPhaseIncrementer */;
              hook.call(directive);
          }
      }
      else {
          hook.call(directive);
      }
  }

  /**
   * @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
   */
  var TNODE = 8;
  var PARENT_INJECTOR = 8;
  var INJECTOR_BLOOM_PARENT_SIZE = 9;
  var 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`.
   */
  var NodeInjectorFactory = /** @class */ (function () {
      function NodeInjectorFactory(
      /**
       * 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;
          this.canSeeViewProviders = isViewProvider;
          this.injectImpl = injectImplementation;
      }
      return NodeInjectorFactory;
  }());
  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.
  var unusedValueExportToPlacateAjd$3 = 1;

  /**
   * @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
   */
  function assertNodeType(tNode, type) {
      assertDefined(tNode, 'should be called with a TNode');
      assertEqual(tNode.type, type, "should be a " + typeName(type));
  }
  function assertNodeOfPossibleTypes(tNode) {
      var types = [];
      for (var _i = 1; _i < arguments.length; _i++) {
          types[_i - 1] = arguments[_i];
      }
      assertDefined(tNode, 'should be called with a TNode');
      var found = types.some(function (type) { return tNode.type === type; });
      assertEqual(found, true, "Should be one of " + types.map(typeName).join(', ') + " but got " + typeName(tNode.type));
  }
  function typeName(type) {
      if (type == 1 /* Projection */)
          return 'Projection';
      if (type == 0 /* Container */)
          return 'Container';
      if (type == 5 /* IcuContainer */)
          return 'IcuContainer';
      if (type == 2 /* View */)
          return 'View';
      if (type == 3 /* Element */)
          return 'Element';
      if (type == 4 /* ElementContainer */)
          return 'ElementContainer';
      return '<unknown>';
  }

  /**
   * 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) {
      var isProc = isProceduralRenderer(renderer);
      var i = 0;
      while (i < attrs.length) {
          var 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 /* NamespaceURI */) {
                  break;
              }
              // we just landed on the marker value ... therefore
              // we should skip to the next entry
              i++;
              var namespaceURI = attrs[i++];
              var attrName = attrs[i++];
              var attrVal = attrs[i++];
              ngDevMode && ngDevMode.rendererSetAttribute++;
              isProc ?
                  renderer.setAttribute(native, attrName, attrVal, namespaceURI) :
                  native.setAttributeNS(namespaceURI, attrName, attrVal);
          }
          else {
              // attrName is string;
              var attrName = value;
              var attrVal = attrs[++i];
              // Standard attributes
              ngDevMode && ngDevMode.rendererSetAttribute++;
              if (isAnimationProp(attrName)) {
                  if (isProc) {
                      renderer.setProperty(native, attrName, attrVal);
                  }
              }
              else {
                  isProc ?
                      renderer.setAttribute(native, attrName, attrVal) :
                      native.setAttribute(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 /* Bindings */ || marker === 4 /* Template */ ||
          marker === 6 /* 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 /* 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 {
          var srcMarker = -1 /* ImplicitAttributes */;
          for (var i = 0; i < src.length; i++) {
              var item = src[i];
              if (typeof item === 'number') {
                  srcMarker = item;
              }
              else {
                  if (srcMarker === 0 /* NamespaceURI */) {
                      // Case where we need to consume `key1`, `key2`, `value` items.
                  }
                  else if (srcMarker === -1 /* ImplicitAttributes */ ||
                      srcMarker === 2 /* 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) {
      var i = 0;
      // Assume that new markers will be inserted at the end.
      var markerInsertPosition = dst.length;
      // scan until correct type.
      if (marker === -1 /* ImplicitAttributes */) {
          markerInsertPosition = -1;
      }
      else {
          while (i < dst.length) {
              var 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) {
          var 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 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
   */
  /// Parent Injector Utils ///////////////////////////////////////////////////////////////
  function hasParentInjector(parentLocation) {
      return parentLocation !== NO_PARENT_INJECTOR;
  }
  function getParentInjectorIndex(parentLocation) {
      return parentLocation & 32767 /* InjectorIndexMask */;
  }
  function getParentInjectorViewOffset(parentLocation) {
      return parentLocation >> 16 /* 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) {
      var viewOffset = getParentInjectorViewOffset(location);
      var 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 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
   */
  /**
   * 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.
   */
  function renderStringify(value) {
      if (typeof value === 'string')
          return value;
      if (value == null)
          return '';
      return '' + 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);
  }
  var ɵ0$3 = function () { return (typeof requestAnimationFrame !== 'undefined' &&
      requestAnimationFrame || // browser only
      setTimeout // everything else
  )
      .bind(_global); };
  var defaultScheduler = (ɵ0$3)();
  /**
   *
   * @codeGenApi
   */
  function ɵɵresolveWindow(element) {
      return { name: 'window', target: element.ownerDocument.defaultView };
  }
  /**
   *
   * @codeGenApi
   */
  function ɵɵresolveDocument(element) {
      return { name: 'document', target: element.ownerDocument };
  }
  /**
   *
   * @codeGenApi
   */
  function ɵɵresolveBody(element) {
      return { name: 'body', target: 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)
   *
   */
  var INTERPOLATION_DELIMITER = "\uFFFD";
  /**
   * 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 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
   */
  /**
   * 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');
   *   }
   * }
   *
   * ```
   */
  var includeViewProviders = true;
  function setIncludeViewProviders(v) {
      var 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.
   */
  var BLOOM_SIZE = 256;
  var BLOOM_MASK = BLOOM_SIZE - 1;
  /** Counter used to generate unique IDs for directives. */
  var nextNgElementId = 0;
  /**
   * 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');
      var id = typeof type !== 'string' ? type[NG_ELEMENT_ID] : type.charCodeAt(0) || 0;
      // 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.
      var bloomBit = 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.
      var mask = 1 << bloomBit;
      // Use the raw bloomBit number to determine which bloom filter bucket we should check
      // e.g: bf0 = [0 - 31], bf1 = [32 - 63], bf2 = [64 - 95], bf3 = [96 - 127], etc
      var b7 = bloomBit & 0x80;
      var b6 = bloomBit & 0x40;
      var b5 = bloomBit & 0x20;
      var tData = tView.data;
      if (b7) {
          b6 ? (b5 ? (tData[injectorIndex + 7] |= mask) : (tData[injectorIndex + 6] |= mask)) :
              (b5 ? (tData[injectorIndex + 5] |= mask) : (tData[injectorIndex + 4] |= mask));
      }
      else {
          b6 ? (b5 ? (tData[injectorIndex + 3] |= mask) : (tData[injectorIndex + 2] |= mask)) :
              (b5 ? (tData[injectorIndex + 1] |= mask) : (tData[injectorIndex] |= mask));
      }
  }
  /**
   * Creates (or gets an existing) injector for a given element or container.
   *
   * @param tNode for which an injector should be retrieved / created.
   * @param hostView View where the node is stored
   * @returns Node injector
   */
  function getOrCreateNodeInjectorForNode(tNode, hostView) {
      var existingInjectorIndex = getInjectorIndex(tNode, hostView);
      if (existingInjectorIndex !== -1) {
          return existingInjectorIndex;
      }
      var tView = hostView[TVIEW];
      if (tView.firstCreatePass) {
          tNode.injectorIndex = hostView.length;
          insertBloom(tView.data, tNode); // foundation for node bloom
          insertBloom(hostView, null); // foundation for cumulative bloom
          insertBloom(tView.blueprint, null);
      }
      var parentLoc = getParentInjectorLocation(tNode, hostView);
      var 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)) {
          var parentIndex = getParentInjectorIndex(parentLoc);
          var parentLView = getParentInjectorView(parentLoc, hostView);
          var 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 (var i = 0; i < 8; i++) {
              hostView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i];
          }
      }
      hostView[injectorIndex + PARENT_INJECTOR] = parentLoc;
      return injectorIndex;
  }
  function insertBloom(arr, footer) {
      arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);
  }
  function getInjectorIndex(tNode, hostView) {
      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
          hostView[tNode.injectorIndex + PARENT_INJECTOR] == null) {
          return -1;
      }
      else {
          return tNode.injectorIndex;
      }
  }
  /**
   * Finds the index of the parent injector, with a view offset if applicable. Used to set the
   * parent injector initially.
   *
   * Returns a combination of number of `ViewData` we have to go up and index in that `Viewdata`
   */
  function getParentInjectorLocation(tNode, view) {
      if (tNode.parent && tNode.parent.injectorIndex !== -1) {
          return tNode.parent.injectorIndex; // ViewOffset is 0
      }
      // For most cases, the parent injector index can be found on the host node (e.g. for component
      // or container), so this loop will be skipped, but we must keep the loop here to support
      // the rarer case of deeply nested <ng-template> tags or inline views.
      var hostTNode = view[T_HOST];
      var viewOffset = 1;
      while (hostTNode && hostTNode.injectorIndex === -1) {
          view = view[DECLARATION_VIEW];
          hostTNode = view ? view[T_HOST] : null;
          viewOffset++;
      }
      return hostTNode ?
          hostTNode.injectorIndex | (viewOffset << 16 /* ViewOffsetShift */) :
          -1;
  }
  /**
   * 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 &&
          assertNodeOfPossibleTypes(tNode, 0 /* Container */, 3 /* Element */, 4 /* ElementContainer */);
      ngDevMode && assertDefined(tNode, 'expecting tNode');
      if (attrNameToInject === 'class') {
          return tNode.classes;
      }
      if (attrNameToInject === 'style') {
          return tNode.styles;
      }
      var attrs = tNode.attrs;
      if (attrs) {
          var attrsLength = attrs.length;
          var i = 0;
          while (i < attrsLength) {
              var 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 /* 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;
  }
  /**
   * 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. Negative values are reserved for special objects.
   *   - `-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, notFoundValue) {
      if (flags === void 0) { flags = exports.InjectFlags.Default; }
      if (tNode !== null) {
          var 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') {
              enterDI(lView, tNode);
              try {
                  var value = bloomHash();
                  if (value == null && !(flags & exports.InjectFlags.Optional)) {
                      throw new Error("No provider for " + stringifyForError(token) + "!");
                  }
                  else {
                      return value;
                  }
              }
              finally {
                  leaveDI();
              }
          }
          else if (typeof bloomHash == 'number') {
              if (bloomHash === -1) {
                  // `-1` is a special value used to identify `Injector` types.
                  return new NodeInjector(tNode, lView);
              }
              // If the token has a bloom hash, then it is a token which could be in NodeInjector.
              // 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.
              var previousTView = null;
              var injectorIndex = getInjectorIndex(tNode, lView);
              var parentLocation = NO_PARENT_INJECTOR;
              var hostTElementNode = flags & exports.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 & exports.InjectFlags.SkipSelf) {
                  parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) :
                      lView[injectorIndex + PARENT_INJECTOR];
                  if (!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) {
                  parentLocation = lView[injectorIndex + PARENT_INJECTOR];
                  // Check the current injector. If it matches, see if it contains token.
                  var tView = lView[TVIEW];
                  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.
                      var instance = searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode);
                      if (instance !== NOT_FOUND) {
                          return instance;
                      }
                  }
                  if (shouldSearchParent(flags, lView[TVIEW].data[injectorIndex + 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;
                  }
              }
          }
      }
      if (flags & exports.InjectFlags.Optional && notFoundValue === undefined) {
          // This must be set or the NullInjector will throw for optional deps
          notFoundValue = null;
      }
      if ((flags & (exports.InjectFlags.Self | exports.InjectFlags.Host)) === 0) {
          var 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)
          var previousInjectImplementation = setInjectImplementation(undefined);
          try {
              if (moduleInjector) {
                  return moduleInjector.get(token, notFoundValue, flags & exports.InjectFlags.Optional);
              }
              else {
                  return injectRootLimpMode(token, notFoundValue, flags & exports.InjectFlags.Optional);
              }
          }
          finally {
              setInjectImplementation(previousInjectImplementation);
          }
      }
      if (flags & exports.InjectFlags.Optional) {
          return notFoundValue;
      }
      else {
          throw new Error("NodeInjector: NOT_FOUND [" + stringifyForError(token) + "]");
      }
  }
  var NOT_FOUND = {};
  function searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode) {
      var currentTView = lView[TVIEW];
      var tNode = currentTView.data[injectorIndex + TNODE];
      // First, we need to determine if view providers can be accessed by the starting element.
      // There are two possibities
      var 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 /* Element */));
      // This special case happens when there is a @host on the inject and when we are searching
      // on the host element node.
      var isHostSpecialCase = (flags & exports.InjectFlags.Host) && hostTElementNode === tNode;
      var 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) {
      var nodeProviderIndexes = tNode.providerIndexes;
      var tInjectables = tView.data;
      var injectablesStart = nodeProviderIndexes & 65535 /* ProvidersStartIndexMask */;
      var directivesStart = tNode.directiveStart;
      var directiveEnd = tNode.directiveEnd;
      var cptViewProvidersCount = nodeProviderIndexes >> 16 /* CptViewProvidersCountShift */;
      var startingIndex = canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount;
      // When the host special case applies, only the viewProviders and the component are visible
      var endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd;
      for (var i = startingIndex; i < endIndex; i++) {
          var providerTokenOrDef = tInjectables[i];
          if (i < directivesStart && token === providerTokenOrDef ||
              i >= directivesStart && providerTokenOrDef.type === token) {
              return i;
          }
      }
      if (isHostSpecialCase) {
          var 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) {
      var value = lView[index];
      var tData = tView.data;
      if (isFactory(value)) {
          var factory = value;
          if (factory.resolving) {
              throw new Error("Circular dep for " + stringifyForError(tData[index]));
          }
          var previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
          factory.resolving = true;
          var previousInjectImplementation = void 0;
          if (factory.injectImpl) {
              previousInjectImplementation = setInjectImplementation(factory.injectImpl);
          }
          enterDI(lView, tNode);
          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 {
              if (factory.injectImpl)
                  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;
      }
      var tokenId = token[NG_ELEMENT_ID];
      // Negative token IDs are used for special objects such as `Injector`
      return (typeof tokenId === 'number' && tokenId > 0) ? tokenId & BLOOM_MASK : 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.
      var mask = 1 << bloomHash;
      var b7 = bloomHash & 0x80;
      var b6 = bloomHash & 0x40;
      var b5 = bloomHash & 0x20;
      // Our bloom filter size is 256 bits, which is eight 32-bit bloom filter buckets:
      // bf0 = [0 - 31], bf1 = [32 - 63], bf2 = [64 - 95], bf3 = [96 - 127], etc.
      // Get the bloom filter value from the appropriate bucket based on the directive's bloomBit.
      var value;
      if (b7) {
          value = b6 ? (b5 ? injectorView[injectorIndex + 7] : injectorView[injectorIndex + 6]) :
              (b5 ? injectorView[injectorIndex + 5] : injectorView[injectorIndex + 4]);
      }
      else {
          value = b6 ? (b5 ? injectorView[injectorIndex + 3] : injectorView[injectorIndex + 2]) :
              (b5 ? injectorView[injectorIndex + 1] : injectorView[injectorIndex]);
      }
      // 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 & exports.InjectFlags.Self) && !(flags & exports.InjectFlags.Host && isFirstHostTNode);
  }
  var NodeInjector = /** @class */ (function () {
      function NodeInjector(_tNode, _lView) {
          this._tNode = _tNode;
          this._lView = _lView;
      }
      NodeInjector.prototype.get = function (token, notFoundValue) {
          return getOrCreateInjectable(this._tNode, this._lView, token, undefined, notFoundValue);
      };
      return NodeInjector;
  }());
  /**
   * @codeGenApi
   */
  function ɵɵgetFactoryOf(type) {
      var typeAny = type;
      if (isForwardRef(type)) {
          return (function () {
              var factory = ɵɵgetFactoryOf(resolveForwardRef(typeAny));
              return factory ? factory() : null;
          });
      }
      var factory = getFactoryDef(typeAny);
      if (factory === null) {
          var injectorDef = getInjectorDef(typeAny);
          factory = injectorDef && injectorDef.factory;
      }
      return factory || null;
  }
  /**
   * @codeGenApi
   */
  function ɵɵgetInheritedFactory(type) {
      return noSideEffects(function () {
          var proto = Object.getPrototypeOf(type.prototype).constructor;
          var factory = proto[NG_FACTORY_DEF] || ɵɵgetFactoryOf(proto);
          if (factory !== null) {
              return factory;
          }
          else {
              // 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 function (t) { return new t(); };
          }
      });
  }

  /**
   * @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
   */
  var ERROR_TYPE = 'ngType';
  var ERROR_DEBUG_CONTEXT = 'ngDebugContext';
  var ERROR_ORIGINAL_ERROR = 'ngOriginalError';
  var ERROR_LOGGER = 'ngErrorLogger';
  function wrappedError(message, originalError) {
      var msg = message + " caused by: " + (originalError instanceof Error ? originalError.message : originalError);
      var error = Error(msg);
      error[ERROR_ORIGINAL_ERROR] = originalError;
      return error;
  }

  /**
   * @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
   */
  function getType(error) {
      return error[ERROR_TYPE];
  }
  function getDebugContext(error) {
      return error[ERROR_DEBUG_CONTEXT];
  }
  function getOriginalError(error) {
      return error[ERROR_ORIGINAL_ERROR];
  }
  function getErrorLogger(error) {
      return error[ERROR_LOGGER] || defaultErrorLogger;
  }
  function defaultErrorLogger(console) {
      var values = [];
      for (var _i = 1; _i < arguments.length; _i++) {
          values[_i - 1] = arguments[_i];
      }
      console.error.apply(console, __spread(values));
  }

  /**
   * @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
   */
  /**
   * 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
   */
  var ErrorHandler = /** @class */ (function () {
      function ErrorHandler() {
          /**
           * @internal
           */
          this._console = console;
      }
      ErrorHandler.prototype.handleError = function (error) {
          var originalError = this._findOriginalError(error);
          var context = this._findContext(error);
          // Note: Browser consoles show the place from where console.error was called.
          // We can use this to give users additional information about the error.
          var errorLogger = getErrorLogger(error);
          errorLogger(this._console, "ERROR", error);
          if (originalError) {
              errorLogger(this._console, "ORIGINAL ERROR", originalError);
          }
          if (context) {
              errorLogger(this._console, 'ERROR CONTEXT', context);
          }
      };
      /** @internal */
      ErrorHandler.prototype._findContext = function (error) {
          if (error) {
              return getDebugContext(error) ? getDebugContext(error) :
                  this._findContext(getOriginalError(error));
          }
          return null;
      };
      /** @internal */
      ErrorHandler.prototype._findOriginalError = function (error) {
          var e = getOriginalError(error);
          while (e && getOriginalError(e)) {
              e = getOriginalError(e);
          }
          return e;
      };
      return ErrorHandler;
  }());

  /**
   * @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
   */
  /**
   * 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
   */
  var CUSTOM_ELEMENTS_SCHEMA = {
      name: 'custom-elements'
  };
  /**
   * Defines a schema that allows any property on any element.
   *
   * @publicApi
   */
  var NO_ERRORS_SCHEMA = {
      name: 'no-errors-schema'
  };

  /**
   * @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
   */
  var SafeValueImpl = /** @class */ (function () {
      function SafeValueImpl(changingThisBreaksApplicationSecurity) {
          this.changingThisBreaksApplicationSecurity = changingThisBreaksApplicationSecurity;
      }
      SafeValueImpl.prototype.toString = function () {
          return "SafeValue must use [property]=binding: " + this.changingThisBreaksApplicationSecurity +
              " (see http://g.co/ng/security#xss)";
      };
      return SafeValueImpl;
  }());
  var SafeHtmlImpl = /** @class */ (function (_super) {
      __extends(SafeHtmlImpl, _super);
      function SafeHtmlImpl() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      SafeHtmlImpl.prototype.getTypeName = function () {
          return "HTML" /* Html */;
      };
      return SafeHtmlImpl;
  }(SafeValueImpl));
  var SafeStyleImpl = /** @class */ (function (_super) {
      __extends(SafeStyleImpl, _super);
      function SafeStyleImpl() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      SafeStyleImpl.prototype.getTypeName = function () {
          return "Style" /* Style */;
      };
      return SafeStyleImpl;
  }(SafeValueImpl));
  var SafeScriptImpl = /** @class */ (function (_super) {
      __extends(SafeScriptImpl, _super);
      function SafeScriptImpl() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      SafeScriptImpl.prototype.getTypeName = function () {
          return "Script" /* Script */;
      };
      return SafeScriptImpl;
  }(SafeValueImpl));
  var SafeUrlImpl = /** @class */ (function (_super) {
      __extends(SafeUrlImpl, _super);
      function SafeUrlImpl() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      SafeUrlImpl.prototype.getTypeName = function () {
          return "URL" /* Url */;
      };
      return SafeUrlImpl;
  }(SafeValueImpl));
  var SafeResourceUrlImpl = /** @class */ (function (_super) {
      __extends(SafeResourceUrlImpl, _super);
      function SafeResourceUrlImpl() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      SafeResourceUrlImpl.prototype.getTypeName = function () {
          return "ResourceURL" /* ResourceUrl */;
      };
      return SafeResourceUrlImpl;
  }(SafeValueImpl));
  function unwrapSafeValue(value) {
      return value instanceof SafeValueImpl ? value.changingThisBreaksApplicationSecurity :
          value;
  }
  function allowSanitizationBypassAndThrow(value, type) {
      var actualType = getSanitizationBypassType(value);
      if (actualType != null && actualType !== type) {
          // Allow ResourceURLs in URL contexts, they are strictly more trusted.
          if (actualType === "ResourceURL" /* ResourceUrl */ && type === "URL" /* Url */)
              return true;
          throw new Error("Required a safe " + type + ", got a " + actualType + " (see http://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 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
   */
  /**
   * 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).
   */
  var _devMode = true;
  var _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.');
      }
      _devMode = false;
  }

  /**
   * @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
   */
  /**
   * This helper class is used to get hold of an inert tree of DOM elements containing dirty HTML
   * that needs sanitizing.
   * Depending upon browser support we must use one of three strategies for doing this.
   * Support: Safari 10.x -> XHR strategy
   * Support: Firefox -> DomParser strategy
   * Default: InertDocument strategy
   */
  var InertBodyHelper = /** @class */ (function () {
      function InertBodyHelper(defaultDoc) {
          this.defaultDoc = defaultDoc;
          this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert');
          var inertBodyElement = this.inertDocument.body;
          if (inertBodyElement == null) {
              // usually there should be only one body element in the document, but IE doesn't have any, so
              // we need to create one.
              var inertHtml = this.inertDocument.createElement('html');
              this.inertDocument.appendChild(inertHtml);
              inertBodyElement = this.inertDocument.createElement('body');
              inertHtml.appendChild(inertBodyElement);
          }
          inertBodyElement.innerHTML = '<svg><g onload="this.parentNode.remove()"></g></svg>';
          if (inertBodyElement.querySelector && !inertBodyElement.querySelector('svg')) {
              // We just hit the Safari 10.1 bug - which allows JS to run inside the SVG G element
              // so use the XHR strategy.
              this.getInertBodyElement = this.getInertBodyElement_XHR;
              return;
          }
          inertBodyElement.innerHTML = '<svg><p><style><img src="</style><img src=x onerror=alert(1)//">';
          if (inertBodyElement.querySelector && inertBodyElement.querySelector('svg img')) {
              // We just hit the Firefox bug - which prevents the inner img JS from being sanitized
              // so use the DOMParser strategy, if it is available.
              // If the DOMParser is not available then we are not in Firefox (Server/WebWorker?) so we
              // fall through to the default strategy below.
              if (isDOMParserAvailable()) {
                  this.getInertBodyElement = this.getInertBodyElement_DOMParser;
                  return;
              }
          }
          // None of the bugs were hit so it is safe for us to use the default InertDocument strategy
          this.getInertBodyElement = this.getInertBodyElement_InertDocument;
      }
      /**
       * Use XHR to create and fill an inert body element (on Safari 10.1)
       * See
       * https://github.com/cure53/DOMPurify/blob/a992d3a75031cb8bb032e5ea8399ba972bdf9a65/src/purify.js#L439-L449
       */
      InertBodyHelper.prototype.getInertBodyElement_XHR = function (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.
          html = '<body><remove></remove>' + html + '</body>';
          try {
              html = encodeURI(html);
          }
          catch (_a) {
              return null;
          }
          var xhr = new XMLHttpRequest();
          xhr.responseType = 'document';
          xhr.open('GET', 'data:text/html;charset=utf-8,' + html, false);
          xhr.send(undefined);
          var body = xhr.response.body;
          body.removeChild(body.firstChild);
          return body;
      };
      /**
       * Use DOMParser to create and fill an inert body element (on Firefox)
       * See https://github.com/cure53/DOMPurify/releases/tag/0.6.7
       *
       */
      InertBodyHelper.prototype.getInertBodyElement_DOMParser = function (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.
          html = '<body><remove></remove>' + html + '</body>';
          try {
              var body = new window.DOMParser().parseFromString(html, 'text/html').body;
              body.removeChild(body.firstChild);
              return body;
          }
          catch (_a) {
              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 default sane strategy to use if the browser does not require one of the specialised
       * strategies above.
       */
      InertBodyHelper.prototype.getInertBodyElement_InertDocument = function (html) {
          // Prefer using <template> element if supported.
          var templateEl = this.inertDocument.createElement('template');
          if ('content' in templateEl) {
              templateEl.innerHTML = 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.
          var inertBody = this.inertDocument.createElement('body');
          inertBody.innerHTML = html;
          // Support: IE 9-11 only
          // strip custom-namespaced attributes on IE<=11
          if (this.defaultDoc.documentMode) {
              this.stripCustomNsAttrs(inertBody);
          }
          return inertBody;
      };
      /**
       * When IE9-11 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.
       */
      InertBodyHelper.prototype.stripCustomNsAttrs = function (el) {
          var elAttrs = el.attributes;
          // loop backwards so that we can support removals.
          for (var i = elAttrs.length - 1; 0 < i; i--) {
              var attrib = elAttrs.item(i);
              var attrName = attrib.name;
              if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
                  el.removeAttribute(attrName);
              }
          }
          var childNode = el.firstChild;
          while (childNode) {
              if (childNode.nodeType === Node.ELEMENT_NODE)
                  this.stripCustomNsAttrs(childNode);
              childNode = childNode.nextSibling;
          }
      };
      return InertBodyHelper;
  }());
  /**
   * We need to determine whether the DOMParser exists in the global context.
   * The try-catch is because, on some browsers, trying to access this property
   * on window can actually throw an error.
   *
   * @suppress {uselessCode}
   */
  function isDOMParserAvailable() {
      try {
          return !!window.DOMParser;
      }
      catch (_a) {
          return false;
      }
  }

  /**
   * @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
   */
  /**
   * 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.
   */
  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi;
  /* A pattern that matches safe srcset values */
  var SAFE_SRCSET_PATTERN = /^(?:(?:https?|file):|[^&:/?#]*(?:[/?#]|$))/gi;
  /** A pattern that matches safe data URLs. Only matches image, video and audio types. */
  var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+\/]+=*$/i;
  function _sanitizeUrl(url) {
      url = String(url);
      if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN))
          return url;
      if (isDevMode()) {
          console.warn("WARNING: sanitizing unsafe URL value " + url + " (see http://g.co/ng/security#xss)");
      }
      return 'unsafe:' + url;
  }
  function sanitizeSrcset(srcset) {
      srcset = String(srcset);
      return srcset.split(',').map(function (srcset) { return _sanitizeUrl(srcset.trim()); }).join(', ');
  }

  /**
   * @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
   */
  function tagSet(tags) {
      var e_1, _a;
      var res = {};
      try {
          for (var _b = __values(tags.split(',')), _c = _b.next(); !_c.done; _c = _b.next()) {
              var t = _c.value;
              res[t] = true;
          }
      }
      catch (e_1_1) { e_1 = { error: e_1_1 }; }
      finally {
          try {
              if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
          }
          finally { if (e_1) throw e_1.error; }
      }
      return res;
  }
  function merge() {
      var e_2, _a;
      var sets = [];
      for (var _i = 0; _i < arguments.length; _i++) {
          sets[_i] = arguments[_i];
      }
      var res = {};
      try {
          for (var sets_1 = __values(sets), sets_1_1 = sets_1.next(); !sets_1_1.done; sets_1_1 = sets_1.next()) {
              var s = sets_1_1.value;
              for (var v in s) {
                  if (s.hasOwnProperty(v))
                      res[v] = true;
              }
          }
      }
      catch (e_2_1) { e_2 = { error: e_2_1 }; }
      finally {
          try {
              if (sets_1_1 && !sets_1_1.done && (_a = sets_1.return)) _a.call(sets_1);
          }
          finally { if (e_2) throw e_2.error; }
      }
      return res;
  }
  // Good source of info about elements and attributes
  // http://dev.w3.org/html5/spec/Overview.html#semantics
  // http://simon.html5.org/html-elements
  // Safe Void Elements - HTML5
  // http://dev.w3.org/html5/spec/Overview.html#void-elements
  var VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr');
  // Elements that you can, intentionally, leave open (and which close themselves)
  // http://dev.w3.org/html5/spec/Overview.html#optional-tags
  var OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr');
  var OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt');
  var OPTIONAL_END_TAG_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS);
  // Safe Block Elements - HTML5
  var 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
  var 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'));
  var VALID_ELEMENTS = merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS);
  // Attributes that have href and hence need to be sanitized
  var URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');
  // Attributes that have special href set hence need to be sanitized
  var SRCSET_ATTRS = tagSet('srcset');
  var 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,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)
  var 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.
  var VALID_ATTRS = merge(URI_ATTRS, SRCSET_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.
  var SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template');
  /**
   * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe
   * attributes.
   */
  var SanitizingHtmlSerializer = /** @class */ (function () {
      function SanitizingHtmlSerializer() {
          // Explicitly track if something was stripped, to avoid accidentally warning of sanitization just
          // because characters were re-encoded.
          this.sanitizedSomething = false;
          this.buf = [];
      }
      SanitizingHtmlSerializer.prototype.sanitizeChildren = function (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.
          var current = el.firstChild;
          var 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);
                  }
                  var 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.
       */
      SanitizingHtmlSerializer.prototype.startElement = function (element) {
          var 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);
          var elAttrs = element.attributes;
          for (var i = 0; i < elAttrs.length; i++) {
              var elAttr = elAttrs.item(i);
              var attrName = elAttr.name;
              var lower = attrName.toLowerCase();
              if (!VALID_ATTRS.hasOwnProperty(lower)) {
                  this.sanitizedSomething = true;
                  continue;
              }
              var value = elAttr.value;
              // TODO(martinprobst): Special case image URIs for data:image/...
              if (URI_ATTRS[lower])
                  value = _sanitizeUrl(value);
              if (SRCSET_ATTRS[lower])
                  value = sanitizeSrcset(value);
              this.buf.push(' ', attrName, '="', encodeEntities(value), '"');
          }
          this.buf.push('>');
          return true;
      };
      SanitizingHtmlSerializer.prototype.endElement = function (current) {
          var tagName = current.nodeName.toLowerCase();
          if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) {
              this.buf.push('</');
              this.buf.push(tagName);
              this.buf.push('>');
          }
      };
      SanitizingHtmlSerializer.prototype.chars = function (chars) {
          this.buf.push(encodeEntities(chars));
      };
      SanitizingHtmlSerializer.prototype.checkClobberedElement = function (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;
      };
      return SanitizingHtmlSerializer;
  }());
  // Regular Expressions for parsing tags and attributes
  var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
  // ! to ~ is the ASCII range.
  var 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) {
          var hi = match.charCodeAt(0);
          var 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;');
  }
  var 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) {
      var inertBodyElement = null;
      try {
          inertBodyHelper = inertBodyHelper || new InertBodyHelper(defaultDoc);
          // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime).
          var 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.
          var mXSSAttempts = 5;
          var 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);
          var sanitizer = new SanitizingHtmlSerializer();
          var safeHtml = sanitizer.sanitizeChildren(getTemplateContent(inertBodyElement) || inertBodyElement);
          if (isDevMode() && sanitizer.sanitizedSomething) {
              console.warn('WARNING: sanitizing HTML stripped some content, see http://g.co/ng/security#xss');
          }
          return safeHtml;
      }
      finally {
          // In case anything goes wrong, clear out inertElement to reset the entire DOM structure.
          if (inertBodyElement) {
              var parent_1 = getTemplateContent(inertBodyElement) || inertBodyElement;
              while (parent_1.firstChild) {
                  parent_1.removeChild(parent_1.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 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
   */
  (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";
  })(exports.SecurityContext || (exports.SecurityContext = {}));

  /**
   * @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
   */
  /**
   * Regular expression for safe style values.
   *
   * Quotes (" and ') are allowed, but a check must be done elsewhere to ensure they're balanced.
   *
   * ',' allows multiple values to be assigned to the same property (e.g. background-attachment or
   * font-family) and hence could allow multiple values to get injected, but that should pose no risk
   * of XSS.
   *
   * The function expression checks only for XSS safety, not for CSS validity.
   *
   * This regular expression was taken from the Closure sanitization library, and augmented for
   * transformation values.
   */
  var VALUES = '[-,."\'%_!# a-zA-Z0-9]+';
  var TRANSFORMATION_FNS = '(?:matrix|translate|scale|rotate|skew|perspective)(?:X|Y|Z|3d)?';
  var COLOR_FNS = '(?:rgb|hsl)a?';
  var GRADIENTS = '(?:repeating-)?(?:linear|radial)-gradient';
  var CSS3_FNS = '(?:attr|calc|var)';
  var FN_ARGS = '\\([-0-9.%, #a-zA-Z]+\\)';
  var SAFE_STYLE_VALUE = new RegExp("^(" + VALUES + "|" +
      ("(?:" + TRANSFORMATION_FNS + "|" + COLOR_FNS + "|" + GRADIENTS + "|" + CSS3_FNS + ")") +
      (FN_ARGS + ")$"), 'g');
  /**
   * Matches a `url(...)` value with an arbitrary argument as long as it does
   * not contain parentheses.
   *
   * The URL value still needs to be sanitized separately.
   *
   * `url(...)` values are a very common use case, e.g. for `background-image`. With carefully crafted
   * CSS style rules, it is possible to construct an information leak with `url` values in CSS, e.g.
   * by observing whether scroll bars are displayed, or character ranges used by a font face
   * definition.
   *
   * Angular only allows binding CSS values (as opposed to entire CSS rules), so it is unlikely that
   * binding a URL value without further cooperation from the page will cause an information leak, and
   * if so, it is just a leak, not a full blown XSS vulnerability.
   *
   * Given the common use case, low likelihood of attack vector, and low impact of an attack, this
   * code is permissive and allows URLs that sanitize otherwise.
   */
  var URL_RE = /^url\(([^)]+)\)$/;
  /**
   * Checks that quotes (" and ') are properly balanced inside a string. Assumes
   * that neither escape (\) nor any other character that could result in
   * breaking out of a string parsing context are allowed;
   * see http://www.w3.org/TR/css3-syntax/#string-token-diagram.
   *
   * This code was taken from the Closure sanitization library.
   */
  function hasBalancedQuotes(value) {
      var outsideSingle = true;
      var outsideDouble = true;
      for (var i = 0; i < value.length; i++) {
          var c = value.charAt(i);
          if (c === '\'' && outsideDouble) {
              outsideSingle = !outsideSingle;
          }
          else if (c === '"' && outsideSingle) {
              outsideDouble = !outsideDouble;
          }
      }
      return outsideSingle && outsideDouble;
  }
  /**
   * Sanitizes the given untrusted CSS style property value (i.e. not an entire object, just a single
   * value) and returns a value that is safe to use in a browser environment.
   */
  function _sanitizeStyle(value) {
      value = String(value).trim(); // Make sure it's actually a string.
      if (!value)
          return '';
      // Single url(...) values are supported, but only for URLs that sanitize cleanly. See above for
      // reasoning behind this.
      var urlMatch = value.match(URL_RE);
      if ((urlMatch && _sanitizeUrl(urlMatch[1]) === urlMatch[1]) ||
          value.match(SAFE_STYLE_VALUE) && hasBalancedQuotes(value)) {
          return value; // Safe style values.
      }
      if (isDevMode()) {
          console.warn("WARNING: sanitizing unsafe style value " + value + " (see http://g.co/ng/security#xss).");
      }
      return 'unsafe';
  }

  /**
   * @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
   */
  /**
   * 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.
   *
   * @publicApi
   */
  function ɵɵsanitizeHtml(unsafeHtml) {
      var sanitizer = getSanitizer();
      if (sanitizer) {
          return sanitizer.sanitize(exports.SecurityContext.HTML, unsafeHtml) || '';
      }
      if (allowSanitizationBypassAndThrow(unsafeHtml, "HTML" /* Html */)) {
          return unwrapSafeValue(unsafeHtml);
      }
      return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
  }
  /**
   * A `style` sanitizer which converts untrusted `style` **string** into trusted string by removing
   * dangerous content.
   *
   * This method parses the `style` 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 bypassSanitizationTrustStyle}.
   *
   * @param unsafeStyle untrusted `style`, typically from the user.
   * @returns `style` string which is safe to bind to the `style` properties, because all of the
   * dangerous javascript and urls have been removed.
   *
   * @publicApi
   */
  function ɵɵsanitizeStyle(unsafeStyle) {
      var sanitizer = getSanitizer();
      if (sanitizer) {
          return sanitizer.sanitize(exports.SecurityContext.STYLE, unsafeStyle) || '';
      }
      if (allowSanitizationBypassAndThrow(unsafeStyle, "Style" /* Style */)) {
          return unwrapSafeValue(unsafeStyle);
      }
      return _sanitizeStyle(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.
   *
   * @publicApi
   */
  function ɵɵsanitizeUrl(unsafeUrl) {
      var sanitizer = getSanitizer();
      if (sanitizer) {
          return sanitizer.sanitize(exports.SecurityContext.URL, unsafeUrl) || '';
      }
      if (allowSanitizationBypassAndThrow(unsafeUrl, "URL" /* 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.
   *
   * @publicApi
   */
  function ɵɵsanitizeResourceUrl(unsafeResourceUrl) {
      var sanitizer = getSanitizer();
      if (sanitizer) {
          return sanitizer.sanitize(exports.SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '';
      }
      if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL" /* ResourceUrl */)) {
          return unwrapSafeValue(unsafeResourceUrl);
      }
      throw new Error('unsafe value used in a resource URL context (see http://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.
   *
   * @publicApi
   */
  function ɵɵsanitizeScript(unsafeScript) {
      var sanitizer = getSanitizer();
      if (sanitizer) {
          return sanitizer.sanitize(exports.SecurityContext.SCRIPT, unsafeScript) || '';
      }
      if (allowSanitizationBypassAndThrow(unsafeScript, "Script" /* Script */)) {
          return unwrapSafeValue(unsafeScript);
      }
      throw new Error('unsafe value used in a script context');
  }
  /**
   * 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.
   *
   * @publicApi
   */
  function ɵɵsanitizeUrlOrResourceUrl(unsafeUrl, tag, prop) {
      return getUrlSanitizer(tag, prop)(unsafeUrl);
  }
  /**
   * The default style sanitizer will handle sanitization for style properties by
   * sanitizing any CSS property that can include a `url` value (usually image-based properties)
   *
   * @publicApi
   */
  var ɵɵdefaultStyleSanitizer = function (prop, value, mode) {
      if (value === undefined && mode === undefined) {
          // This is a workaround for the fact that `StyleSanitizeFn` should not exist once PR#34480
          // lands. For now the `StyleSanitizeFn` and should act like `(value: any) => string` as a
          // work around.
          return ɵɵsanitizeStyle(prop);
      }
      mode = mode || 3 /* ValidateAndSanitize */;
      var doSanitizeValue = true;
      if (mode & 1 /* ValidateProperty */) {
          doSanitizeValue = stylePropNeedsSanitization(prop);
      }
      if (mode & 2 /* SanitizeOnly */) {
          return doSanitizeValue ? ɵɵsanitizeStyle(value) : unwrapSafeValue(value);
      }
      else {
          return doSanitizeValue;
      }
  };
  function stylePropNeedsSanitization(prop) {
      return prop === 'background-image' || prop === 'backgroundImage' || prop === 'background' ||
          prop === 'border-image' || prop === 'borderImage' || prop === 'border-image-source' ||
          prop === 'borderImageSource' || prop === 'filter' || prop === 'list-style' ||
          prop === 'listStyle' || prop === 'list-style-image' || prop === 'listStyleImage' ||
          prop === 'clip-path' || prop === 'clipPath';
  }
  function validateAgainstEventProperties(name) {
      if (name.toLowerCase().startsWith('on')) {
          var msg = "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 Error(msg);
      }
  }
  function validateAgainstEventAttributes(name) {
      if (name.toLowerCase().startsWith('on')) {
          var msg = "Binding to event attribute '" + name + "' is disallowed for security reasons, " +
              ("please use (" + name.slice(2) + ")=...");
          throw new Error(msg);
      }
  }
  function getSanitizer() {
      var lView = getLView();
      return lView && lView[SANITIZER];
  }

  /**
   * @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
   */
  /**
   * 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 {
              // We need to do it this way so that TypeScript does not down-level the below code.
              var FunctionConstructor = createNamedArrayType.constructor;
              return (new FunctionConstructor('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 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
   */
  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;
  }
  var CAMEL_CASE_REGEXP = /([A-Z])/g;
  function camelCaseToDashCase(input) {
      return input.replace(CAMEL_CASE_REGEXP, function () {
          var m = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              m[_i] = arguments[_i];
          }
          return '-' + 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 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
   */
  /**
   * 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) {
      var 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 (Array.isArray(mpValue)) {
              var lView = mpValue;
              var nodeIndex = void 0;
              var component = undefined;
              var 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.
              var native = unwrapRNode(lView[nodeIndex]);
              var existingCtx = readPatchedData(native);
              var 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 (var i = 0; i < directives.length; i++) {
                      attachPatchData(directives[i], context);
                  }
              }
              attachPatchData(context.native, context);
              mpValue = context;
          }
      }
      else {
          var 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
          var parent_1 = rElement;
          while (parent_1 = parent_1.parentNode) {
              var parentContext = readPatchedData(parent_1);
              if (parentContext) {
                  var lView = void 0;
                  if (Array.isArray(parentContext)) {
                      lView = parentContext;
                  }
                  else {
                      lView = 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;
                  }
                  var index = findViaNativeElement(lView, rElement);
                  if (index >= 0) {
                      var native = unwrapRNode(lView[index]);
                      var 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 {
          lView: lView,
          nodeIndex: nodeIndex,
          native: native,
          component: undefined,
          directives: undefined,
          localRefs: undefined,
      };
  }
  /**
   * Takes a component instance and returns the view for that component.
   *
   * @param componentInstance
   * @returns The component's view
   */
  function getComponentViewByInstance(componentInstance) {
      var lView = readPatchedData(componentInstance);
      var view;
      if (Array.isArray(lView)) {
          var nodeIndex = findViaComponent(lView, componentInstance);
          view = getComponentLViewByIndex(nodeIndex, lView);
          var context = createLContext(lView, nodeIndex, view[HOST]);
          context.component = componentInstance;
          attachPatchData(componentInstance, context);
          attachPatchData(context.native, context);
      }
      else {
          var context = lView;
          view = getComponentLViewByIndex(context.nodeIndex, context.lView);
      }
      return view;
  }
  /**
   * 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) {
      target[MONKEY_PATCH_KEY_NAME] = data;
  }
  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) {
      var tNode = lView[TVIEW].firstChild;
      while (tNode) {
          var native = getNativeByTNodeOrNull(tNode, lView);
          if (native === target) {
              return tNode.index;
          }
          tNode = traverseNextElement(tNode);
      }
      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) {
      var componentIndices = lView[TVIEW].components;
      if (componentIndices) {
          for (var i = 0; i < componentIndices.length; i++) {
              var elementComponentIndex = componentIndices[i];
              var componentView = getComponentLViewByIndex(elementComponentIndex, lView);
              if (componentView[CONTEXT] === componentInstance) {
                  return elementComponentIndex;
              }
          }
      }
      else {
          var rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView);
          var 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.
      var tNode = lView[TVIEW].firstChild;
      while (tNode) {
          var directiveIndexStart = tNode.directiveStart;
          var directiveIndexEnd = tNode.directiveEnd;
          for (var 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) {
      var tNode = lView[TVIEW].data[nodeIndex];
      var directiveStartIndex = tNode.directiveStart;
      if (directiveStartIndex == 0)
          return EMPTY_ARRAY;
      var directiveEndIndex = tNode.directiveEnd;
      if (!includeComponents && tNode.flags & 2 /* isComponentHost */)
          directiveStartIndex++;
      return lView.slice(directiveStartIndex, directiveEndIndex);
  }
  function getComponentAtNodeIndex(nodeIndex, lView) {
      var tNode = lView[TVIEW].data[nodeIndex];
      var directiveStartIndex = tNode.directiveStart;
      return tNode.flags & 2 /* 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) {
      var tNode = lView[TVIEW].data[nodeIndex];
      if (tNode && tNode.localNames) {
          var result = {};
          var localIndex = tNode.index + 1;
          for (var i = 0; i < tNode.localNames.length; i += 2) {
              result[tNode.localNames[i]] = lView[localIndex];
              localIndex++;
          }
          return result;
      }
      return null;
  }

  /** Called when directives inject each other (creating a circular dependency) */
  function throwCyclicDependencyError(token) {
      throw new Error("Cannot instantiate cyclic dependency! " + token);
  }
  /** Called when there are multiple component selectors that match a given node */
  function throwMultipleComponentError(tNode) {
      throw new Error("Multiple components match node with tagname " + tNode.tagName);
  }
  function throwMixedMultiProviderError() {
      throw new Error("Cannot mix multi providers and regular providers");
  }
  function throwInvalidProviderError(ngModuleType, providers, provider) {
      var ngModuleDetail = '';
      if (ngModuleType && providers) {
          var providerDetail = providers.map(function (v) { return v == provider ? '?' + provider + '?' : '...'; });
          ngModuleDetail =
              " - only instances of Provider and Type are allowed, got: [" + providerDetail.join(', ') + "]";
      }
      throw new Error("Invalid provider for the NgModule '" + stringify(ngModuleType) + "'" + ngModuleDetail);
  }
  /** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
  function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
      var field = propName ? " for '" + propName + "'" : '';
      var 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?";
      }
      // TODO: include debug context, see `viewDebugError` function in
      // `packages/core/src/view/errors.ts` for reference.
      throw new Error(msg);
  }
  function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
      var _a = __read(meta.split(INTERPOLATION_DELIMITER)), propName = _a[0], prefix = _a[1], chunks = _a.slice(2);
      var oldValue = prefix, newValue = prefix;
      for (var i = 0; i < chunks.length; i++) {
          var slotIdx = rootIndex + i;
          oldValue += "" + lView[slotIdx] + chunks[i];
          newValue += "" + (slotIdx === expressionIndex ? changedValue : lView[slotIdx]) + chunks[i];
      }
      return { propName: propName, oldValue: oldValue, newValue: 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) {
      var tData = lView[TVIEW].data;
      var 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: oldValue, newValue: 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) {
          var idx = bindingIndex - 1;
          while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
              idx--;
          }
          var meta = tData[idx];
          if (typeof meta === 'string') {
              var 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: oldValue, newValue: newValue };
  }

  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$4 = 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 /* 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 /* hasStyleInput */) !== 0;
  }

  /**
   * @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
   */
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$5 = 1;

  /**
   * @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
   */
  /**
   * 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.');
      var end = className.length;
      while (true) {
          var foundIndex = className.indexOf(classToSearch, startingIndex);
          if (foundIndex === -1)
              return foundIndex;
          if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32 /* SPACE */) {
              // Ensure that it has leading whitespace
              var length_1 = classToSearch.length;
              if (foundIndex + length_1 === end ||
                  className.charCodeAt(foundIndex + length_1) <= 32 /* SPACE */) {
                  // Ensure that it has trailing whitespace
                  return foundIndex;
              }
          }
          // False positive, keep searching from where we left off.
          startingIndex = foundIndex + 1;
      }
  }

  /**
   * @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
   */
  var unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$5;
  var 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.');
      var i = 0;
      while (i < attrs.length) {
          var item = attrs[i++];
          if (isProjectionMode && item === 'class') {
              item = attrs[i];
              if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
                  return true;
              }
          }
          else if (item === 1 /* 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 === 0 /* Container */ && tNode.tagName !== 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) {
      var tagNameToCompare = tNode.type === 0 /* Container */ && !isProjectionMode ?
          NG_TEMPLATE_SELECTOR :
          tNode.tagName;
      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');
      var mode = 4 /* ELEMENT */;
      var nodeAttrs = tNode.attrs || [];
      // Find the index of first attribute that has no value, only a name.
      var nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs);
      // When processing ":not" selectors, we skip to the next ":not" if the
      // current one doesn't match
      var skipToNextSelector = false;
      for (var i = 0; i < selector.length; i++) {
          var 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 /* NOT */);
              continue;
          }
          if (skipToNextSelector)
              continue;
          if (mode & 4 /* ELEMENT */) {
              mode = 2 /* ATTRIBUTE */ | mode & 1 /* NOT */;
              if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) ||
                  current === '' && selector.length === 1) {
                  if (isPositive(mode))
                      return false;
                  skipToNextSelector = true;
              }
          }
          else {
              var selectorAttrValue = mode & 8 /* 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 /* CLASS */) && tNode.attrs !== null) {
                  if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) {
                      if (isPositive(mode))
                          return false;
                      skipToNextSelector = true;
                  }
                  continue;
              }
              var attrName = (mode & 8 /* CLASS */) ? 'class' : current;
              var attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);
              if (attrIndexInNode === -1) {
                  if (isPositive(mode))
                      return false;
                  skipToNextSelector = true;
                  continue;
              }
              if (selectorAttrValue !== '') {
                  var nodeAttrValue = void 0;
                  if (attrIndexInNode > nameOnlyMarkerIdx) {
                      nodeAttrValue = '';
                  }
                  else {
                      ngDevMode &&
                          assertNotEqual(nodeAttrs[attrIndexInNode], 0 /* 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();
                  }
                  var compareAgainstClassName = mode & 8 /* CLASS */ ? nodeAttrValue : null;
                  if (compareAgainstClassName &&
                      classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 ||
                      mode & 2 /* ATTRIBUTE */ && selectorAttrValue !== nodeAttrValue) {
                      if (isPositive(mode))
                          return false;
                      skipToNextSelector = true;
                  }
              }
          }
      }
      return isPositive(mode) || skipToNextSelector;
  }
  function isPositive(mode) {
      return (mode & 1 /* 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;
      var i = 0;
      if (isProjectionMode || !isInlineTemplate) {
          var bindingsMode = false;
          while (i < attrs.length) {
              var maybeAttrName = attrs[i];
              if (maybeAttrName === name) {
                  return i;
              }
              else if (maybeAttrName === 3 /* Bindings */ || maybeAttrName === 6 /* I18n */) {
                  bindingsMode = true;
              }
              else if (maybeAttrName === 1 /* Classes */ || maybeAttrName === 2 /* Styles */) {
                  var 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 /* Template */) {
                  // We do not care about Template attributes in this scenario.
                  break;
              }
              else if (maybeAttrName === 0 /* 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) {
      if (isProjectionMode === void 0) { isProjectionMode = false; }
      for (var i = 0; i < selector.length; i++) {
          if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {
              return true;
          }
      }
      return false;
  }
  function getProjectAsAttrValue(tNode) {
      var nodeAttrs = tNode.attrs;
      if (nodeAttrs != null) {
          var ngProjectAsAttrIdx = nodeAttrs.indexOf(5 /* 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 (var i = 0; i < nodeAttrs.length; i++) {
          var nodeAttr = nodeAttrs[i];
          if (isNameOnlyAttributeMarker(nodeAttr)) {
              return i;
          }
      }
      return nodeAttrs.length;
  }
  function matchTemplateAttribute(attrs, name) {
      var i = attrs.indexOf(4 /* Template */);
      if (i > -1) {
          i++;
          while (i < attrs.length) {
              var 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 (var i = 0; i < list.length; i++) {
          var currentSelectorInList = list[i];
          if (selector.length !== currentSelectorInList.length) {
              continue;
          }
          for (var 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) {
      var result = selector[0];
      var i = 1;
      var mode = 2 /* ATTRIBUTE */;
      var currentChunk = '';
      var isNegativeMode = false;
      while (i < selector.length) {
          var valueOrMarker = selector[i];
          if (typeof valueOrMarker === 'string') {
              if (mode & 2 /* ATTRIBUTE */) {
                  var attrValue = selector[++i];
                  currentChunk +=
                      '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']';
              }
              else if (mode & 8 /* CLASS */) {
                  currentChunk += '.' + valueOrMarker;
              }
              else if (mode & 4 /* 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) {
      var attrs = [];
      var classes = [];
      var i = 1;
      var mode = 2 /* ATTRIBUTE */;
      while (i < selector.length) {
          var valueOrMarker = selector[i];
          if (typeof valueOrMarker === 'string') {
              if (mode === 2 /* ATTRIBUTE */) {
                  if (valueOrMarker !== '') {
                      attrs.push(valueOrMarker, selector[++i]);
                  }
              }
              else if (mode === 8 /* 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: attrs, classes: classes };
  }

  /**
   * @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
   */
  /** A special value which designates that a value has not changed. */
  var NO_CHANGE = (typeof ngDevMode === 'undefined' || ngDevMode) ? { __brand__: 'NO_CHANGE' } : {};

  /**
   * @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
   */
  /**
   * 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);
      var 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');
      var lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView);
      while (lView && !(lView[FLAGS] & 512 /* IsRoot */)) {
          lView = getLViewParent(lView);
      }
      ngDevMode && assertLView(lView);
      return lView;
  }
  /**
   * Returns the `RootContext` instance that is 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) {
      var rootView = getRootView(viewOrComponent);
      ngDevMode &&
          assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
      return rootView[CONTEXT];
  }

  /**
   * @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
   */
  /**
   * 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, getCheckNoChangesMode());
  }
  /**
   * Selects an element for later binding instructions.
   * @deprecated No longer being generated, but still used in unit tests.
   * @codeGenApi
   */
  function ɵɵselect(index) {
      // TODO(misko): Remove this function as it is no longer being used.
      selectIndexInternal(getTView(), getLView(), index, getCheckNoChangesMode());
  }
  function selectIndexInternal(tView, lView, index, checkNoChangesMode) {
      ngDevMode && assertGreaterThan(index, -1, 'Invalid index');
      ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
      // 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) {
          var hooksInitPhaseCompleted = (lView[FLAGS] & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;
          if (hooksInitPhaseCompleted) {
              var preOrderCheckHooks = tView.preOrderCheckHooks;
              if (preOrderCheckHooks !== null) {
                  executeCheckHooks(lView, preOrderCheckHooks, index);
              }
          }
          else {
              var preOrderHooks = tView.preOrderHooks;
              if (preOrderHooks !== null) {
                  executeInitAndCheckHooks(lView, preOrderHooks, 0 /* 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 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
   */
  /**
   * Marks that the next string is for element.
   *
   * See `I18nMutateOpCodes` documentation.
   */
  var ELEMENT_MARKER = {
      marker: 'element'
  };
  /**
   * Marks that the next string is for comment.
   *
   * See `I18nMutateOpCodes` documentation.
   */
  var COMMENT_MARKER = {
      marker: 'comment'
  };
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$6 = 1;

  /**
   * @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
   */
  function toTStylingRange(prev, next) {
      ngDevMode && assertNumberInRange(prev, 0, 32767 /* UNSIGNED_MASK */);
      ngDevMode && assertNumberInRange(next, 0, 32767 /* UNSIGNED_MASK */);
      return (prev << 17 /* PREV_SHIFT */ | next << 2 /* NEXT_SHIFT */);
  }
  function getTStylingRangePrev(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      return (tStylingRange >> 17 /* PREV_SHIFT */) & 32767 /* UNSIGNED_MASK */;
  }
  function getTStylingRangePrevDuplicate(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      return (tStylingRange & 2 /* PREV_DUPLICATE */) ==
          2 /* PREV_DUPLICATE */;
  }
  function setTStylingRangePrev(tStylingRange, previous) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      ngDevMode && assertNumberInRange(previous, 0, 32767 /* UNSIGNED_MASK */);
      return ((tStylingRange & ~4294836224 /* PREV_MASK */) |
          (previous << 17 /* PREV_SHIFT */));
  }
  function setTStylingRangePrevDuplicate(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      return (tStylingRange | 2 /* PREV_DUPLICATE */);
  }
  function getTStylingRangeNext(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      return (tStylingRange & 131068 /* NEXT_MASK */) >> 2 /* NEXT_SHIFT */;
  }
  function setTStylingRangeNext(tStylingRange, next) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      ngDevMode && assertNumberInRange(next, 0, 32767 /* UNSIGNED_MASK */);
      return ((tStylingRange & ~131068 /* NEXT_MASK */) | //
          next << 2 /* NEXT_SHIFT */);
  }
  function getTStylingRangeNextDuplicate(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      return (tStylingRange & 1 /* NEXT_DUPLICATE */) ===
          1 /* NEXT_DUPLICATE */;
  }
  function setTStylingRangeNextDuplicate(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      return (tStylingRange | 1 /* NEXT_DUPLICATE */);
  }
  function getTStylingRangeTail(tStylingRange) {
      ngDevMode && assertNumber(tStylingRange, 'expected number');
      var next = getTStylingRangeNext(tStylingRange);
      return next === 0 ? getTStylingRangePrev(tStylingRange) : next;
  }

  /**
   * @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
   */
  function attachDebugObject(obj, debug) {
      Object.defineProperty(obj, 'debug', { value: debug, enumerable: false });
  }

  /**
   * @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
   */
  var NG_DEV_MODE = ((typeof ngDevMode === 'undefined' || !!ngDevMode) && initNgDevMode());
  /*
   * 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}
   *     ]}
   *   ]
   * }
   * ```
   */
  var LVIEW_COMPONENT_CACHE;
  var LVIEW_EMBEDDED_CACHE;
  var LVIEW_ROOT;
  /**
   * 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) {
      var debugTView = tView;
      var lView = getLViewToClone(debugTView.type, tView.template && tView.template.name);
      return lView.concat(tView.blueprint);
  }
  function getLViewToClone(type, name) {
      switch (type) {
          case 0 /* Root */:
              if (LVIEW_ROOT === undefined)
                  LVIEW_ROOT = new (createNamedArrayType('LRootView'))();
              return LVIEW_ROOT;
          case 1 /* Component */:
              if (LVIEW_COMPONENT_CACHE === undefined)
                  LVIEW_COMPONENT_CACHE = new Map();
              var 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 /* Embedded */:
              if (LVIEW_EMBEDDED_CACHE === undefined)
                  LVIEW_EMBEDDED_CACHE = new Map();
              var embeddedArray = LVIEW_EMBEDDED_CACHE.get(name);
              if (embeddedArray === undefined) {
                  embeddedArray = new (createNamedArrayType('LEmbeddedView' + nameSuffix(name)))();
                  LVIEW_EMBEDDED_CACHE.set(name, embeddedArray);
              }
              return embeddedArray;
      }
      throw new Error('unreachable code');
  }
  function nameSuffix(text) {
      if (text == null)
          return '';
      var index = text.lastIndexOf('_Template');
      return '_' + (index === -1 ? text : text.substr(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.
   */
  var TViewConstructor = /** @class */ (function () {
      function TView(type, //
      id, //
      blueprint, //
      template, //
      queries, //
      viewQuery, //
      node, //
      data, //
      bindingStartIndex, //
      expandoStartIndex, //
      expandoInstructions, //
      firstCreatePass, //
      firstUpdatePass, //
      staticViewQueries, //
      staticContentQueries, //
      preOrderHooks, //
      preOrderCheckHooks, //
      contentHooks, //
      contentCheckHooks, //
      viewHooks, //
      viewCheckHooks, //
      destroyHooks, //
      cleanup, //
      contentQueries, //
      components, //
      directiveRegistry, //
      pipeRegistry, //
      firstChild, //
      schemas, //
      consts, //
      incompleteFirstPass //
      ) {
          this.type = type;
          this.id = id;
          this.blueprint = blueprint;
          this.template = template;
          this.queries = queries;
          this.viewQuery = viewQuery;
          this.node = node;
          this.data = data;
          this.bindingStartIndex = bindingStartIndex;
          this.expandoStartIndex = expandoStartIndex;
          this.expandoInstructions = expandoInstructions;
          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;
      }
      Object.defineProperty(TView.prototype, "template_", {
          get: function () {
              var buf = [];
              processTNodeChildren(this.firstChild, buf);
              return buf.join('');
          },
          enumerable: true,
          configurable: true
      });
      return TView;
  }());
  var TNode = /** @class */ (function () {
      function TNode(tView_, //
      type, //
      index, //
      injectorIndex, //
      directiveStart, //
      directiveEnd, //
      directiveStylingLast, //
      propertyBindings, //
      flags, //
      providerIndexes, //
      tagName, //
      attrs, //
      mergedAttrs, //
      localNames, //
      initialInputs, //
      inputs, //
      outputs, //
      tViews, //
      next, //
      projectionNext, //
      child, //
      parent, //
      projection, //
      styles, //
      residualStyles, //
      classes, //
      residualClasses, //
      classBindings, //
      styleBindings) {
          this.tView_ = tView_;
          this.type = type;
          this.index = index;
          this.injectorIndex = injectorIndex;
          this.directiveStart = directiveStart;
          this.directiveEnd = directiveEnd;
          this.directiveStylingLast = directiveStylingLast;
          this.propertyBindings = propertyBindings;
          this.flags = flags;
          this.providerIndexes = providerIndexes;
          this.tagName = tagName;
          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.residualStyles = residualStyles;
          this.classes = classes;
          this.residualClasses = residualClasses;
          this.classBindings = classBindings;
          this.styleBindings = styleBindings;
      }
      Object.defineProperty(TNode.prototype, "type_", {
          get: function () {
              switch (this.type) {
                  case 0 /* Container */:
                      return 'TNodeType.Container';
                  case 3 /* Element */:
                      return 'TNodeType.Element';
                  case 4 /* ElementContainer */:
                      return 'TNodeType.ElementContainer';
                  case 5 /* IcuContainer */:
                      return 'TNodeType.IcuContainer';
                  case 1 /* Projection */:
                      return 'TNodeType.Projection';
                  case 2 /* View */:
                      return 'TNodeType.View';
                  default:
                      return 'TNodeType.???';
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(TNode.prototype, "flags_", {
          get: function () {
              var flags = [];
              if (this.flags & 16 /* hasClassInput */)
                  flags.push('TNodeFlags.hasClassInput');
              if (this.flags & 8 /* hasContentQuery */)
                  flags.push('TNodeFlags.hasContentQuery');
              if (this.flags & 32 /* hasStyleInput */)
                  flags.push('TNodeFlags.hasStyleInput');
              if (this.flags & 128 /* hasHostBindings */)
                  flags.push('TNodeFlags.hasHostBindings');
              if (this.flags & 2 /* isComponentHost */)
                  flags.push('TNodeFlags.isComponentHost');
              if (this.flags & 1 /* isDirectiveHost */)
                  flags.push('TNodeFlags.isDirectiveHost');
              if (this.flags & 64 /* isDetached */)
                  flags.push('TNodeFlags.isDetached');
              if (this.flags & 4 /* isProjected */)
                  flags.push('TNodeFlags.isProjected');
              return flags.join('|');
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(TNode.prototype, "template_", {
          get: function () {
              var buf = [];
              buf.push('<', this.tagName || this.type_);
              if (this.attrs) {
                  for (var i = 0; i < this.attrs.length;) {
                      var attrName = this.attrs[i++];
                      if (typeof attrName == 'number') {
                          break;
                      }
                      var attrValue = this.attrs[i++];
                      buf.push(' ', attrName, '="', attrValue, '"');
                  }
              }
              buf.push('>');
              processTNodeChildren(this.child, buf);
              buf.push('</', this.tagName || this.type_, '>');
              return buf.join('');
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(TNode.prototype, "styleBindings_", {
          get: function () {
              return toDebugStyleBinding(this, false);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(TNode.prototype, "classBindings_", {
          get: function () {
              return toDebugStyleBinding(this, true);
          },
          enumerable: true,
          configurable: true
      });
      return TNode;
  }());
  var TNodeDebug = TNode;
  function toDebugStyleBinding(tNode, isClassBased) {
      var tData = tNode.tView_.data;
      var bindings = [];
      var range = isClassBased ? tNode.classBindings : tNode.styleBindings;
      var prev = getTStylingRangePrev(range);
      var next = getTStylingRangeNext(range);
      var isTemplate = next !== 0;
      var cursor = isTemplate ? next : prev;
      while (cursor !== 0) {
          var itemKey = tData[cursor];
          var 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;
      }
  }
  var TViewData = NG_DEV_MODE && createNamedArrayType('TViewData') || null;
  var 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);
  }
  var LViewBlueprint = NG_DEV_MODE && createNamedArrayType('LViewBlueprint') || null;
  var MatchesArray = NG_DEV_MODE && createNamedArrayType('MatchesArray') || null;
  var TViewComponents = NG_DEV_MODE && createNamedArrayType('TViewComponents') || null;
  var TNodeLocalNames = NG_DEV_MODE && createNamedArrayType('TNodeLocalNames') || null;
  var TNodeInitialInputs = NG_DEV_MODE && createNamedArrayType('TNodeInitialInputs') || null;
  var TNodeInitialData = NG_DEV_MODE && createNamedArrayType('TNodeInitialData') || null;
  var LCleanup = NG_DEV_MODE && createNamedArrayType('LCleanup') || null;
  var TCleanup = NG_DEV_MODE && createNamedArrayType('TCleanup') || null;
  function attachLViewDebug(lView) {
      attachDebugObject(lView, new LViewDebug(lView));
  }
  function attachLContainerDebug(lContainer) {
      attachDebugObject(lContainer, new LContainerDebug(lContainer));
  }
  function toDebug(obj) {
      if (obj) {
          var 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) {
      if (includeChildren === void 0) { includeChildren = false; }
      var node = unwrapRNode(value);
      if (node) {
          var isTextNode = node.nodeType === Node.TEXT_NODE;
          var outerHTML = (isTextNode ? node.textContent : node.outerHTML) || '';
          if (includeChildren || isTextNode) {
              return outerHTML;
          }
          else {
              var innerHTML = '>' + node.innerHTML + '<';
              return (outerHTML.split(innerHTML)[0]) + '>';
          }
      }
      else {
          return null;
      }
  }
  var LViewDebug = /** @class */ (function () {
      function LViewDebug(_raw_lView) {
          this._raw_lView = _raw_lView;
      }
      Object.defineProperty(LViewDebug.prototype, "flags", {
          /**
           * Flags associated with the `LView` unpacked into a more readable state.
           */
          get: function () {
              var flags = this._raw_lView[FLAGS];
              return {
                  __raw__flags__: flags,
                  initPhaseState: flags & 3 /* InitPhaseStateMask */,
                  creationMode: !!(flags & 4 /* CreationMode */),
                  firstViewPass: !!(flags & 8 /* FirstLViewPass */),
                  checkAlways: !!(flags & 16 /* CheckAlways */),
                  dirty: !!(flags & 64 /* Dirty */),
                  attached: !!(flags & 128 /* Attached */),
                  destroyed: !!(flags & 256 /* Destroyed */),
                  isRoot: !!(flags & 512 /* IsRoot */),
                  indexWithinInitPhase: flags >> 11 /* IndexWithinInitPhaseShift */,
              };
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "parent", {
          get: function () {
              return toDebug(this._raw_lView[PARENT]);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "host", {
          get: function () {
              return toHtml(this._raw_lView[HOST], true);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "html", {
          get: function () {
              return (this.nodes || []).map(function (node) { return toHtml(node.native, true); }).join('');
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "context", {
          get: function () {
              return this._raw_lView[CONTEXT];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "nodes", {
          /**
           * 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: function () {
              var lView = this._raw_lView;
              var tNode = lView[TVIEW].firstChild;
              return toDebugNodes(tNode, lView);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "tView", {
          get: function () {
              return this._raw_lView[TVIEW];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "cleanup", {
          get: function () {
              return this._raw_lView[CLEANUP];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "injector", {
          get: function () {
              return this._raw_lView[INJECTOR$1];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "rendererFactory", {
          get: function () {
              return this._raw_lView[RENDERER_FACTORY];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "renderer", {
          get: function () {
              return this._raw_lView[RENDERER];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "sanitizer", {
          get: function () {
              return this._raw_lView[SANITIZER];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "childHead", {
          get: function () {
              return toDebug(this._raw_lView[CHILD_HEAD]);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "next", {
          get: function () {
              return toDebug(this._raw_lView[NEXT]);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "childTail", {
          get: function () {
              return toDebug(this._raw_lView[CHILD_TAIL]);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "declarationView", {
          get: function () {
              return toDebug(this._raw_lView[DECLARATION_VIEW]);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "queries", {
          get: function () {
              return this._raw_lView[QUERIES];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "tHost", {
          get: function () {
              return this._raw_lView[T_HOST];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LViewDebug.prototype, "childViews", {
          /**
           * Normalized view of child views (and containers) attached at this location.
           */
          get: function () {
              var childViews = [];
              var child = this.childHead;
              while (child) {
                  childViews.push(child);
                  child = child.next;
              }
              return childViews;
          },
          enumerable: true,
          configurable: true
      });
      return LViewDebug;
  }());
  /**
   * 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) {
          var debugNodes = [];
          var tNodeCursor = tNode;
          while (tNodeCursor) {
              debugNodes.push(buildDebugNode(tNodeCursor, lView, tNodeCursor.index));
              tNodeCursor = tNodeCursor.next;
          }
          return debugNodes;
      }
      else {
          return null;
      }
  }
  function buildDebugNode(tNode, lView, nodeIndex) {
      var rawValue = lView[nodeIndex];
      var native = unwrapRNode(rawValue);
      var componentLViewDebug = toDebug(readLViewValue(rawValue));
      return {
          html: toHtml(native),
          native: native,
          nodes: toDebugNodes(tNode.child, lView),
          component: componentLViewDebug,
      };
  }
  var LContainerDebug = /** @class */ (function () {
      function LContainerDebug(_raw_lContainer) {
          this._raw_lContainer = _raw_lContainer;
      }
      Object.defineProperty(LContainerDebug.prototype, "activeIndex", {
          get: function () {
              return getLContainerActiveIndex(this._raw_lContainer);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "hasTransplantedViews", {
          get: function () {
              return (this._raw_lContainer[ACTIVE_INDEX] & 1 /* HAS_TRANSPLANTED_VIEWS */) ===
                  1 /* HAS_TRANSPLANTED_VIEWS */;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "views", {
          get: function () {
              return this._raw_lContainer.slice(CONTAINER_HEADER_OFFSET)
                  .map(toDebug);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "parent", {
          get: function () {
              return toDebug(this._raw_lContainer[PARENT]);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "movedViews", {
          get: function () {
              return this._raw_lContainer[MOVED_VIEWS];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "host", {
          get: function () {
              return this._raw_lContainer[HOST];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "native", {
          get: function () {
              return this._raw_lContainer[NATIVE];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(LContainerDebug.prototype, "next", {
          get: function () {
              return toDebug(this._raw_lContainer[NEXT]);
          },
          enumerable: true,
          configurable: true
      });
      return LContainerDebug;
  }());
  /**
   * Return an `LView` value if found.
   *
   * @param value `LView` if any
   */
  function readLViewValue(value) {
      while (Array.isArray(value)) {
          // This check is not quite right, as it does not take into account `StylingContext`
          // This is why it is in debug, not in util.ts
          if (value.length >= HEADER_OFFSET - 1)
              return value;
          value = value[HOST];
      }
      return null;
  }
  var I18NDebugItem = /** @class */ (function () {
      function I18NDebugItem(__raw_opCode, _lView, nodeIndex, type) {
          this.__raw_opCode = __raw_opCode;
          this._lView = _lView;
          this.nodeIndex = nodeIndex;
          this.type = type;
      }
      Object.defineProperty(I18NDebugItem.prototype, "tNode", {
          get: function () {
              return getTNode(this._lView[TVIEW], this.nodeIndex);
          },
          enumerable: true,
          configurable: true
      });
      return I18NDebugItem;
  }());
  /**
   * Turns a list of "Create" & "Update" OpCodes into a human-readable list of operations for
   * debugging purposes.
   * @param mutateOpCodes mutation opCodes to read
   * @param updateOpCodes update opCodes to read
   * @param icus list of ICU expressions
   * @param lView The view the opCodes are acting on
   */
  function attachI18nOpCodesDebug(mutateOpCodes, updateOpCodes, icus, lView) {
      attachDebugObject(mutateOpCodes, new I18nMutateOpCodesDebug(mutateOpCodes, lView));
      attachDebugObject(updateOpCodes, new I18nUpdateOpCodesDebug(updateOpCodes, icus, lView));
      if (icus) {
          icus.forEach(function (icu) {
              icu.create.forEach(function (icuCase) {
                  attachDebugObject(icuCase, new I18nMutateOpCodesDebug(icuCase, lView));
              });
              icu.update.forEach(function (icuCase) {
                  attachDebugObject(icuCase, new I18nUpdateOpCodesDebug(icuCase, icus, lView));
              });
          });
      }
  }
  var I18nMutateOpCodesDebug = /** @class */ (function () {
      function I18nMutateOpCodesDebug(__raw_opCodes, __lView) {
          this.__raw_opCodes = __raw_opCodes;
          this.__lView = __lView;
      }
      Object.defineProperty(I18nMutateOpCodesDebug.prototype, "operations", {
          /**
           * A list of operation information about how the OpCodes will act on the view.
           */
          get: function () {
              var _a = this, __lView = _a.__lView, __raw_opCodes = _a.__raw_opCodes;
              var results = [];
              for (var i = 0; i < __raw_opCodes.length; i++) {
                  var opCode = __raw_opCodes[i];
                  var result = void 0;
                  if (typeof opCode === 'string') {
                      result = {
                          __raw_opCode: opCode,
                          type: 'Create Text Node',
                          nodeIndex: __raw_opCodes[++i],
                          text: opCode,
                      };
                  }
                  if (typeof opCode === 'number') {
                      switch (opCode & 7 /* MASK_OPCODE */) {
                          case 1 /* AppendChild */:
                              var destinationNodeIndex = opCode >>> 17 /* SHIFT_PARENT */;
                              result = new I18NDebugItem(opCode, __lView, destinationNodeIndex, 'AppendChild');
                              break;
                          case 0 /* Select */:
                              var nodeIndex = opCode >>> 3 /* SHIFT_REF */;
                              result = new I18NDebugItem(opCode, __lView, nodeIndex, 'Select');
                              break;
                          case 5 /* ElementEnd */:
                              var elementIndex = opCode >>> 3 /* SHIFT_REF */;
                              result = new I18NDebugItem(opCode, __lView, elementIndex, 'ElementEnd');
                              break;
                          case 4 /* Attr */:
                              elementIndex = opCode >>> 3 /* SHIFT_REF */;
                              result = new I18NDebugItem(opCode, __lView, elementIndex, 'Attr');
                              result['attrName'] = __raw_opCodes[++i];
                              result['attrValue'] = __raw_opCodes[++i];
                              break;
                      }
                  }
                  if (!result) {
                      switch (opCode) {
                          case COMMENT_MARKER:
                              result = {
                                  __raw_opCode: opCode,
                                  type: 'COMMENT_MARKER',
                                  commentValue: __raw_opCodes[++i],
                                  nodeIndex: __raw_opCodes[++i],
                              };
                              break;
                          case ELEMENT_MARKER:
                              result = {
                                  __raw_opCode: opCode,
                                  type: 'ELEMENT_MARKER',
                              };
                              break;
                      }
                  }
                  if (!result) {
                      result = {
                          __raw_opCode: opCode,
                          type: 'Unknown Op Code',
                          code: opCode,
                      };
                  }
                  results.push(result);
              }
              return results;
          },
          enumerable: true,
          configurable: true
      });
      return I18nMutateOpCodesDebug;
  }());
  var I18nUpdateOpCodesDebug = /** @class */ (function () {
      function I18nUpdateOpCodesDebug(__raw_opCodes, icus, __lView) {
          this.__raw_opCodes = __raw_opCodes;
          this.icus = icus;
          this.__lView = __lView;
      }
      Object.defineProperty(I18nUpdateOpCodesDebug.prototype, "operations", {
          /**
           * A list of operation information about how the OpCodes will act on the view.
           */
          get: function () {
              var _a = this, __lView = _a.__lView, __raw_opCodes = _a.__raw_opCodes, icus = _a.icus;
              var results = [];
              for (var i = 0; i < __raw_opCodes.length; i++) {
                  // bit code to check if we should apply the next update
                  var checkBit = __raw_opCodes[i];
                  // Number of opCodes to skip until next set of update codes
                  var skipCodes = __raw_opCodes[++i];
                  var value = '';
                  for (var j = i + 1; j <= (i + skipCodes); j++) {
                      var opCode = __raw_opCodes[j];
                      if (typeof opCode === 'string') {
                          value += opCode;
                      }
                      else if (typeof opCode == 'number') {
                          if (opCode < 0) {
                              // It's a binding index whose value is negative
                              // We cannot know the value of the binding so we only show the index
                              value += "\uFFFD" + (-opCode - 1) + "\uFFFD";
                          }
                          else {
                              var nodeIndex = opCode >>> 2 /* SHIFT_REF */;
                              var tIcuIndex = void 0;
                              var tIcu = void 0;
                              switch (opCode & 3 /* MASK_OPCODE */) {
                                  case 1 /* Attr */:
                                      var attrName = __raw_opCodes[++j];
                                      var sanitizeFn = __raw_opCodes[++j];
                                      results.push({
                                          __raw_opCode: opCode,
                                          checkBit: checkBit,
                                          type: 'Attr',
                                          attrValue: value,
                                          attrName: attrName,
                                          sanitizeFn: sanitizeFn,
                                      });
                                      break;
                                  case 0 /* Text */:
                                      results.push({
                                          __raw_opCode: opCode,
                                          checkBit: checkBit,
                                          type: 'Text',
                                          nodeIndex: nodeIndex,
                                          text: value,
                                      });
                                      break;
                                  case 2 /* IcuSwitch */:
                                      tIcuIndex = __raw_opCodes[++j];
                                      tIcu = icus[tIcuIndex];
                                      var result = new I18NDebugItem(opCode, __lView, nodeIndex, 'IcuSwitch');
                                      result['tIcuIndex'] = tIcuIndex;
                                      result['checkBit'] = checkBit;
                                      result['mainBinding'] = value;
                                      result['tIcu'] = tIcu;
                                      results.push(result);
                                      break;
                                  case 3 /* IcuUpdate */:
                                      tIcuIndex = __raw_opCodes[++j];
                                      tIcu = icus[tIcuIndex];
                                      result = new I18NDebugItem(opCode, __lView, nodeIndex, 'IcuUpdate');
                                      result['tIcuIndex'] = tIcuIndex;
                                      result['checkBit'] = checkBit;
                                      result['tIcu'] = tIcu;
                                      results.push(result);
                                      break;
                              }
                          }
                      }
                  }
                  i += skipCodes;
              }
              return results;
          },
          enumerable: true,
          configurable: true
      });
      return I18nUpdateOpCodesDebug;
  }());

  var ɵ0$4 = function () { return Promise.resolve(null); };
  /**
   * A permanent marker promise which signifies that the current CD tree is
   * clean.
   */
  var _CLEAN_PROMISE = (ɵ0$4)();
  /**
   * Process the `TView.expandoInstructions`. (Execute the `hostBindings`.)
   *
   * @param tView `TView` containing the `expandoInstructions`
   * @param lView `LView` associated with the `TView`
   */
  function setHostBindingsByExecutingExpandoInstructions(tView, lView) {
      ngDevMode && assertSame(tView, lView[TVIEW], '`LView` is not associated with the `TView`!');
      try {
          var expandoInstructions = tView.expandoInstructions;
          if (expandoInstructions !== null) {
              var bindingRootIndex = tView.expandoStartIndex;
              var currentDirectiveIndex = -1;
              var currentElementIndex = -1;
              // TODO(misko): PERF It is possible to get here with `TView.expandoInstructions` containing no
              // functions to execute. This is wasteful as there is no work to be done, but we still need
              // to iterate over the instructions.
              // In example of this is in this test: `host_binding_spec.ts`
              // `fit('should not cause problems if detectChanges is called when a property updates', ...`
              // In the above test we get here with expando [0, 0, 1] which requires a lot of processing but
              // there is no function to execute.
              for (var i = 0; i < expandoInstructions.length; i++) {
                  var instruction = expandoInstructions[i];
                  if (typeof instruction === 'number') {
                      if (instruction <= 0) {
                          // Negative numbers mean that we are starting new EXPANDO block and need to update
                          // the current element and directive index.
                          // Important: In JS `-x` and `0-x` is not the same! If `x===0` then `-x` will produce
                          // `-0` which requires non standard math arithmetic and it can prevent VM optimizations.
                          // `0-0` will always produce `0` and will not cause a potential deoptimization in VM.
                          // TODO(misko): PERF This should be refactored to use `~instruction` as that does not
                          // suffer from `-0` and it is faster/more compact.
                          currentElementIndex = 0 - instruction;
                          setSelectedIndex(currentElementIndex);
                          // Injector block and providers are taken into account.
                          var providerCount = expandoInstructions[++i];
                          bindingRootIndex += INJECTOR_BLOOM_PARENT_SIZE + providerCount;
                          currentDirectiveIndex = bindingRootIndex;
                      }
                      else {
                          // This is either the injector size (so the binding root can skip over directives
                          // and get to the first set of host bindings on this node) or the host var count
                          // (to get to the next set of host bindings on this node).
                          bindingRootIndex += instruction;
                      }
                  }
                  else {
                      // If it's not a number, it's a host binding function that needs to be executed.
                      if (instruction !== null) {
                          setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex);
                          var hostCtx = lView[currentDirectiveIndex];
                          instruction(2 /* Update */, hostCtx);
                      }
                      // TODO(misko): PERF Relying on incrementing the `currentDirectiveIndex` here is
                      // sub-optimal. The implications are that if we have a lot of directives but none of them
                      // have host bindings we nevertheless need to iterate over the expando instructions to
                      // update the counter. It would be much better if we could encode the
                      // `currentDirectiveIndex` into the `expandoInstruction` array so that we only need to
                      // iterate over those directives which actually have `hostBindings`.
                      currentDirectiveIndex++;
                  }
              }
          }
      }
      finally {
          setSelectedIndex(-1);
      }
  }
  /** Refreshes all content queries declared by directives in a given view */
  function refreshContentQueries(tView, lView) {
      var contentQueries = tView.contentQueries;
      if (contentQueries !== null) {
          for (var i = 0; i < contentQueries.length; i += 2) {
              var queryStartIdx = contentQueries[i];
              var directiveDefIdx = contentQueries[i + 1];
              if (directiveDefIdx !== -1) {
                  var directiveDef = tView.data[directiveDefIdx];
                  ngDevMode &&
                      assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined');
                  setCurrentQueryIndex(queryStartIdx);
                  directiveDef.contentQueries(2 /* Update */, lView[directiveDefIdx], directiveDefIdx);
              }
          }
      }
  }
  /** Refreshes child components in the current view (update mode). */
  function refreshChildComponents(hostLView, components) {
      for (var i = 0; i < components.length; i++) {
          refreshComponent(hostLView, components[i]);
      }
  }
  /** Renders child components in the current view (creation mode). */
  function renderChildComponents(hostLView, components) {
      for (var i = 0; i < components.length; i++) {
          renderComponent(hostLView, components[i]);
      }
  }
  /**
   * Creates a native element from a tag name, using a renderer.
   * @param name the tag name
   * @param renderer A renderer to use
   * @returns the element created
   */
  function elementCreate(name, renderer, namespace) {
      if (isProceduralRenderer(renderer)) {
          return renderer.createElement(name, namespace);
      }
      else {
          return namespace === null ? renderer.createElement(name) :
              renderer.createElementNS(namespace, name);
      }
  }
  function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector) {
      var lView = ngDevMode ? cloneToLViewFromTViewBlueprint(tView) : tView.blueprint.slice();
      lView[HOST] = host;
      lView[FLAGS] = flags | 4 /* CreationMode */ | 128 /* Attached */ | 8 /* FirstLViewPass */;
      resetPreOrderHookFlags(lView);
      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;
      ngDevMode &&
          assertEqual(tView.type == 2 /* Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
      lView[DECLARATION_COMPONENT_VIEW] =
          tView.type == 2 /* Embedded */ ? parentLView[DECLARATION_COMPONENT_VIEW] : lView;
      ngDevMode && attachLViewDebug(lView);
      return lView;
  }
  function getOrCreateTNode(tView, tHostNode, index, type, name, attrs) {
      // Keep this function short, so that the VM will inline it.
      var adjustedIndex = index + HEADER_OFFSET;
      var tNode = tView.data[adjustedIndex] ||
          createTNodeAtIndex(tView, tHostNode, adjustedIndex, type, name, attrs);
      setPreviousOrParentTNode(tNode, true);
      return tNode;
  }
  function createTNodeAtIndex(tView, tHostNode, adjustedIndex, type, name, attrs) {
      var previousOrParentTNode = getPreviousOrParentTNode();
      var isParent = getIsParent();
      var parent = isParent ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
      // Parents cannot cross component boundaries because components will be used in multiple places,
      // so it's only set if the view is the same.
      var parentInSameView = parent && parent !== tHostNode;
      var tParentNode = parentInSameView ? parent : null;
      var tNode = tView.data[adjustedIndex] =
          createTNode(tView, tParentNode, type, adjustedIndex, 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 (previousOrParentTNode) {
          if (isParent && previousOrParentTNode.child == null &&
              (tNode.parent !== null || previousOrParentTNode.type === 2 /* View */)) {
              // We are in the same view, which means we are adding content node to the parent view.
              previousOrParentTNode.child = tNode;
          }
          else if (!isParent) {
              previousOrParentTNode.next = tNode;
          }
      }
      return tNode;
  }
  function assignTViewNodeToLView(tView, tParentNode, index, lView) {
      // View nodes are not stored in data because they can be added / removed at runtime (which
      // would cause indices to change). Their TNodes are instead stored in tView.node.
      var tNode = tView.node;
      if (tNode == null) {
          ngDevMode && tParentNode &&
              assertNodeOfPossibleTypes(tParentNode, 3 /* Element */, 0 /* Container */);
          tView.node = tNode = createTNode(tView, tParentNode, //
          2 /* View */, index, null, null);
      }
      return lView[T_HOST] = tNode;
  }
  /**
   * When elements are created dynamically after a view blueprint is created (e.g. through
   * i18nApply() or ComponentFactory.create), we need to adjust the blueprint for future
   * template passes.
   *
   * @param tView `TView` associated with `LView`
   * @param view The `LView` containing the blueprint to adjust
   * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0
   */
  function allocExpando(tView, lView, numSlotsToAlloc) {
      ngDevMode &&
          assertGreaterThan(numSlotsToAlloc, 0, 'The number of slots to alloc should be greater than 0');
      if (numSlotsToAlloc > 0) {
          if (tView.firstCreatePass) {
              for (var i = 0; i < numSlotsToAlloc; i++) {
                  tView.blueprint.push(null);
                  tView.data.push(null);
                  lView.push(null);
              }
              // We should only increment the expando start index if there aren't already directives
              // and injectors saved in the "expando" section
              if (!tView.expandoInstructions) {
                  tView.expandoStartIndex += numSlotsToAlloc;
              }
              else {
                  // Since we're adding the dynamic nodes into the expando section, we need to let the host
                  // bindings know that they should skip x slots
                  tView.expandoInstructions.push(numSlotsToAlloc);
              }
          }
      }
  }
  //////////////////////////
  //// 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, lView[T_HOST]);
      try {
          var viewQuery = tView.viewQuery;
          if (viewQuery !== null) {
              executeViewQueryFn(1 /* 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.
          var templateFn = tView.template;
          if (templateFn !== null) {
              executeTemplate(tView, lView, templateFn, 1 /* 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 /* Update */, tView.viewQuery, context);
          }
          // Render child component views.
          var 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;
          }
          throw error;
      }
      finally {
          lView[FLAGS] &= ~4 /* 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');
      var flags = lView[FLAGS];
      if ((flags & 256 /* Destroyed */) === 256 /* Destroyed */)
          return;
      enterView(lView, lView[T_HOST]);
      var checkNoChangesMode = getCheckNoChangesMode();
      try {
          resetPreOrderHookFlags(lView);
          setBindingIndex(tView.bindingStartIndex);
          if (templateFn !== null) {
              executeTemplate(tView, lView, templateFn, 2 /* Update */, context);
          }
          var hooksInitPhaseCompleted = (flags & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;
          // execute pre-order hooks (OnInit, OnChanges, DoCheck)
          // PERF WARNING: do NOT extract this to a separate function without running benchmarks
          if (!checkNoChangesMode) {
              if (hooksInitPhaseCompleted) {
                  var preOrderCheckHooks = tView.preOrderCheckHooks;
                  if (preOrderCheckHooks !== null) {
                      executeCheckHooks(lView, preOrderCheckHooks, null);
                  }
              }
              else {
                  var preOrderHooks = tView.preOrderHooks;
                  if (preOrderHooks !== null) {
                      executeInitAndCheckHooks(lView, preOrderHooks, 0 /* OnInitHooksToBeRun */, null);
                  }
                  incrementInitPhaseFlags(lView, 0 /* 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);
          refreshDynamicEmbeddedViews(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 (!checkNoChangesMode) {
              if (hooksInitPhaseCompleted) {
                  var contentCheckHooks = tView.contentCheckHooks;
                  if (contentCheckHooks !== null) {
                      executeCheckHooks(lView, contentCheckHooks);
                  }
              }
              else {
                  var contentHooks = tView.contentHooks;
                  if (contentHooks !== null) {
                      executeInitAndCheckHooks(lView, contentHooks, 1 /* AfterContentInitHooksToBeRun */);
                  }
                  incrementInitPhaseFlags(lView, 1 /* AfterContentInitHooksToBeRun */);
              }
          }
          setHostBindingsByExecutingExpandoInstructions(tView, lView);
          // Refresh child component views.
          var 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.
          var viewQuery = tView.viewQuery;
          if (viewQuery !== null) {
              executeViewQueryFn(2 /* Update */, viewQuery, context);
          }
          // execute view hooks (AfterViewInit, AfterViewChecked)
          // PERF WARNING: do NOT extract this to a separate function without running benchmarks
          if (!checkNoChangesMode) {
              if (hooksInitPhaseCompleted) {
                  var viewCheckHooks = tView.viewCheckHooks;
                  if (viewCheckHooks !== null) {
                      executeCheckHooks(lView, viewCheckHooks);
                  }
              }
              else {
                  var viewHooks = tView.viewHooks;
                  if (viewHooks !== null) {
                      executeInitAndCheckHooks(lView, viewHooks, 2 /* AfterViewInitHooksToBeRun */);
                  }
                  incrementInitPhaseFlags(lView, 2 /* 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 (!checkNoChangesMode) {
              lView[FLAGS] &= ~(64 /* Dirty */ | 8 /* FirstLViewPass */);
          }
          if (lView[FLAGS] & 1024 /* RefreshTransplantedView */) {
              lView[FLAGS] &= ~1024 /* RefreshTransplantedView */;
              updateTransplantedViewCount(lView[PARENT], -1);
          }
      }
      finally {
          leaveView();
      }
  }
  function renderComponentOrTemplate(tView, lView, templateFn, context) {
      var rendererFactory = lView[RENDERER_FACTORY];
      var normalExecutionPath = !getCheckNoChangesMode();
      var creationModeIsActive = isCreationMode(lView);
      try {
          if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
              rendererFactory.begin();
          }
          if (creationModeIsActive) {
              renderView(tView, lView, context);
          }
          refreshView(tView, lView, templateFn, context);
      }
      finally {
          if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
              rendererFactory.end();
          }
      }
  }
  function executeTemplate(tView, lView, templateFn, rf, context) {
      var prevSelectedIndex = getSelectedIndex();
      try {
          setSelectedIndex(-1);
          if (rf & 2 /* Update */ && 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, 0, getCheckNoChangesMode());
          }
          templateFn(rf, context);
      }
      finally {
          setSelectedIndex(prevSelectedIndex);
      }
  }
  //////////////////////////
  //// Element
  //////////////////////////
  function executeContentQueries(tView, tNode, lView) {
      if (isContentQueryHost(tNode)) {
          var start = tNode.directiveStart;
          var end = tNode.directiveEnd;
          for (var directiveIndex = start; directiveIndex < end; directiveIndex++) {
              var def = tView.data[directiveIndex];
              if (def.contentQueries) {
                  def.contentQueries(1 /* 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 /* hasHostBindings */) === 128 /* 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) {
      if (localRefExtractor === void 0) { localRefExtractor = getNativeByTNode; }
      var localNames = tNode.localNames;
      if (localNames !== null) {
          var localIndex = tNode.index + 1;
          for (var i = 0; i < localNames.length; i += 2) {
              var index = localNames[i + 1];
              var 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 getOrCreateTComponentView(def) {
      var tView = def.tView;
      // Create a TView if there isn't one, or recreate it if the first create pass didn't
      // complete successfuly since we can't know for sure whether it's in a usable shape.
      if (tView === null || tView.incompleteFirstPass) {
          return def.tView = createTView(1 /* Component */, -1, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts);
      }
      return tView;
  }
  /**
   * Creates a TView instance
   *
   * @param viewIndex The viewBlockId for inline views, or -1 if it's a component/dynamic
   * @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, viewIndex, templateFn, decls, vars, directives, pipes, viewQuery, schemas, consts) {
      ngDevMode && ngDevMode.tView++;
      var 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.
      var initialViewLength = bindingStartIndex + vars;
      var blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
      return blueprint[TVIEW] = ngDevMode ?
          new TViewConstructor(type, viewIndex, // id: number,
          blueprint, // blueprint: LView,
          templateFn, // template: ComponentTemplate<{}>|null,
          null, // queries: TQueries|null
          viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
          null, // node: TViewNode|TElementNode|null,
          cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
          bindingStartIndex, // bindingStartIndex: number,
          initialViewLength, // expandoStartIndex: number,
          null, // expandoInstructions: ExpandoInstructions|null,
          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
          ) :
          {
              type: type,
              id: viewIndex,
              blueprint: blueprint,
              template: templateFn,
              queries: null,
              viewQuery: viewQuery,
              node: null,
              data: blueprint.slice().fill(null, bindingStartIndex),
              bindingStartIndex: bindingStartIndex,
              expandoStartIndex: initialViewLength,
              expandoInstructions: 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
          };
  }
  function createViewBlueprint(bindingStartIndex, initialViewLength) {
      var blueprint = ngDevMode ? new LViewBlueprint() : [];
      for (var 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) + "]");
  }
  function assertHostNodeExists(rElement, elementOrSelector) {
      if (!rElement) {
          if (typeof elementOrSelector === 'string') {
              throw createError('Host node with selector not found:', elementOrSelector);
          }
          else {
              throw createError('Host node is required:', elementOrSelector);
          }
      }
  }
  /**
   * 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) {
      if (isProceduralRenderer(renderer)) {
          // When using native Shadow DOM, do not clear host element to allow native slot projection
          var preserveContent = encapsulation === exports.ViewEncapsulation.ShadowDom;
          return renderer.selectRootElement(elementOrSelector, preserveContent);
      }
      var rElement = typeof elementOrSelector === 'string' ?
          renderer.querySelector(elementOrSelector) :
          elementOrSelector;
      ngDevMode && assertHostNodeExists(rElement, elementOrSelector);
      // Always clear host element's content when Renderer3 is in use. For procedural renderer case we
      // make it depend on whether ShadowDom encapsulation is used (in which case the content should be
      // preserved to allow native slot projection). ShadowDom encapsulation requires procedural
      // renderer, and procedural renderer case is handled above.
      rElement.textContent = '';
      return rElement;
  }
  /**
   * 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
   */
  function storeCleanupWithContext(tView, lView, context, cleanupFn) {
      var lCleanup = getLCleanup(lView);
      lCleanup.push(context);
      if (tView.firstCreatePass) {
          getTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
      }
  }
  /**
   * Saves the cleanup function itself in LView.cleanupInstances.
   *
   * This is necessary for functions that are wrapped with their contexts, like in renderer2
   * listeners.
   *
   * On the first template pass, the index of the cleanup function is saved in TView.
   */
  function storeCleanupFn(tView, lView, cleanupFn) {
      getLCleanup(lView).push(cleanupFn);
      if (tView.firstCreatePass) {
          getTViewCleanup(tView).push(lView[CLEANUP].length - 1, null);
      }
  }
  /**
   * Constructs a TNode object from the arguments.
   *
   * @param tView `TView` to which this `TNode` belongs (used only in `ngDevMode`)
   * @param type The type of the node
   * @param adjustedIndex The index of the TNode in TView.data, adjusted for HEADER_OFFSET
   * @param tagName The tag name of the node
   * @param attrs The attributes defined on this node
   * @param tViews Any TViews attached to this node
   * @returns the TNode object
   */
  function createTNode(tView, tParent, type, adjustedIndex, tagName, attrs) {
      ngDevMode && ngDevMode.tNode++;
      var injectorIndex = tParent ? tParent.injectorIndex : -1;
      return ngDevMode ? new TNodeDebug(tView, // tView_: TView
      type, // type: TNodeType
      adjustedIndex, // index: number
      injectorIndex, // injectorIndex: number
      -1, // directiveStart: number
      -1, // directiveEnd: number
      -1, // directiveStylingLast: number
      null, // propertyBindings: number[]|null
      0, // flags: TNodeFlags
      0, // providerIndexes: TNodeProviderIndexes
      tagName, // tagName: 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
      undefined, // residualStyles: string|null
      null, // classes: string|null
      undefined, // residualClasses: string|null
      0, // classBindings: TStylingRange;
      0) :
          {
              type: type,
              index: adjustedIndex,
              injectorIndex: injectorIndex,
              directiveStart: -1,
              directiveEnd: -1,
              directiveStylingLast: -1,
              propertyBindings: null,
              flags: 0,
              providerIndexes: 0,
              tagName: tagName,
              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,
              residualStyles: undefined,
              classes: null,
              residualClasses: undefined,
              classBindings: 0,
              styleBindings: 0,
          };
  }
  function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) {
      for (var publicName in inputAliasMap) {
          if (inputAliasMap.hasOwnProperty(publicName)) {
              propStore = propStore === null ? {} : propStore;
              var 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 outputs and outputs.
   * Initialization is done for all directives matched on a given TNode.
   */
  function initializeInputAndOutputAliases(tView, tNode) {
      ngDevMode && assertFirstCreatePass(tView);
      var start = tNode.directiveStart;
      var end = tNode.directiveEnd;
      var defs = tView.data;
      var tNodeAttrs = tNode.attrs;
      var inputsFromAttrs = ngDevMode ? new TNodeInitialInputs() : [];
      var inputsStore = null;
      var outputsStore = null;
      for (var i = start; i < end; i++) {
          var directiveDef = defs[i];
          var 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.
          var 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 /* hasClassInput */;
          }
          if (inputsStore.hasOwnProperty('style')) {
              tNode.flags |= 32 /* 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.');
      var element = getNativeByTNode(tNode, lView);
      var inputData = tNode.inputs;
      var 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 /* Element */) {
          propName = mapPropName(propName);
          if (ngDevMode) {
              validateAgainstEventProperties(propName);
              if (!validateProperty(tView, lView, element, propName, tNode)) {
                  // Return here since we only log warnings for unknown properties.
                  warnAboutUnknownProperty(propName, tNode);
                  return;
              }
              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.tagName || '', propName) : value;
          if (isProceduralRenderer(renderer)) {
              renderer.setProperty(element, propName, value);
          }
          else if (!isAnimationProp(propName)) {
              element.setProperty ? element.setProperty(propName, value) :
                  element[propName] = value;
          }
      }
      else if (tNode.type === 0 /* Container */) {
          // 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, lView, tNode.tagName)) {
              warnAboutUnknownProperty(propName, tNode);
          }
      }
  }
  /** If node is an OnPush component, marks its LView dirty. */
  function markDirtyIfOnPush(lView, viewIndex) {
      ngDevMode && assertLView(lView);
      var childComponentLView = getComponentLViewByIndex(viewIndex, lView);
      if (!(childComponentLView[FLAGS] & 16 /* CheckAlways */)) {
          childComponentLView[FLAGS] |= 64 /* Dirty */;
      }
  }
  function setNgReflectProperty(lView, element, type, attrName, value) {
      var _a;
      var renderer = lView[RENDERER];
      attrName = normalizeDebugBindingName(attrName);
      var debugValue = normalizeDebugBindingValue(value);
      if (type === 3 /* Element */) {
          if (value == null) {
              isProceduralRenderer(renderer) ? renderer.removeAttribute(element, attrName) :
                  element.removeAttribute(attrName);
          }
          else {
              isProceduralRenderer(renderer) ?
                  renderer.setAttribute(element, attrName, debugValue) :
                  element.setAttribute(attrName, debugValue);
          }
      }
      else {
          var textContent = "bindings=" + JSON.stringify((_a = {}, _a[attrName] = debugValue, _a), null, 2);
          if (isProceduralRenderer(renderer)) {
              renderer.setValue(element, textContent);
          }
          else {
              element.textContent = textContent;
          }
      }
  }
  function setNgReflectProperties(lView, element, type, dataValue, value) {
      if (type === 3 /* Element */ || type === 0 /* 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 (var i = 0; i < dataValue.length; i += 2) {
              setNgReflectProperty(lView, element, type, dataValue[i + 1], value);
          }
      }
  }
  function validateProperty(tView, lView, element, propName, tNode) {
      // 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 (tView.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(tView, lView, tNode.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 for `typeof null` also returning 'object'.
      return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
  }
  function matchingSchemas(tView, lView, tagName) {
      var schemas = tView.schemas;
      if (schemas !== null) {
          for (var i = 0; i < schemas.length; i++) {
              var schema = schemas[i];
              if (schema === NO_ERRORS_SCHEMA ||
                  schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
                  return true;
              }
          }
      }
      return false;
  }
  /**
   * Logs a warning that a property is not supported on an element.
   * @param propName Name of the invalid property.
   * @param tNode Node on which we encountered the property.
   */
  function warnAboutUnknownProperty(propName, tNode) {
      console.warn("Can't bind to '" + propName + "' since it isn't a known property of '" + tNode.tagName + "'.");
  }
  /**
   * Instantiate a root component.
   */
  function instantiateRootComponent(tView, lView, def) {
      var rootTNode = getPreviousOrParentTNode();
      if (tView.firstCreatePass) {
          if (def.providersResolver)
              def.providersResolver(def);
          generateExpandoInstructionBlock(tView, rootTNode, 1);
          baseResolveDirective(tView, lView, def);
      }
      var directive = getNodeInjectable(lView, tView, lView.length - 1, rootTNode);
      attachPatchData(directive, lView);
      var 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);
      var hasDirectives = false;
      if (getBindingsEnabled()) {
          var directiveDefs = findDirectiveDefMatches(tView, lView, tNode);
          var exportsMap = localRefs === null ? null : { '': -1 };
          if (directiveDefs !== null) {
              var totalDirectiveHostVars = 0;
              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 (var i = 0; i < directiveDefs.length; i++) {
                  var def = directiveDefs[i];
                  if (def.providersResolver)
                      def.providersResolver(def);
              }
              generateExpandoInstructionBlock(tView, tNode, directiveDefs.length);
              var preOrderHooksFound = false;
              var preOrderCheckHooksFound = false;
              for (var i = 0; i < directiveDefs.length; i++) {
                  var 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);
                  baseResolveDirective(tView, lView, def);
                  saveNameToExportMap(tView.data.length - 1, def, exportsMap);
                  if (def.contentQueries !== null)
                      tNode.flags |= 8 /* hasContentQuery */;
                  if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0)
                      tNode.flags |= 128 /* hasHostBindings */;
                  // Only push a node index into the preOrderHooks array if this is the first
                  // pre-order hook found on this node.
                  if (!preOrderHooksFound && (def.onChanges || def.onInit || def.doCheck)) {
                      // 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 - HEADER_OFFSET);
                      preOrderHooksFound = true;
                  }
                  if (!preOrderCheckHooksFound && (def.onChanges || def.doCheck)) {
                      (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = []))
                          .push(tNode.index - HEADER_OFFSET);
                      preOrderCheckHooksFound = true;
                  }
                  addHostBindingsToExpandoInstructions(tView, def);
                  totalDirectiveHostVars += def.hostVars;
              }
              initializeInputAndOutputAliases(tView, tNode);
              growHostVarsSpace(tView, lView, totalDirectiveHostVars);
          }
          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.expandoInstructions`.
   *
   * @param tView `TView` to which the `hostBindings` should be added.
   * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add.
   */
  function addHostBindingsToExpandoInstructions(tView, def) {
      ngDevMode && assertFirstCreatePass(tView);
      var expando = tView.expandoInstructions;
      // TODO(misko): PERF we are adding `hostBindings` even if there is nothing to add! This is
      // suboptimal for performance. `def.hostBindings` may be null,
      // but we still need to push null to the array as a placeholder
      // to ensure the directive counter is incremented (so host
      // binding functions always line up with the corrective directive).
      // This is suboptimal for performance. See `currentDirectiveIndex`
      //  comment in `setHostBindingsByExecutingExpandoInstructions` for more
      // details.  expando.push(def.hostBindings);
      expando.push(def.hostBindings);
      var hostVars = def.hostVars;
      if (hostVars !== 0) {
          expando.push(def.hostVars);
      }
  }
  /**
   * Grow the `LView`, blueprint and `TView.data` to accommodate the `hostBindings`.
   *
   * To support locality we don't know ahead of time how many `hostVars` of the containing directives
   * we need to allocate. For this reason we allow growing these data structures as we discover more
   * directives to accommodate them.
   *
   * @param tView `TView` which needs to be grown.
   * @param lView `LView` which needs to be grown.
   * @param count Size by which we need to grow the data structures.
   */
  function growHostVarsSpace(tView, lView, count) {
      ngDevMode && assertFirstCreatePass(tView);
      ngDevMode && assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!');
      for (var i = 0; i < count; i++) {
          lView.push(NO_CHANGE);
          tView.blueprint.push(NO_CHANGE);
          tView.data.push(null);
      }
  }
  /**
   * Instantiate all the directives that were previously resolved on the current node.
   */
  function instantiateAllDirectives(tView, lView, tNode, native) {
      var start = tNode.directiveStart;
      var end = tNode.directiveEnd;
      if (!tView.firstCreatePass) {
          getOrCreateNodeInjectorForNode(tNode, lView);
      }
      attachPatchData(native, lView);
      var initialInputs = tNode.initialInputs;
      for (var i = start; i < end; i++) {
          var def = tView.data[i];
          var isComponent = isComponentDef(def);
          if (isComponent) {
              ngDevMode && assertNodeOfPossibleTypes(tNode, 3 /* Element */);
              addComponentLogic(lView, tNode, def);
          }
          var directive = getNodeInjectable(lView, tView, i, tNode);
          attachPatchData(directive, lView);
          if (initialInputs !== null) {
              setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs);
          }
          if (isComponent) {
              var componentView = getComponentLViewByIndex(tNode.index, lView);
              componentView[CONTEXT] = directive;
          }
      }
  }
  function invokeDirectivesHostBindings(tView, lView, tNode) {
      var start = tNode.directiveStart;
      var end = tNode.directiveEnd;
      var expando = tView.expandoInstructions;
      var firstCreatePass = tView.firstCreatePass;
      var elementIndex = tNode.index - HEADER_OFFSET;
      var currentDirectiveIndex = getCurrentDirectiveIndex();
      try {
          setSelectedIndex(elementIndex);
          for (var dirIndex = start; dirIndex < end; dirIndex++) {
              var def = tView.data[dirIndex];
              var directive = lView[dirIndex];
              setCurrentDirectiveIndex(dirIndex);
              if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
                  invokeHostBindingsInCreationMode(def, directive);
              }
              else if (firstCreatePass) {
                  expando.push(null);
              }
          }
      }
      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 /* Create */, directive);
      }
  }
  /**
   * Generates a new block in TView.expandoInstructions for this node.
   *
   * Each expando block starts with the element index (turned negative so we can distinguish
   * it from the hostVar count) and the directive count. See more in VIEW_DATA.md.
   */
  function generateExpandoInstructionBlock(tView, tNode, directiveCount) {
      ngDevMode &&
          assertEqual(tView.firstCreatePass, true, 'Expando block should only be generated on first create pass.');
      // Important: In JS `-x` and `0-x` is not the same! If `x===0` then `-x` will produce `-0` which
      // requires non standard math arithmetic and it can prevent VM optimizations.
      // `0-0` will always produce `0` and will not cause a potential deoptimization in VM.
      var elementIndex = HEADER_OFFSET - tNode.index;
      var providerStartIndex = tNode.providerIndexes & 65535 /* ProvidersStartIndexMask */;
      var providerCount = tView.data.length - providerStartIndex;
      (tView.expandoInstructions || (tView.expandoInstructions = []))
          .push(elementIndex, providerCount, directiveCount);
  }
  /**
   * 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 &&
          assertNodeOfPossibleTypes(tNode, 3 /* Element */, 4 /* ElementContainer */, 0 /* Container */);
      var registry = tView.directiveRegistry;
      var matches = null;
      if (registry) {
          for (var i = 0; i < registry.length; i++) {
              var 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 (tNode.flags & 2 /* isComponentHost */)
                          throwMultipleComponentError(tNode);
                      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 /* 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) {
          var 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 (var i = 0; i < localRefs.length; i += 2) {
              var index = exportsMap[localRefs[i + 1]];
              if (index == null)
                  throw new Error("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(index, def, exportsMap) {
      if (exportsMap) {
          if (def.exportAs) {
              for (var i = 0; i < def.exportAs.length; i++) {
                  exportsMap[def.exportAs[i]] = index;
              }
          }
          if (isComponentDef(def))
              exportsMap[''] = index;
      }
  }
  /**
   * 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 /* isDirectiveHost */;
      // When the first directive is created on a node, save the index
      tNode.directiveStart = index;
      tNode.directiveEnd = index + numberOfDirectives;
      tNode.providerIndexes = index;
  }
  function baseResolveDirective(tView, viewData, def) {
      tView.data.push(def);
      var directiveFactory = def.factory || (def.factory = getFactoryDef(def.type, true));
      var nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null);
      tView.blueprint.push(nodeInjectorFactory);
      viewData.push(nodeInjectorFactory);
  }
  function addComponentLogic(lView, hostTNode, def) {
      var native = getNativeByTNode(hostTNode, lView);
      var tView = getOrCreateTComponentView(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.
      var rendererFactory = lView[RENDERER_FACTORY];
      var componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 64 /* Dirty */ : 16 /* CheckAlways */, native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def)));
      // 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) {
      ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
      ngDevMode && validateAgainstEventAttributes(name);
      var element = getNativeByTNode(tNode, lView);
      var renderer = lView[RENDERER];
      if (value == null) {
          ngDevMode && ngDevMode.rendererRemoveAttribute++;
          isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) :
              element.removeAttribute(name);
      }
      else {
          ngDevMode && ngDevMode.rendererSetAttribute++;
          var strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tNode.tagName || '', name);
          if (isProceduralRenderer(renderer)) {
              renderer.setAttribute(element, name, strValue, namespace);
          }
          else {
              namespace ? element.setAttributeNS(namespace, name, strValue) :
                  element.setAttribute(name, strValue);
          }
      }
  }
  /**
   * 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) {
      var initialInputs = initialInputData[directiveIndex];
      if (initialInputs !== null) {
          var setInput = def.setInput;
          for (var i = 0; i < initialInputs.length;) {
              var publicName = initialInputs[i++];
              var privateName = initialInputs[i++];
              var value = initialInputs[i++];
              if (setInput !== null) {
                  def.setInput(instance, value, publicName, privateName);
              }
              else {
                  instance[privateName] = value;
              }
              if (ngDevMode) {
                  var 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) {
      var inputsToStore = null;
      var i = 0;
      while (i < attrs.length) {
          var attrName = attrs[i];
          if (attrName === 0 /* NamespaceURI */) {
              // We do not allow inputs on namespaced attributes.
              i += 4;
              continue;
          }
          else if (attrName === 5 /* 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.
  var LContainerArray = ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) &&
      createNamedArrayType('LContainer');
  /**
   * 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);
      ngDevMode && !isProceduralRenderer(currentView[RENDERER]) && assertDomNode(native);
      // https://jsperf.com/array-literal-vs-new-array-really
      var lContainer = new (ngDevMode ? LContainerArray : Array)(hostNative, // host native
      true, // Boolean `true` in this position signifies that this is an `LContainer`
      -1 /* DYNAMIC_EMBEDDED_VIEWS_ONLY */ << 1 /* SHIFT */, // active index
      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 dynamic embedded views (ones created through ViewContainerRef APIs) and refreshes
   * them by executing an associated template function.
   */
  function refreshDynamicEmbeddedViews(lView) {
      for (var lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
          for (var i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
              var embeddedLView = lContainer[i];
              var embeddedTView = embeddedLView[TVIEW];
              ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
              if (viewAttachedToChangeDetector(embeddedLView)) {
                  refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
              }
          }
      }
  }
  /**
   * Gets the first `LContainer` in the LView or `null` if none exists.
   */
  function getFirstLContainer(lView) {
      var viewOrContainer = lView[CHILD_HEAD];
      while (viewOrContainer !== null &&
          !(isLContainer(viewOrContainer) &&
              viewOrContainer[ACTIVE_INDEX] >> 1 /* SHIFT */ ===
                  -1 /* DYNAMIC_EMBEDDED_VIEWS_ONLY */)) {
          viewOrContainer = viewOrContainer[NEXT];
      }
      return viewOrContainer;
  }
  /**
   * Gets the next `LContainer` that is a sibling of the given container.
   */
  function getNextLContainer(container) {
      var viewOrContainer = container[NEXT];
      while (viewOrContainer !== null &&
          !(isLContainer(viewOrContainer) &&
              viewOrContainer[ACTIVE_INDEX] >> 1 /* SHIFT */ ===
                  -1 /* DYNAMIC_EMBEDDED_VIEWS_ONLY */)) {
          viewOrContainer = viewOrContainer[NEXT];
      }
      return viewOrContainer;
  }
  /**
   * Mark transplanted views as needing to be refreshed at their insertion points.
   *
   * See: `ActiveIndexFlag.HAS_TRANSPLANTED_VIEWS` and `LView[DECLARATION_COMPONENT_VIEW]` for
   * explanation of transplanted views.
   *
   * @param lView The `LView` that may have transplanted views.
   */
  function markTransplantedViewsForRefresh(lView) {
      for (var lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
          if ((lContainer[ACTIVE_INDEX] & 1 /* HAS_TRANSPLANTED_VIEWS */) !== 0) {
              var movedViews = lContainer[MOVED_VIEWS];
              ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS');
              for (var i = 0; i < movedViews.length; i++) {
                  var movedLView = movedViews[i];
                  var 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] & 1024 /* 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
                  // `refreshDynamicEmbeddedViews` for the view currently being refreshed.
                  movedLView[FLAGS] |= 1024 /* 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');
      var componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
      // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
      if (viewAttachedToChangeDetector(componentView)) {
          var tView = componentView[TVIEW];
          if (componentView[FLAGS] & (16 /* CheckAlways */ | 64 /* 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 (var lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
          for (var i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
              var embeddedLView = lContainer[i];
              if (embeddedLView[FLAGS] & 1024 /* RefreshTransplantedView */) {
                  var 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);
              }
          }
      }
      var tView = lView[TVIEW];
      // Refresh child component views.
      var components = tView.components;
      if (components !== null) {
          for (var i = 0; i < components.length; i++) {
              var 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');
      var componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
      var 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 (var 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] |= 64 /* Dirty */;
          var parent_1 = getLViewParent(lView);
          // Stop traversing up as soon as you find a root view that wasn't attached to any container
          if (isRootView(lView) && !parent_1) {
              return lView;
          }
          // continue otherwise
          lView = parent_1;
      }
      return null;
  }
  /**
   * Used to schedule change detection on the whole application.
   *
   * Unlike `tick`, `scheduleTick` coalesces multiple calls into one change detection run.
   * It is usually called indirectly by calling `markDirty` when the view needs to be
   * re-rendered.
   *
   * Typically `scheduleTick` uses `requestAnimationFrame` to coalesce multiple
   * `scheduleTick` requests. The scheduling function can be overridden in
   * `renderComponent`'s `scheduler` option.
   */
  function scheduleTick(rootContext, flags) {
      var nothingScheduled = rootContext.flags === 0 /* Empty */;
      rootContext.flags |= flags;
      if (nothingScheduled && rootContext.clean == _CLEAN_PROMISE) {
          var res_1;
          rootContext.clean = new Promise(function (r) { return res_1 = r; });
          rootContext.scheduler(function () {
              if (rootContext.flags & 1 /* DetectChanges */) {
                  rootContext.flags &= ~1 /* DetectChanges */;
                  tickRootContext(rootContext);
              }
              if (rootContext.flags & 2 /* FlushPlayers */) {
                  rootContext.flags &= ~2 /* FlushPlayers */;
                  var playerHandler = rootContext.playerHandler;
                  if (playerHandler) {
                      playerHandler.flushPlayers();
                  }
              }
              rootContext.clean = _CLEAN_PROMISE;
              res_1(null);
          });
      }
  }
  function tickRootContext(rootContext) {
      for (var i = 0; i < rootContext.components.length; i++) {
          var rootComponent = rootContext.components[i];
          var lView = readPatchedLView(rootComponent);
          var tView = lView[TVIEW];
          renderComponentOrTemplate(tView, lView, tView.template, rootComponent);
      }
  }
  function detectChangesInternal(tView, lView, context) {
      var rendererFactory = lView[RENDERER_FACTORY];
      if (rendererFactory.begin)
          rendererFactory.begin();
      try {
          refreshView(tView, lView, tView.template, context);
      }
      catch (error) {
          handleError(lView, error);
          throw error;
      }
      finally {
          if (rendererFactory.end)
              rendererFactory.end();
      }
  }
  /**
   * Synchronously perform change detection on a root view and its components.
   *
   * @param lView The view which the change detection should be performed on.
   */
  function detectChangesInRootView(lView) {
      tickRootContext(lView[CONTEXT]);
  }
  function checkNoChangesInternal(tView, view, context) {
      setCheckNoChangesMode(true);
      try {
          detectChangesInternal(tView, view, context);
      }
      finally {
          setCheckNoChangesMode(false);
      }
  }
  /**
   * Checks the change detector on a root view and its components, and throws if any changes are
   * detected.
   *
   * This is used in development mode to verify that running change detection doesn't
   * introduce other changes.
   *
   * @param lView The view which the change detection should be checked on.
   */
  function checkNoChangesInRootView(lView) {
      setCheckNoChangesMode(true);
      try {
          detectChangesInRootView(lView);
      }
      finally {
          setCheckNoChangesMode(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) {
      var interpolationParts = [];
      for (var _i = 4; _i < arguments.length; _i++) {
          interpolationParts[_i - 4] = arguments[_i];
      }
      // 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]) {
              var propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
              propBindingIdxs.push(bindingIndex);
              var bindingMetadata = propertyName;
              if (interpolationParts.length > 0) {
                  bindingMetadata +=
                      INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
              }
              tData[bindingIndex] = bindingMetadata;
          }
      }
  }
  var CLEAN_PROMISE = _CLEAN_PROMISE;
  function getLCleanup(view) {
      // top level variables should not be exported for performance reasons (PERF_NOTES.md)
      return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []);
  }
  function getTViewCleanup(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) {
      var injector = lView[INJECTOR$1];
      var 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 (var i = 0; i < inputs.length;) {
          var index = inputs[i++];
          var privateName = inputs[i++];
          var instance = lView[index];
          ngDevMode && assertDataInRange(lView, index);
          var 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 && assertNotSame(value, NO_CHANGE, 'value should not be NO_CHANGE');
      ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
      var element = getNativeByIndex(index, lView);
      ngDevMode && assertDefined(element, 'native element should exist');
      ngDevMode && ngDevMode.rendererSetText++;
      var renderer = lView[RENDERER];
      isProceduralRenderer(renderer) ? renderer.setValue(element, value) : element.textContent = value;
  }

  /**
   * @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
   */
  var unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$2 + unusedValueExportToPlacateAjd;
  function getLContainer(tNode, embeddedView) {
      ngDevMode && assertLView(embeddedView);
      var container = embeddedView[PARENT];
      if (tNode.index === -1) {
          // This is a dynamically created view inside a dynamic container.
          // The parent isn't an LContainer if the embedded view hasn't been attached yet.
          return isLContainer(container) ? container : null;
      }
      else {
          ngDevMode && assertLContainer(container);
          // This is a inline view node (e.g. embeddedViewStart)
          return container;
      }
  }
  /**
   * Retrieves render parent for a given view.
   * Might be null if a view is not yet attached to any container.
   */
  function getContainerRenderParent(tViewNode, view) {
      var container = getLContainer(tViewNode, view);
      return container ? nativeParentNode(view[RENDERER], container[NATIVE]) : null;
  }
  /**
   * 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) {
          var lContainer = void 0;
          var 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];
          }
          var rNode = unwrapRNode(lNodeToHandle);
          ngDevMode && !isProceduralRenderer(renderer) && assertDomNode(rNode);
          if (action === 0 /* Create */ && parent !== null) {
              if (beforeNode == null) {
                  nativeAppendChild(renderer, parent, rNode);
              }
              else {
                  nativeInsertBefore(renderer, parent, rNode, beforeNode || null);
              }
          }
          else if (action === 1 /* Insert */ && parent !== null) {
              nativeInsertBefore(renderer, parent, rNode, beforeNode || null);
          }
          else if (action === 2 /* Detach */) {
              nativeRemoveNode(renderer, rNode, isComponent);
          }
          else if (action === 3 /* Destroy */) {
              ngDevMode && ngDevMode.rendererDestroyNode++;
              renderer.destroyNode(rNode);
          }
          if (lContainer != null) {
              applyContainer(renderer, action, lContainer, parent, beforeNode);
          }
      }
  }
  function createTextNode(value, renderer) {
      ngDevMode && ngDevMode.rendererCreateTextNode++;
      ngDevMode && ngDevMode.rendererSetText++;
      return isProceduralRenderer(renderer) ? renderer.createText(value) :
          renderer.createTextNode(value);
  }
  function addRemoveViewFromContainer(tView, lView, insertMode, beforeNode) {
      var renderParent = getContainerRenderParent(tView.node, lView);
      ngDevMode && assertNodeType(tView.node, 2 /* View */);
      if (renderParent) {
          var renderer = lView[RENDERER];
          var action = insertMode ? 1 /* Insert */ : 2 /* Detach */;
          applyView(tView, lView, renderer, action, renderParent, 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 /* 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.
      var lViewOrLContainer = rootView[CHILD_HEAD];
      if (!lViewOrLContainer) {
          return cleanUpView(rootView[TVIEW], rootView);
      }
      while (lViewOrLContainer) {
          var 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.
              var 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) {
                  isLView(lViewOrLContainer) && cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
                  lViewOrLContainer = getParentState(lViewOrLContainer, rootView);
              }
              if (lViewOrLContainer === null)
                  lViewOrLContainer = rootView;
              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);
      var indexInContainer = CONTAINER_HEADER_OFFSET + index;
      var 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
      var declarationLContainer = lView[DECLARATION_LCONTAINER];
      if (declarationLContainer !== null && lContainer !== declarationLContainer) {
          trackMovedView(declarationLContainer, lView);
      }
      // notify query that a new view has been added
      var lQueries = lView[QUERIES];
      if (lQueries !== null) {
          lQueries.insertView(tView);
      }
      // Sets the attached flag
      lView[FLAGS] |= 128 /* 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);
      var movedViews = declarationContainer[MOVED_VIEWS];
      var insertedLContainer = lView[PARENT];
      ngDevMode && assertLContainer(insertedLContainer);
      var insertedComponentLView = insertedLContainer[PARENT][DECLARATION_COMPONENT_VIEW];
      ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView');
      var 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[ACTIVE_INDEX] |= 1 /* HAS_TRANSPLANTED_VIEWS */;
      }
      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');
      var movedViews = declarationContainer[MOVED_VIEWS];
      var declarationViewIndex = movedViews.indexOf(lView);
      var 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] & 1024 /* 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;
      var indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;
      var viewToDetach = lContainer[indexInContainer];
      if (viewToDetach) {
          var declarationLContainer = viewToDetach[DECLARATION_LCONTAINER];
          if (declarationLContainer !== null && declarationLContainer !== lContainer) {
              detachMovedView(declarationLContainer, viewToDetach);
          }
          if (removeIndex > 0) {
              lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT];
          }
          var removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);
          addRemoveViewFromContainer(viewToDetach[TVIEW], viewToDetach, false, null);
          // notify query that a view has been removed
          var lQueries = removedLView[QUERIES];
          if (lQueries !== null) {
              lQueries.detachView(removedLView[TVIEW]);
          }
          viewToDetach[PARENT] = null;
          viewToDetach[NEXT] = null;
          // Unsets the attached flag
          viewToDetach[FLAGS] &= ~128 /* Attached */;
      }
      return viewToDetach;
  }
  /**
   * Removes a view from a container, i.e. detaches it and then destroys the underlying LView.
   *
   * @param lContainer The container from which to remove a view
   * @param removeIndex The index of the view to remove
   */
  function removeView(lContainer, removeIndex) {
      var detachedView = detachView(lContainer, removeIndex);
      detachedView && destroyLView(detachedView[TVIEW], detachedView);
  }
  /**
   * 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] & 256 /* Destroyed */)) {
          var renderer = lView[RENDERER];
          if (isProceduralRenderer(renderer) && renderer.destroyNode) {
              applyView(tView, lView, renderer, 3 /* Destroy */, null, null);
          }
          destroyViewTree(lView);
      }
  }
  /**
   * Determines which LViewOrLContainer to jump to when traversing back up the
   * tree in destroyViewTree.
   *
   * Normally, the view's parent LView should be checked, but in the case of
   * embedded views, the container (which is the view node's parent, but not the
   * LView's parent) needs to be checked for a possible next property.
   *
   * @param lViewOrLContainer The LViewOrLContainer for which we need a parent state
   * @param rootView The rootView, so we don't propagate too far up the view tree
   * @returns The correct parent LViewOrLContainer
   */
  function getParentState(lViewOrLContainer, rootView) {
      var tNode;
      if (isLView(lViewOrLContainer) && (tNode = lViewOrLContainer[T_HOST]) &&
          tNode.type === 2 /* View */) {
          // if it's an embedded view, the state needs to go up to the container, in case the
          // container has a next
          return getLContainer(tNode, lViewOrLContainer);
      }
      else {
          // otherwise, use parent view for containers or component views
          return lViewOrLContainer[PARENT] === rootView ? null : lViewOrLContainer[PARENT];
      }
  }
  /**
   * 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] & 256 /* 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] &= ~128 /* 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] |= 256 /* Destroyed */;
          executeOnDestroys(tView, lView);
          removeListeners(tView, lView);
          var hostTNode = lView[T_HOST];
          // For component views only, the local renderer is destroyed as clean up time.
          if (hostTNode && hostTNode.type === 3 /* Element */ &&
              isProceduralRenderer(lView[RENDERER])) {
              ngDevMode && ngDevMode.rendererDestroy++;
              lView[RENDERER].destroy();
          }
          var 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.
              var lQueries = lView[QUERIES];
              if (lQueries !== null) {
                  lQueries.detachView(tView);
              }
          }
      }
  }
  /** Removes listeners and unsubscribes from output subscriptions */
  function removeListeners(tView, lView) {
      var tCleanup = tView.cleanup;
      if (tCleanup !== null) {
          var lCleanup = lView[CLEANUP];
          for (var i = 0; i < tCleanup.length - 1; i += 2) {
              if (typeof tCleanup[i] === 'string') {
                  // This is a native DOM listener
                  var idxOrTargetGetter = tCleanup[i + 1];
                  var target = typeof idxOrTargetGetter === 'function' ?
                      idxOrTargetGetter(lView) :
                      unwrapRNode(lView[idxOrTargetGetter]);
                  var listener = lCleanup[tCleanup[i + 2]];
                  var 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[useCaptureOrSubIdx]();
                      }
                      else {
                          // Subscription
                          lCleanup[-useCaptureOrSubIdx].unsubscribe();
                      }
                  }
                  i += 2;
              }
              else {
                  // This is a cleanup function that is grouped with the index of its context
                  var context = lCleanup[tCleanup[i + 1]];
                  tCleanup[i].call(context);
              }
          }
          lView[CLEANUP] = null;
      }
  }
  /** Calls onDestroy hooks for this view */
  function executeOnDestroys(tView, lView) {
      var destroyHooks;
      if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
          for (var i = 0; i < destroyHooks.length; i += 2) {
              var context = lView[destroyHooks[i]];
              // Only call the destroy hook if the context has been requested.
              if (!(context instanceof NodeInjectorFactory)) {
                  var toCall = destroyHooks[i + 1];
                  if (Array.isArray(toCall)) {
                      for (var j = 0; j < toCall.length; j += 2) {
                          toCall[j + 1].call(context[toCall[j]]);
                      }
                  }
                  else {
                      toCall.call(context);
                  }
              }
          }
      }
  }
  /**
   * 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.
   */
  function getRenderParent(tView, tNode, currentView) {
      // Skip over element and ICU containers as those are represented by a comment node and
      // can't be used as a render parent.
      var parentTNode = tNode.parent;
      while (parentTNode != null &&
          (parentTNode.type === 4 /* ElementContainer */ ||
              parentTNode.type === 5 /* IcuContainer */)) {
          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) {
          var hostTNode = currentView[T_HOST];
          if (hostTNode.type === 2 /* View */) {
              // We are inserting a root element of an embedded view We might delay insertion of children
              // for a given view if it is disconnected. This might happen for 2 main reasons:
              // - view is not inserted into any container(view was created but not inserted yet)
              // - view is inserted into a container but the container itself is not inserted into the DOM
              // (container might be part of projection or child of a view that is not inserted yet).
              // In other words we can insert children of a given view if this view was inserted into a
              // container and the container itself has its render parent determined.
              return getContainerRenderParent(hostTNode, currentView);
          }
          else {
              // We are inserting a root element of the component view into the component host element and
              // it should always be eager.
              ngDevMode && assertNodeOfPossibleTypes(hostTNode, 3 /* Element */);
              return currentView[HOST];
          }
      }
      else {
          var isIcuCase = tNode && tNode.type === 5 /* IcuContainer */;
          // If the parent of this node is an ICU container, then it is represented by comment node and we
          // need to use it as an anchor. If it is projected then it's direct parent node is the renderer.
          if (isIcuCase && tNode.flags & 4 /* isProjected */) {
              return getNativeByTNode(tNode, currentView).parentNode;
          }
          ngDevMode && assertNodeType(parentTNode, 3 /* Element */);
          if (parentTNode.flags & 2 /* isComponentHost */) {
              var tData = tView.data;
              var tNode_1 = tData[parentTNode.index];
              var encapsulation = tData[tNode_1.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 !== exports.ViewEncapsulation.ShadowDom &&
                  encapsulation !== exports.ViewEncapsulation.Native) {
                  return null;
              }
          }
          return getNativeByTNode(parentTNode, currentView);
      }
  }
  /**
   * Inserts a native node before another native node for a given parent using {@link Renderer3}.
   * This is a utility function that can be used when native nodes were determined - it abstracts an
   * actual renderer being used.
   */
  function nativeInsertBefore(renderer, parent, child, beforeNode) {
      ngDevMode && ngDevMode.rendererInsertBefore++;
      if (isProceduralRenderer(renderer)) {
          renderer.insertBefore(parent, child, beforeNode);
      }
      else {
          parent.insertBefore(child, beforeNode, true);
      }
  }
  function nativeAppendChild(renderer, parent, child) {
      ngDevMode && ngDevMode.rendererAppendChild++;
      ngDevMode && assertDefined(parent, 'parent node must be defined');
      if (isProceduralRenderer(renderer)) {
          renderer.appendChild(parent, child);
      }
      else {
          parent.appendChild(child);
      }
  }
  function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode) {
      if (beforeNode !== null) {
          nativeInsertBefore(renderer, parent, child, beforeNode);
      }
      else {
          nativeAppendChild(renderer, parent, child);
      }
  }
  /** Removes a node from the DOM given its native parent. */
  function nativeRemoveChild(renderer, parent, child, isHostElement) {
      if (isProceduralRenderer(renderer)) {
          renderer.removeChild(parent, child, isHostElement);
      }
      else {
          parent.removeChild(child);
      }
  }
  /**
   * Returns a native parent of a given native node.
   */
  function nativeParentNode(renderer, node) {
      return (isProceduralRenderer(renderer) ? renderer.parentNode(node) : node.parentNode);
  }
  /**
   * Returns a native sibling of a given native node.
   */
  function nativeNextSibling(renderer, node) {
      return isProceduralRenderer(renderer) ? renderer.nextSibling(node) : node.nextSibling;
  }
  /**
   * Finds a native "anchor" node for cases where we can't append a native child directly
   * (`appendChild`) and need to use a reference (anchor) node for the `insertBefore` operation.
   * @param parentTNode
   * @param lView
   */
  function getNativeAnchorNode(parentTNode, lView) {
      if (parentTNode.type === 2 /* View */) {
          var lContainer = getLContainer(parentTNode, lView);
          if (lContainer === null)
              return null;
          var index = lContainer.indexOf(lView, CONTAINER_HEADER_OFFSET) - CONTAINER_HEADER_OFFSET;
          return getBeforeNodeForView(index, lContainer);
      }
      else if (parentTNode.type === 4 /* ElementContainer */ ||
          parentTNode.type === 5 /* IcuContainer */) {
          return getNativeByTNode(parentTNode, lView);
      }
      return null;
  }
  /**
   * Appends the `child` native node (or a collection of nodes) to the `parent`.
   *
   * The element insertion might be delayed {@link canInsertNativeNode}.
   *
   * @param tView The `TView' to be appended
   * @param lView The current LView
   * @param childEl The native child (or children) that should be appended
   * @param childTNode The TNode of the child element
   * @returns Whether or not the child was appended
   */
  function appendChild(tView, lView, childEl, childTNode) {
      var renderParent = getRenderParent(tView, childTNode, lView);
      if (renderParent != null) {
          var renderer = lView[RENDERER];
          var parentTNode = childTNode.parent || lView[T_HOST];
          var anchorNode = getNativeAnchorNode(parentTNode, lView);
          if (Array.isArray(childEl)) {
              for (var i = 0; i < childEl.length; i++) {
                  nativeAppendOrInsertBefore(renderer, renderParent, childEl[i], anchorNode);
              }
          }
          else {
              nativeAppendOrInsertBefore(renderer, renderParent, childEl, anchorNode);
          }
      }
  }
  /**
   * 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 &&
              assertNodeOfPossibleTypes(tNode, 3 /* Element */, 0 /* Container */, 4 /* ElementContainer */, 5 /* IcuContainer */, 1 /* Projection */);
          var tNodeType = tNode.type;
          if (tNodeType === 3 /* Element */) {
              return getNativeByTNode(tNode, lView);
          }
          else if (tNodeType === 0 /* Container */) {
              return getBeforeNodeForView(-1, lView[tNode.index]);
          }
          else if (tNodeType === 4 /* ElementContainer */ || tNodeType === 5 /* IcuContainer */) {
              var elIcuContainerChild = tNode.child;
              if (elIcuContainerChild !== null) {
                  return getFirstNativeNode(lView, elIcuContainerChild);
              }
              else {
                  var rNodeOrLContainer = lView[tNode.index];
                  if (isLContainer(rNodeOrLContainer)) {
                      return getBeforeNodeForView(-1, rNodeOrLContainer);
                  }
                  else {
                      return unwrapRNode(rNodeOrLContainer);
                  }
              }
          }
          else {
              var componentView = lView[DECLARATION_COMPONENT_VIEW];
              var componentHost = componentView[T_HOST];
              var parentView = getLViewParent(componentView);
              var firstProjectedTNode = componentHost.projection[tNode.projection];
              if (firstProjectedTNode != null) {
                  return getFirstNativeNode(parentView, firstProjectedTNode);
              }
              else {
                  return getFirstNativeNode(lView, tNode.next);
              }
          }
      }
      return null;
  }
  function getBeforeNodeForView(viewIndexInContainer, lContainer) {
      var nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;
      if (nextViewIndex < lContainer.length) {
          var lView = lContainer[nextViewIndex];
          var 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) {
      var 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, renderParent, beforeNode, isProjection) {
      while (tNode != null) {
          ngDevMode && assertTNodeForLView(tNode, lView);
          ngDevMode &&
              assertNodeOfPossibleTypes(tNode, 0 /* Container */, 3 /* Element */, 4 /* ElementContainer */, 1 /* Projection */, 1 /* Projection */, 5 /* IcuContainer */);
          var rawSlotValue = lView[tNode.index];
          var tNodeType = tNode.type;
          if (isProjection) {
              if (action === 0 /* Create */) {
                  rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
                  tNode.flags |= 4 /* isProjected */;
              }
          }
          if ((tNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
              if (tNodeType === 4 /* ElementContainer */ || tNodeType === 5 /* IcuContainer */) {
                  applyNodes(renderer, action, tNode.child, lView, renderParent, beforeNode, false);
                  applyToElementOrContainer(action, renderer, renderParent, rawSlotValue, beforeNode);
              }
              else if (tNodeType === 1 /* Projection */) {
                  applyProjectionRecursive(renderer, action, lView, tNode, renderParent, beforeNode);
              }
              else {
                  ngDevMode && assertNodeOfPossibleTypes(tNode, 3 /* Element */, 0 /* Container */);
                  applyToElementOrContainer(action, renderer, renderParent, rawSlotValue, beforeNode);
              }
          }
          tNode = isProjection ? tNode.projectionNext : tNode.next;
      }
  }
  /**
   * `applyView` performs operation on the view as specified in `action` (insert, detach, destroy)
   *
   * Inserting a view without projection or containers at top level is simple. Just iterate over the
   * root nodes of the View, and for each node perform the `action`.
   *
   * Things get more complicated with containers and projections. That is because coming across:
   * - Container: implies that we have to insert/remove/destroy the views of that container as well
   *              which in turn can have their own Containers at the View roots.
   * - Projection: implies that we have to insert/remove/destroy the nodes of the projection. The
   *               complication is that the nodes we are projecting can themselves have Containers
   *               or other Projections.
   *
   * As you can see this is a very recursive problem. Yes recursion is not most efficient but the
   * code is complicated enough that trying to implemented with recursion becomes unmaintainable.
   *
   * @param tView The `TView' which needs to be inserted, detached, destroyed
   * @param lView The LView which needs to be inserted, detached, destroyed.
   * @param renderer Renderer to use
   * @param action action to perform (insert, detach, destroy)
   * @param renderParent parent DOM element for insertion/removal.
   * @param beforeNode Before which node the insertions should happen.
   */
  function applyView(tView, lView, renderer, action, renderParent, beforeNode) {
      ngDevMode && assertNodeType(tView.node, 2 /* View */);
      var viewRootTNode = tView.node.child;
      applyNodes(renderer, action, viewRootTNode, lView, renderParent, 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) {
      var renderer = lView[RENDERER];
      var renderParent = getRenderParent(tView, tProjectionNode, lView);
      var parentTNode = tProjectionNode.parent || lView[T_HOST];
      var beforeNode = getNativeAnchorNode(parentTNode, lView);
      applyProjectionRecursive(renderer, 0 /* Create */, lView, tProjectionNode, renderParent, 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 renderParent parent DOM element for insertion/removal.
   * @param beforeNode Before which node the insertions should happen.
   */
  function applyProjectionRecursive(renderer, action, lView, tProjectionNode, renderParent, beforeNode) {
      var componentLView = lView[DECLARATION_COMPONENT_VIEW];
      var componentNode = componentLView[T_HOST];
      ngDevMode &&
          assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');
      var 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 (var i = 0; i < nodeToProjectOrRNodes.length; i++) {
              var rNode = nodeToProjectOrRNodes[i];
              applyToElementOrContainer(action, renderer, renderParent, rNode, beforeNode);
          }
      }
      else {
          var nodeToProject = nodeToProjectOrRNodes;
          var projectedComponentLView = componentLView[PARENT];
          applyNodes(renderer, action, nodeToProject, projectedComponentLView, renderParent, 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 renderParent parent DOM element for insertion/removal.
   * @param beforeNode Before which node the insertions should happen.
   */
  function applyContainer(renderer, action, lContainer, renderParent, beforeNode) {
      ngDevMode && assertLContainer(lContainer);
      var anchor = lContainer[NATIVE]; // LContainer has its own before node.
      var 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, renderParent, anchor, beforeNode);
      }
      for (var i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
          var lView = lContainer[i];
          applyView(lView[TVIEW], lView, renderer, action, renderParent, 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) {
      var isProcedural = isProceduralRenderer(renderer);
      if (isClassBased) {
          // We actually want JS true/false here because any truthy value should add the class
          if (!value) {
              ngDevMode && ngDevMode.rendererRemoveClass++;
              if (isProcedural) {
                  renderer.removeClass(rNode, prop);
              }
              else {
                  rNode.classList.remove(prop);
              }
          }
          else {
              ngDevMode && ngDevMode.rendererAddClass++;
              if (isProcedural) {
                  renderer.addClass(rNode, prop);
              }
              else {
                  ngDevMode && assertDefined(rNode.classList, 'HTMLElement expected');
                  rNode.classList.add(prop);
              }
          }
      }
      else {
          // TODO(misko): Can't import RendererStyleFlags2.DashCase as it causes imports to be resolved in
          // different order which causes failures. Using direct constant as workaround for now.
          var flags = prop.indexOf('-') == -1 ? undefined : 2 /* RendererStyleFlags2.DashCase */;
          if (value == null /** || value === undefined */) {
              ngDevMode && ngDevMode.rendererRemoveStyle++;
              if (isProcedural) {
                  renderer.removeStyle(rNode, prop, flags);
              }
              else {
                  rNode.style.removeProperty(prop);
              }
          }
          else {
              ngDevMode && ngDevMode.rendererSetStyle++;
              if (isProcedural) {
                  renderer.setStyle(rNode, prop, value, flags);
              }
              else {
                  ngDevMode && assertDefined(rNode.style, 'HTMLElement expected');
                  rNode.style.setProperty(prop, value);
              }
          }
      }
  }
  /**
   * 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');
      if (isProceduralRenderer(renderer)) {
          renderer.setAttribute(element, 'style', newValue);
      }
      else {
          element.style.cssText = 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 (isProceduralRenderer(renderer)) {
          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);
          }
      }
      else {
          element.className = newValue;
      }
      ngDevMode && ngDevMode.rendererSetClassName++;
  }

  /**
   * @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
   */
  /**
   * If `startTNode.parent` exists and has an injector, returns TNode for that injector.
   * Otherwise, unwraps a parent injector location number to find the view offset from the current
   * injector, then walks up the declaration view tree until the TNode of the parent injector is
   * found.
   *
   * @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
   * @param startTNode The TNode instance of the starting element
   * @returns The TNode of the parent injector
   */
  function getParentInjectorTNode(location, startView, startTNode) {
      // If there is an injector on the parent TNode, retrieve the TNode for that injector.
      if (startTNode.parent && startTNode.parent.injectorIndex !== -1) {
          // view offset is 0
          var injectorIndex = startTNode.parent.injectorIndex;
          var tNode = startTNode.parent;
          // If tNode.injectorIndex === tNode.parent.injectorIndex, then the index belongs to a parent
          // injector.
          while (tNode.parent != null && injectorIndex == tNode.parent.injectorIndex) {
              tNode = tNode.parent;
          }
          return tNode;
      }
      var viewOffset = getParentInjectorViewOffset(location);
      // view offset is 1
      var parentView = startView;
      var parentTNode = startView[T_HOST];
      // view offset is superior to 1
      while (viewOffset > 1) {
          parentView = parentView[DECLARATION_VIEW];
          parentTNode = parentView[T_HOST];
          viewOffset--;
      }
      return parentTNode;
  }

  /**
   * @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
   */
  var ViewRef = /** @class */ (function () {
      function ViewRef(
      /**
       * 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._viewContainerRef = null;
          /**
           * @internal
           */
          this._tViewNode = null;
      }
      Object.defineProperty(ViewRef.prototype, "rootNodes", {
          get: function () {
              var lView = this._lView;
              if (lView[HOST] == null) {
                  var hostTView = lView[T_HOST];
                  return collectNativeNodes(lView[TVIEW], lView, hostTView.child, []);
              }
              return [];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ViewRef.prototype, "context", {
          get: function () {
              return this._lView[CONTEXT];
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ViewRef.prototype, "destroyed", {
          get: function () {
              return (this._lView[FLAGS] & 256 /* Destroyed */) === 256 /* Destroyed */;
          },
          enumerable: true,
          configurable: true
      });
      ViewRef.prototype.destroy = function () {
          if (this._appRef) {
              this._appRef.detachView(this);
          }
          else if (this._viewContainerRef) {
              var index = this._viewContainerRef.indexOf(this);
              if (index > -1) {
                  this._viewContainerRef.detach(index);
              }
              this._viewContainerRef = null;
          }
          destroyLView(this._lView[TVIEW], this._lView);
      };
      ViewRef.prototype.onDestroy = function (callback) {
          storeCleanupFn(this._lView[TVIEW], this._lView, callback);
      };
      /**
       * Marks a view and all of its ancestors dirty.
       *
       * It also triggers change detection by calling `scheduleTick` internally, which coalesces
       * multiple `markForCheck` calls to into one change detection run.
       *
       * 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: 'my-app',
       *   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);
       *   }
       * }
       * ```
       */
      ViewRef.prototype.markForCheck = function () {
          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 {
       * }
       * ```
       */
      ViewRef.prototype.detach = function () {
          this._lView[FLAGS] &= ~128 /* 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: 'my-app',
       *   providers: [DataProvider],
       *   template: `
       *     Live Update: <input type="checkbox" [(ngModel)]="live">
       *     <live-data [live]="live"><live-data>
       *   `,
       * })
       * class AppComponent {
       *   live = true;
       * }
       * ```
       */
      ViewRef.prototype.reattach = function () {
          this._lView[FLAGS] |= 128 /* 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.
       */
      ViewRef.prototype.detectChanges = function () {
          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.
       */
      ViewRef.prototype.checkNoChanges = function () {
          checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
      };
      ViewRef.prototype.attachToViewContainerRef = function (vcRef) {
          if (this._appRef) {
              throw new Error('This view is already attached directly to the ApplicationRef!');
          }
          this._viewContainerRef = vcRef;
      };
      ViewRef.prototype.detachFromAppRef = function () {
          this._appRef = null;
          renderDetachView(this._lView[TVIEW], this._lView);
      };
      ViewRef.prototype.attachToAppRef = function (appRef) {
          if (this._viewContainerRef) {
              throw new Error('This view is already attached to a ViewContainer!');
          }
          this._appRef = appRef;
      };
      return ViewRef;
  }());
  /** @internal */
  var RootViewRef = /** @class */ (function (_super) {
      __extends(RootViewRef, _super);
      function RootViewRef(_view) {
          var _this = _super.call(this, _view) || this;
          _this._view = _view;
          return _this;
      }
      RootViewRef.prototype.detectChanges = function () {
          detectChangesInRootView(this._view);
      };
      RootViewRef.prototype.checkNoChanges = function () {
          checkNoChangesInRootView(this._view);
      };
      Object.defineProperty(RootViewRef.prototype, "context", {
          get: function () {
              return null;
          },
          enumerable: true,
          configurable: true
      });
      return RootViewRef;
  }(ViewRef));
  function collectNativeNodes(tView, lView, tNode, result, isProjection) {
      if (isProjection === void 0) { isProjection = false; }
      while (tNode !== null) {
          ngDevMode &&
              assertNodeOfPossibleTypes(tNode, 3 /* Element */, 0 /* Container */, 1 /* Projection */, 4 /* ElementContainer */, 5 /* IcuContainer */);
          var 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 (var i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) {
                  var lViewInAContainer = lNode[i];
                  var lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;
                  if (lViewFirstChildTNode !== null) {
                      collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
                  }
              }
          }
          var tNodeType = tNode.type;
          if (tNodeType === 4 /* ElementContainer */ || tNodeType === 5 /* IcuContainer */) {
              collectNativeNodes(tView, lView, tNode.child, result);
          }
          else if (tNodeType === 1 /* Projection */) {
              var componentView = lView[DECLARATION_COMPONENT_VIEW];
              var componentHost = componentView[T_HOST];
              var slotIdx = tNode.projection;
              ngDevMode &&
                  assertDefined(componentHost.projection, 'Components with projection nodes (<ng-content>) must have projection slots defined.');
              var nodesInSlot = componentHost.projection[slotIdx];
              if (Array.isArray(nodesInSlot)) {
                  result.push.apply(result, __spread(nodesInSlot));
              }
              else {
                  var parentView = getLViewParent(componentView);
                  ngDevMode &&
                      assertDefined(parentView, 'Component views should always have a parent view (component\'s host view)');
                  collectNativeNodes(parentView[TVIEW], parentView, nodesInSlot, result, true);
              }
          }
          tNode = isProjection ? tNode.projectionNext : tNode.next;
      }
      return result;
  }

  /**
   * @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
   */
  /**
   * Creates an ElementRef from the most recent node.
   *
   * @returns The ElementRef instance to use
   */
  function injectElementRef(ElementRefToken) {
      return createElementRef(ElementRefToken, getPreviousOrParentTNode(), getLView());
  }
  var R3ElementRef;
  /**
   * Creates an ElementRef given a node.
   *
   * @param ElementRefToken The ElementRef type
   * @param tNode The node for which you'd like an ElementRef
   * @param view The view to which the node belongs
   * @returns The ElementRef instance to use
   */
  function createElementRef(ElementRefToken, tNode, view) {
      if (!R3ElementRef) {
          R3ElementRef = /** @class */ (function (_super) {
              __extends(ElementRef, _super);
              function ElementRef() {
                  return _super !== null && _super.apply(this, arguments) || this;
              }
              return ElementRef;
          }(ElementRefToken));
      }
      return new R3ElementRef(getNativeByTNode(tNode, view));
  }
  var R3TemplateRef;
  /**
   * Creates a TemplateRef given a node.
   *
   * @returns The TemplateRef instance to use
   */
  function injectTemplateRef(TemplateRefToken, ElementRefToken) {
      return createTemplateRef(TemplateRefToken, ElementRefToken, getPreviousOrParentTNode(), getLView());
  }
  /**
   * Creates a TemplateRef and stores it on the injector.
   *
   * @param TemplateRefToken The TemplateRef type
   * @param ElementRefToken The ElementRef type
   * @param hostTNode The node on which a TemplateRef is requested
   * @param hostView The view 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(TemplateRefToken, ElementRefToken, hostTNode, hostView) {
      if (!R3TemplateRef) {
          R3TemplateRef = /** @class */ (function (_super) {
              __extends(TemplateRef, _super);
              function TemplateRef(_declarationView, _declarationTContainer, elementRef) {
                  var _this = _super.call(this) || this;
                  _this._declarationView = _declarationView;
                  _this._declarationTContainer = _declarationTContainer;
                  _this.elementRef = elementRef;
                  return _this;
              }
              TemplateRef.prototype.createEmbeddedView = function (context) {
                  var embeddedTView = this._declarationTContainer.tViews;
                  var embeddedLView = createLView(this._declarationView, embeddedTView, context, 16 /* CheckAlways */, null, embeddedTView.node);
                  var declarationLContainer = this._declarationView[this._declarationTContainer.index];
                  ngDevMode && assertLContainer(declarationLContainer);
                  embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
                  var declarationViewLQueries = this._declarationView[QUERIES];
                  if (declarationViewLQueries !== null) {
                      embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
                  }
                  renderView(embeddedTView, embeddedLView, context);
                  var viewRef = new ViewRef(embeddedLView);
                  viewRef._tViewNode = embeddedLView[T_HOST];
                  return viewRef;
              };
              return TemplateRef;
          }(TemplateRefToken));
      }
      if (hostTNode.type === 0 /* Container */) {
          ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
          return new R3TemplateRef(hostView, hostTNode, createElementRef(ElementRefToken, hostTNode, hostView));
      }
      else {
          return null;
      }
  }
  var R3ViewContainerRef;
  /**
   * 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(ViewContainerRefToken, ElementRefToken) {
      var previousTNode = getPreviousOrParentTNode();
      return createContainerRef(ViewContainerRefToken, ElementRefToken, previousTNode, getLView());
  }
  /**
   * 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 hostView The view to which the node belongs
   * @returns The ViewContainerRef instance to use
   */
  function createContainerRef(ViewContainerRefToken, ElementRefToken, hostTNode, hostView) {
      if (!R3ViewContainerRef) {
          R3ViewContainerRef = /** @class */ (function (_super) {
              __extends(ViewContainerRef, _super);
              function ViewContainerRef(_lContainer, _hostTNode, _hostView) {
                  var _this = _super.call(this) || this;
                  _this._lContainer = _lContainer;
                  _this._hostTNode = _hostTNode;
                  _this._hostView = _hostView;
                  return _this;
              }
              Object.defineProperty(ViewContainerRef.prototype, "element", {
                  get: function () {
                      return createElementRef(ElementRefToken, this._hostTNode, this._hostView);
                  },
                  enumerable: true,
                  configurable: true
              });
              Object.defineProperty(ViewContainerRef.prototype, "injector", {
                  get: function () {
                      return new NodeInjector(this._hostTNode, this._hostView);
                  },
                  enumerable: true,
                  configurable: true
              });
              Object.defineProperty(ViewContainerRef.prototype, "parentInjector", {
                  /** @deprecated No replacement */
                  get: function () {
                      var parentLocation = getParentInjectorLocation(this._hostTNode, this._hostView);
                      var parentView = getParentInjectorView(parentLocation, this._hostView);
                      var parentTNode = getParentInjectorTNode(parentLocation, this._hostView, this._hostTNode);
                      return !hasParentInjector(parentLocation) || parentTNode == null ?
                          new NodeInjector(null, this._hostView) :
                          new NodeInjector(parentTNode, parentView);
                  },
                  enumerable: true,
                  configurable: true
              });
              ViewContainerRef.prototype.clear = function () {
                  while (this.length > 0) {
                      this.remove(this.length - 1);
                  }
              };
              ViewContainerRef.prototype.get = function (index) {
                  return this._lContainer[VIEW_REFS] !== null && this._lContainer[VIEW_REFS][index] || null;
              };
              Object.defineProperty(ViewContainerRef.prototype, "length", {
                  get: function () {
                      return this._lContainer.length - CONTAINER_HEADER_OFFSET;
                  },
                  enumerable: true,
                  configurable: true
              });
              ViewContainerRef.prototype.createEmbeddedView = function (templateRef, context, index) {
                  var viewRef = templateRef.createEmbeddedView(context || {});
                  this.insert(viewRef, index);
                  return viewRef;
              };
              ViewContainerRef.prototype.createComponent = function (componentFactory, index, injector, projectableNodes, ngModuleRef) {
                  var contextInjector = injector || this.parentInjector;
                  if (!ngModuleRef && componentFactory.ngModule == null && contextInjector) {
                      // DO NOT REFACTOR. The code here used to have a `value || undefined` expression
                      // which seems to cause internal google apps to fail. This is documented in the
                      // following internal bug issue: go/b/142967802
                      var result = contextInjector.get(NgModuleRef, null);
                      if (result) {
                          ngModuleRef = result;
                      }
                  }
                  var componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
                  this.insert(componentRef.hostView, index);
                  return componentRef;
              };
              ViewContainerRef.prototype.insert = function (viewRef, index) {
                  var lView = viewRef._lView;
                  var tView = lView[TVIEW];
                  if (viewRef.destroyed) {
                      throw new Error('Cannot insert a destroyed View in a ViewContainer!');
                  }
                  this.allocateContainerIfNeeded();
                  if (viewAttachedToContainer(lView)) {
                      // If view is already attached, detach it first so we clean up references appropriately.
                      var 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 {
                          var 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).
                          var prevVCRef = new R3ViewContainerRef(prevLContainer, prevLContainer[T_HOST], prevLContainer[PARENT]);
                          prevVCRef.detach(prevVCRef.indexOf(viewRef));
                      }
                  }
                  var adjustedIdx = this._adjustIndex(index);
                  insertView(tView, lView, this._lContainer, adjustedIdx);
                  var beforeNode = getBeforeNodeForView(adjustedIdx, this._lContainer);
                  addRemoveViewFromContainer(tView, lView, true, beforeNode);
                  viewRef.attachToViewContainerRef(this);
                  addToArray(this._lContainer[VIEW_REFS], adjustedIdx, viewRef);
                  return viewRef;
              };
              ViewContainerRef.prototype.move = function (viewRef, newIndex) {
                  if (viewRef.destroyed) {
                      throw new Error('Cannot move a destroyed View in a ViewContainer!');
                  }
                  return this.insert(viewRef, newIndex);
              };
              ViewContainerRef.prototype.indexOf = function (viewRef) {
                  var viewRefsArr = this._lContainer[VIEW_REFS];
                  return viewRefsArr !== null ? viewRefsArr.indexOf(viewRef) : -1;
              };
              ViewContainerRef.prototype.remove = function (index) {
                  this.allocateContainerIfNeeded();
                  var adjustedIdx = this._adjustIndex(index, -1);
                  removeView(this._lContainer, adjustedIdx);
                  removeFromArray(this._lContainer[VIEW_REFS], adjustedIdx);
              };
              ViewContainerRef.prototype.detach = function (index) {
                  this.allocateContainerIfNeeded();
                  var adjustedIdx = this._adjustIndex(index, -1);
                  var view = detachView(this._lContainer, adjustedIdx);
                  var wasDetached = view && removeFromArray(this._lContainer[VIEW_REFS], adjustedIdx) != null;
                  return wasDetached ? new ViewRef(view) : null;
              };
              ViewContainerRef.prototype._adjustIndex = function (index, shift) {
                  if (shift === void 0) { 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;
              };
              ViewContainerRef.prototype.allocateContainerIfNeeded = function () {
                  if (this._lContainer[VIEW_REFS] === null) {
                      this._lContainer[VIEW_REFS] = [];
                  }
              };
              return ViewContainerRef;
          }(ViewContainerRefToken));
      }
      ngDevMode &&
          assertNodeOfPossibleTypes(hostTNode, 0 /* Container */, 3 /* Element */, 4 /* ElementContainer */);
      var lContainer;
      var slotValue = hostView[hostTNode.index];
      if (isLContainer(slotValue)) {
          // If the host is a container, we don't need to create a new LContainer
          lContainer = slotValue;
          setLContainerActiveIndex(lContainer, -1 /* DYNAMIC_EMBEDDED_VIEWS_ONLY */);
      }
      else {
          var commentNode = void 0;
          // 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 === 4 /* ElementContainer */) {
              commentNode = unwrapRNode(slotValue);
          }
          else {
              ngDevMode && ngDevMode.rendererCreateComment++;
              commentNode = hostView[RENDERER].createComment(ngDevMode ? 'container' : '');
              // A `ViewContainerRef` can be injected by the root (topmost / bootstrapped) component. In
              // this case we can't use TView / TNode data structures to insert container's marker node
              // (both a parent of a comment node and the comment node itself are not part of any view). In
              // this specific case we use low-level DOM manipulation to insert container's marker (comment)
              // node.
              if (isRootView(hostView)) {
                  var renderer = hostView[RENDERER];
                  var hostNative = getNativeByTNode(hostTNode, hostView);
                  var parentOfHostNative = nativeParentNode(renderer, hostNative);
                  nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative));
              }
              else {
                  appendChild(hostView[TVIEW], hostView, commentNode, hostTNode);
              }
          }
          hostView[hostTNode.index] = lContainer =
              createLContainer(slotValue, hostView, commentNode, hostTNode);
          addToViewTree(hostView, lContainer);
      }
      return new R3ViewContainerRef(lContainer, hostTNode, hostView);
  }
  /** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
  function injectChangeDetectorRef(isPipe) {
      if (isPipe === void 0) { isPipe = false; }
      return createViewRef(getPreviousOrParentTNode(), getLView(), isPipe);
  }
  /**
   * 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) {
      // `isComponentView` will be true for Component and Directives (but not for Pipes).
      // See https://github.com/angular/angular/pull/33072 for proper fix
      var isComponentView = !isPipe && isComponentHost(tNode);
      if (isComponentView) {
          // 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.
          var componentView = getComponentLViewByIndex(tNode.index, lView); // look down
          return new ViewRef(componentView, componentView);
      }
      else if (tNode.type === 3 /* Element */ || tNode.type === 0 /* Container */ ||
          tNode.type === 4 /* ElementContainer */ || tNode.type === 5 /* IcuContainer */) {
          // 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)
          var hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
          return new ViewRef(hostComponentView, lView);
      }
      return null;
  }
  /** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
  function getOrCreateRenderer2(view) {
      var renderer = view[RENDERER];
      if (isProceduralRenderer(renderer)) {
          return renderer;
      }
      else {
          throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
      }
  }
  /** 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.
      var lView = getLView();
      var tNode = getPreviousOrParentTNode();
      var nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
      return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView);
  }

  /**
   * @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
   */
  /**
   * Base class for Angular Views, 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 rerendered.
   *
   * @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](http://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
   */
  var ChangeDetectorRef = /** @class */ (function () {
      function ChangeDetectorRef() {
      }
      /**
       * @internal
       * @nocollapse
       */
      ChangeDetectorRef.__NG_ELEMENT_ID__ = function () { return SWITCH_CHANGE_DETECTOR_REF_FACTORY(); };
      return ChangeDetectorRef;
  }());
  var SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ = injectChangeDetectorRef;
  var SWITCH_CHANGE_DETECTOR_REF_FACTORY__PRE_R3__ = function () {
      var args = [];
      for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
      }
  };
  var ɵ0$5 = SWITCH_CHANGE_DETECTOR_REF_FACTORY__PRE_R3__;
  var SWITCH_CHANGE_DETECTOR_REF_FACTORY = SWITCH_CHANGE_DETECTOR_REF_FACTORY__PRE_R3__;

  /**
   * @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
   */
  /**
   * @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 be represented by
   * the `MyCustomComponent` constructor function.
   *
   * @publicApi
   */
  var Type = Function;
  function isType(v) {
      return typeof v === 'function';
  }

  /**
   * @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
   */
  /**
   * Attention: These regex has to hold even if the code is minified!
   */
  var DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*arguments\)/;
  var INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
  var INHERITED_CLASS_WITH_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/;
  var INHERITED_CLASS_WITH_DELEGATE_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(\)\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 DELEGATE_CTOR.test(typeStr) || INHERITED_CLASS_WITH_DELEGATE_CTOR.test(typeStr) ||
          (INHERITED_CLASS.test(typeStr) && !INHERITED_CLASS_WITH_CTOR.test(typeStr));
  }
  var ReflectionCapabilities = /** @class */ (function () {
      function ReflectionCapabilities(reflect) {
          this._reflect = reflect || _global['Reflect'];
      }
      ReflectionCapabilities.prototype.isReflectionEnabled = function () {
          return true;
      };
      ReflectionCapabilities.prototype.factory = function (t) {
          return function () {
              var args = [];
              for (var _i = 0; _i < arguments.length; _i++) {
                  args[_i] = arguments[_i];
              }
              return new (t.bind.apply(t, __spread([void 0], args)))();
          };
      };
      /** @internal */
      ReflectionCapabilities.prototype._zipTypesAndAnnotations = function (paramTypes, paramAnnotations) {
          var result;
          if (typeof paramTypes === 'undefined') {
              result = newArray(paramAnnotations.length);
          }
          else {
              result = newArray(paramTypes.length);
          }
          for (var 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;
      };
      ReflectionCapabilities.prototype._ownParameters = function (type, parentCtor) {
          var 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.
          var tsickleCtorParams = type.ctorParameters;
          if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) {
              // Newer tsickle uses a function closure
              // Retain the non-function case for compatibility with older tsickle
              var ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams;
              var paramTypes_1 = ctorParameters.map(function (ctorParam) { return ctorParam && ctorParam.type; });
              var paramAnnotations_1 = ctorParameters.map(function (ctorParam) {
                  return ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators);
              });
              return this._zipTypesAndAnnotations(paramTypes_1, paramAnnotations_1);
          }
          // API for metadata created by invoking the decorators.
          var paramAnnotations = type.hasOwnProperty(PARAMETERS) && type[PARAMETERS];
          var 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);
      };
      ReflectionCapabilities.prototype.parameters = function (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 [];
          }
          var parentCtor = getParentCtor(type);
          var parameters = this._ownParameters(type, parentCtor);
          if (!parameters && parentCtor !== Object) {
              parameters = this.parameters(parentCtor);
          }
          return parameters || [];
      };
      ReflectionCapabilities.prototype._ownAnnotations = function (typeOrFunc, parentCtor) {
          // Prefer the direct API.
          if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) {
              var 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;
      };
      ReflectionCapabilities.prototype.annotations = function (typeOrFunc) {
          if (!isType(typeOrFunc)) {
              return [];
          }
          var parentCtor = getParentCtor(typeOrFunc);
          var ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
          var parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
          return parentAnnotations.concat(ownAnnotations);
      };
      ReflectionCapabilities.prototype._ownPropMetadata = function (typeOrFunc, parentCtor) {
          // Prefer the direct API.
          if (typeOrFunc.propMetadata &&
              typeOrFunc.propMetadata !== parentCtor.propMetadata) {
              var 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) {
              var propDecorators_1 = typeOrFunc.propDecorators;
              var propMetadata_1 = {};
              Object.keys(propDecorators_1).forEach(function (prop) {
                  propMetadata_1[prop] = convertTsickleDecoratorIntoMetadata(propDecorators_1[prop]);
              });
              return propMetadata_1;
          }
          // API for metadata created by invoking the decorators.
          if (typeOrFunc.hasOwnProperty(PROP_METADATA)) {
              return typeOrFunc[PROP_METADATA];
          }
          return null;
      };
      ReflectionCapabilities.prototype.propMetadata = function (typeOrFunc) {
          if (!isType(typeOrFunc)) {
              return {};
          }
          var parentCtor = getParentCtor(typeOrFunc);
          var propMetadata = {};
          if (parentCtor !== Object) {
              var parentPropMetadata_1 = this.propMetadata(parentCtor);
              Object.keys(parentPropMetadata_1).forEach(function (propName) {
                  propMetadata[propName] = parentPropMetadata_1[propName];
              });
          }
          var ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor);
          if (ownPropMetadata) {
              Object.keys(ownPropMetadata).forEach(function (propName) {
                  var decorators = [];
                  if (propMetadata.hasOwnProperty(propName)) {
                      decorators.push.apply(decorators, __spread(propMetadata[propName]));
                  }
                  decorators.push.apply(decorators, __spread(ownPropMetadata[propName]));
                  propMetadata[propName] = decorators;
              });
          }
          return propMetadata;
      };
      ReflectionCapabilities.prototype.ownPropMetadata = function (typeOrFunc) {
          if (!isType(typeOrFunc)) {
              return {};
          }
          return this._ownPropMetadata(typeOrFunc, getParentCtor(typeOrFunc)) || {};
      };
      ReflectionCapabilities.prototype.hasLifecycleHook = function (type, lcProperty) {
          return type instanceof Type && lcProperty in type.prototype;
      };
      ReflectionCapabilities.prototype.guards = function (type) {
          return {};
      };
      ReflectionCapabilities.prototype.getter = function (name) {
          return new Function('o', 'return o.' + name + ';');
      };
      ReflectionCapabilities.prototype.setter = function (name) {
          return new Function('o', 'v', 'return o.' + name + ' = v;');
      };
      ReflectionCapabilities.prototype.method = function (name) {
          var functionBody = "if (!o." + name + ") throw new Error('\"" + name + "\" is undefined');\n        return o." + name + ".apply(o, args);";
          return new Function('o', 'args', functionBody);
      };
      // There is not a concept of import uri in Js, but this is useful in developing Dart applications.
      ReflectionCapabilities.prototype.importUri = function (type) {
          // StaticSymbol
          if (typeof type === 'object' && type['filePath']) {
              return type['filePath'];
          }
          // Runtime type
          return "./" + stringify(type);
      };
      ReflectionCapabilities.prototype.resourceUri = function (type) {
          return "./" + stringify(type);
      };
      ReflectionCapabilities.prototype.resolveIdentifier = function (name, moduleUrl, members, runtime) {
          return runtime;
      };
      ReflectionCapabilities.prototype.resolveEnum = function (enumIdentifier, name) {
          return enumIdentifier[name];
      };
      return ReflectionCapabilities;
  }());
  function convertTsickleDecoratorIntoMetadata(decoratorInvocations) {
      if (!decoratorInvocations) {
          return [];
      }
      return decoratorInvocations.map(function (decoratorInvocation) {
          var decoratorType = decoratorInvocation.type;
          var annotationCls = decoratorType.annotationCls;
          var annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
          return new (annotationCls.bind.apply(annotationCls, __spread([void 0], annotationArgs)))();
      });
  }
  function getParentCtor(ctor) {
      var parentProto = ctor.prototype ? Object.getPrototypeOf(ctor.prototype) : null;
      var 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 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
   */
  var _reflect = null;
  function getReflect() {
      return (_reflect = _reflect || new ReflectionCapabilities());
  }
  function reflectDependencies(type) {
      return convertDependencies(getReflect().parameters(type));
  }
  function convertDependencies(deps) {
      var compiler = getCompilerFacade();
      return deps.map(function (dep) { return reflectDependency(compiler, dep); });
  }
  function reflectDependency(compiler, dep) {
      var meta = {
          token: null,
          host: false,
          optional: false,
          resolved: compiler.R3ResolvedDependencyType.Token,
          self: false,
          skipSelf: false,
      };
      function setTokenAndResolvedType(token) {
          meta.resolved = compiler.R3ResolvedDependencyType.Token;
          meta.token = token;
      }
      if (Array.isArray(dep) && dep.length > 0) {
          for (var j = 0; j < dep.length; j++) {
              var param = dep[j];
              if (param === undefined) {
                  // param may be undefined if type of dep is not set by ngtsc
                  continue;
              }
              var 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 Error("Attribute name must be defined.");
                  }
                  meta.token = param.attributeName;
                  meta.resolved = compiler.R3ResolvedDependencyType.Attribute;
              }
              else if (param === ChangeDetectorRef) {
                  meta.token = param;
                  meta.resolved = compiler.R3ResolvedDependencyType.ChangeDetectorRef;
              }
              else {
                  setTokenAndResolvedType(param);
              }
          }
      }
      else if (dep === undefined || (Array.isArray(dep) && dep.length === 0)) {
          meta.token = undefined;
          meta.resolved = R3ResolvedDependencyType.Invalid;
      }
      else {
          setTokenAndResolvedType(dep);
      }
      return meta;
  }

  /**
   * @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
   */
  /**
   * Compile an Angular injectable according to its `Injectable` metadata, and patch the resulting
   * injectable def (`ɵprov`) onto the injectable type.
   */
  function compileInjectable(type, srcMeta) {
      var ngInjectableDef = null;
      var 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: function () {
                  if (ngInjectableDef === null) {
                      ngInjectableDef = getCompilerFacade().compileInjectable(angularCoreDiEnv, "ng:///" + type.name + "/\u0275prov.js", getInjectableMetadata(type, srcMeta));
                  }
                  return ngInjectableDef;
              },
          });
          // On IE10 properties defined via `defineProperty` won't be inherited by child classes,
          // which will break inheriting the injectable definition from a grandparent through an
          // undecorated parent class. We work around it by defining a method which should be used
          // as a fallback. This should only be a problem in JIT mode, because in AOT TypeScript
          // seems to have a workaround for static properties. When inheriting from an undecorated
          // parent is no longer supported in v10, this can safely be removed.
          if (!type.hasOwnProperty(NG_PROV_DEF_FALLBACK)) {
              type[NG_PROV_DEF_FALLBACK] = function () { return type[NG_PROV_DEF]; };
          }
      }
      // 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: function () {
                  if (ngFactoryDef === null) {
                      var metadata = getInjectableMetadata(type, srcMeta);
                      var compiler = getCompilerFacade();
                      ngFactoryDef = compiler.compileFactory(angularCoreDiEnv, "ng:///" + type.name + "/\u0275fac.js", {
                          name: metadata.name,
                          type: metadata.type,
                          typeArgumentCount: metadata.typeArgumentCount,
                          deps: reflectDependencies(type),
                          injectFn: 'inject',
                          target: compiler.R3FactoryTarget.Injectable
                      });
                  }
                  return ngFactoryDef;
              },
              // Leave this configurable so that the factories from directives or pipes can take precedence.
              configurable: true
          });
      }
  }
  var ɵ0$6 = getClosureSafeProperty;
  var USE_VALUE$1 = getClosureSafeProperty({ provide: String, useValue: ɵ0$6 });
  function isUseClassProvider(meta) {
      return meta.useClass !== undefined;
  }
  function isUseValueProvider(meta) {
      return USE_VALUE$1 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
      var meta = srcMeta || { providedIn: null };
      var compilerMeta = {
          name: type.name,
          type: type,
          typeArgumentCount: 0,
          providedIn: meta.providedIn,
          userDeps: undefined,
      };
      if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
          compilerMeta.userDeps = convertDependencies(meta.deps);
      }
      if (isUseClassProvider(meta)) {
          // The user explicitly specified useClass, and may or may not have provided deps.
          compilerMeta.useClass = resolveForwardRef(meta.useClass);
      }
      else if (isUseValueProvider(meta)) {
          // The user explicitly specified useValue.
          compilerMeta.useValue = resolveForwardRef(meta.useValue);
      }
      else if (isUseFactoryProvider(meta)) {
          // The user explicitly specified useFactory.
          compilerMeta.useFactory = meta.useFactory;
      }
      else if (isUseExistingProvider(meta)) {
          // The user explicitly specified useExisting.
          compilerMeta.useExisting = resolveForwardRef(meta.useExisting);
      }
      return compilerMeta;
  }

  /**
   * @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
   */
  var ɵ0$7 = getClosureSafeProperty;
  var USE_VALUE$2 = getClosureSafeProperty({ provide: String, useValue: ɵ0$7 });
  var EMPTY_ARRAY$1 = [];
  function convertInjectableProviderToFactory(type, provider) {
      if (!provider) {
          var reflectionCapabilities = new ReflectionCapabilities();
          var deps_1 = reflectionCapabilities.parameters(type);
          // TODO - convert to flags.
          return function () { return new (type.bind.apply(type, __spread([void 0], injectArgs(deps_1))))(); };
      }
      if (USE_VALUE$2 in provider) {
          var valueProvider_1 = provider;
          return function () { return valueProvider_1.useValue; };
      }
      else if (provider.useExisting) {
          var existingProvider_1 = provider;
          return function () { return ɵɵinject(resolveForwardRef(existingProvider_1.useExisting)); };
      }
      else if (provider.useFactory) {
          var factoryProvider_1 = provider;
          return function () { return factoryProvider_1.useFactory.apply(factoryProvider_1, __spread(injectArgs(factoryProvider_1.deps || EMPTY_ARRAY$1))); };
      }
      else if (provider.useClass) {
          var classProvider_1 = provider;
          var deps_2 = provider.deps;
          if (!deps_2) {
              var reflectionCapabilities = new ReflectionCapabilities();
              deps_2 = reflectionCapabilities.parameters(type);
          }
          return function () {
              var _a;
              return new ((_a = (resolveForwardRef(classProvider_1.useClass))).bind.apply(_a, __spread([void 0], injectArgs(deps_2))))();
          };
      }
      else {
          var deps_3 = provider.deps;
          if (!deps_3) {
              var reflectionCapabilities = new ReflectionCapabilities();
              deps_3 = reflectionCapabilities.parameters(type);
          }
          return function () { return new (type.bind.apply(type, __spread([void 0], injectArgs(deps_3))))(); };
      }
  }

  /**
   * @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
   */
  var ɵ0$8 = function (type, meta) { return SWITCH_COMPILE_INJECTABLE(type, meta); };
  /**
   * Injectable decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Injectable = makeDecorator('Injectable', undefined, undefined, undefined, ɵ0$8);
  /**
   * Supports @Injectable() in JIT mode for Render2.
   */
  function render2CompileInjectable(injectableType, options) {
      if (options && options.providedIn !== undefined && !getInjectableDef(injectableType)) {
          injectableType.ɵprov = ɵɵdefineInjectable({
              token: injectableType,
              providedIn: options.providedIn,
              factory: convertInjectableProviderToFactory(injectableType, options),
          });
      }
  }
  var SWITCH_COMPILE_INJECTABLE__POST_R3__ = compileInjectable;
  var SWITCH_COMPILE_INJECTABLE__PRE_R3__ = render2CompileInjectable;
  var SWITCH_COMPILE_INJECTABLE = SWITCH_COMPILE_INJECTABLE__PRE_R3__;

  /**
   * @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
   */
  /**
   * 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.
   */
  var INJECTOR_SCOPE = new InjectionToken('Set Injector scope.');

  /**
   * @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
   */
  /**
   * Marker which indicates that a value has not yet been created from the factory function.
   */
  var 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.
   */
  var CIRCULAR = {};
  var EMPTY_ARRAY$2 = [];
  /**
   * A lazily initialized NullInjector.
   */
  var NULL_INJECTOR = undefined;
  function getNullInjector() {
      if (NULL_INJECTOR === undefined) {
          NULL_INJECTOR = new NullInjector();
      }
      return NULL_INJECTOR;
  }
  /**
   * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
   *
   * @publicApi
   */
  function createInjector(defType, parent, additionalProviders, name) {
      if (parent === void 0) { parent = null; }
      if (additionalProviders === void 0) { additionalProviders = null; }
      var injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);
      injector._resolveInjectorDefTypes();
      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, additionalProviders, name) {
      if (parent === void 0) { parent = null; }
      if (additionalProviders === void 0) { additionalProviders = null; }
      return new R3Injector(defType, additionalProviders, parent || getNullInjector(), name);
  }
  var R3Injector = /** @class */ (function () {
      function R3Injector(def, additionalProviders, parent, source) {
          var _this = this;
          if (source === void 0) { source = null; }
          this.parent = parent;
          /**
           * 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();
          /**
           * The transitive set of `InjectorType`s which define this injector.
           */
          this.injectorDefTypes = new Set();
          /**
           * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks.
           */
          this.onDestroy = new Set();
          this._destroyed = false;
          var dedupStack = [];
          // Start off by creating Records for every provider declared in every InjectorType
          // included transitively in additional providers then do the same for `def`. This order is
          // important because `def` may include providers that override ones in additionalProviders.
          additionalProviders &&
              deepForEach(additionalProviders, function (provider) { return _this.processProvider(provider, def, additionalProviders); });
          deepForEach([def], function (injectorDef) { return _this.processInjectorType(injectorDef, [], dedupStack); });
          // Make sure the INJECTOR token provides this injector.
          this.records.set(INJECTOR, makeRecord(undefined, this));
          // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide
          // any injectable scoped to APP_ROOT_SCOPE.
          var record = this.records.get(INJECTOR_SCOPE);
          this.scope = record != null ? record.value : null;
          // Source name, used for debugging
          this.source = source || (typeof def === 'object' ? null : stringify(def));
      }
      Object.defineProperty(R3Injector.prototype, "destroyed", {
          /**
           * Flag indicating that this injector was previously destroyed.
           */
          get: function () {
              return this._destroyed;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * 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.
       */
      R3Injector.prototype.destroy = function () {
          this.assertNotDestroyed();
          // Set destroyed = true first, in case lifecycle hooks re-enter destroy().
          this._destroyed = true;
          try {
              // Call all the lifecycle hooks.
              this.onDestroy.forEach(function (service) { return service.ngOnDestroy(); });
          }
          finally {
              // Release all references.
              this.records.clear();
              this.onDestroy.clear();
              this.injectorDefTypes.clear();
          }
      };
      R3Injector.prototype.get = function (token, notFoundValue, flags) {
          if (notFoundValue === void 0) { notFoundValue = THROW_IF_NOT_FOUND; }
          if (flags === void 0) { flags = exports.InjectFlags.Default; }
          this.assertNotDestroyed();
          // Set the injection context.
          var previousInjector = setCurrentInjector(this);
          try {
              // Check for the SkipSelf flag.
              if (!(flags & exports.InjectFlags.SkipSelf)) {
                  // SkipSelf isn't set, check if the record belongs to this injector.
                  var 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.
                      var 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.
              var nextInjector = !(flags & exports.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 & exports.InjectFlags.Optional) && notFoundValue === THROW_IF_NOT_FOUND ?
                  null :
                  notFoundValue;
              return nextInjector.get(token, notFoundValue);
          }
          catch (e) {
              if (e.name === 'NullInjectorError') {
                  var 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, clean up the state by restoring the previous injector.
              setCurrentInjector(previousInjector);
          }
      };
      /** @internal */
      R3Injector.prototype._resolveInjectorDefTypes = function () {
          var _this = this;
          this.injectorDefTypes.forEach(function (defType) { return _this.get(defType); });
      };
      R3Injector.prototype.toString = function () {
          var tokens = [], records = this.records;
          records.forEach(function (v, token) { return tokens.push(stringify(token)); });
          return "R3Injector[" + tokens.join(', ') + "]";
      };
      R3Injector.prototype.assertNotDestroyed = function () {
          if (this._destroyed) {
              throw new Error('Injector has already been destroyed.');
          }
      };
      /**
       * Add an `InjectorType` or `InjectorTypeWithProviders` and all of its transitive providers
       * to this injector.
       *
       * 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)
       */
      R3Injector.prototype.processInjectorType = function (defOrWrappedDef, parents, dedupStack) {
          var _this = this;
          defOrWrappedDef = resolveForwardRef(defOrWrappedDef);
          if (!defOrWrappedDef)
              return false;
          // Either the defOrWrappedDef is an InjectorType (with injector def) or an
          // InjectorDefTypeWithProviders (aka ModuleWithProviders). Detecting either is a megamorphic
          // read, so care is taken to only do the read once.
          // First attempt to read the injector def (`ɵinj`).
          var def = getInjectorDef(defOrWrappedDef);
          // If that's not present, then attempt to read ngModule from the InjectorDefTypeWithProviders.
          var ngModule = (def == null) && defOrWrappedDef.ngModule || undefined;
          // Determine the InjectorType. In the case where `defOrWrappedDef` is an `InjectorType`,
          // then this is easy. In the case of an InjectorDefTypeWithProviders, then the definition type
          // is the `ngModule`.
          var defType = (ngModule === undefined) ? defOrWrappedDef : ngModule;
          // Check for circular dependencies.
          if (ngDevMode && parents.indexOf(defType) !== -1) {
              var defName = stringify(defType);
              throw new Error("Circular dependency in DI detected for type " + defName + ". Dependency path: " + parents.map(function (defType) { return stringify(defType); }).join(' > ') + " > " + defName + ".");
          }
          // Check for multiple imports of the same module
          var isDuplicate = dedupStack.indexOf(defType) !== -1;
          // Finally, if defOrWrappedType was an `InjectorDefTypeWithProviders`, then the actual
          // `InjectorDef` is on its `ngModule`.
          if (ngModule !== undefined) {
              def = getInjectorDef(ngModule);
          }
          // If no definition was found, it might be from exports. Remove it.
          if (def == null) {
              return false;
          }
          // Add providers in the same way that @NgModule resolution did:
          // First, include providers from any imports.
          if (def.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
              dedupStack.push(defType);
              var importTypesWithProviders_1;
              try {
                  deepForEach(def.imports, function (imported) {
                      if (_this.processInjectorType(imported, parents, dedupStack)) {
                          if (importTypesWithProviders_1 === undefined)
                              importTypesWithProviders_1 = [];
                          // 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_1.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_1 !== undefined) {
                  var _loop_1 = function (i) {
                      var _a = importTypesWithProviders_1[i], ngModule_1 = _a.ngModule, providers = _a.providers;
                      deepForEach(providers, function (provider) { return _this.processProvider(provider, ngModule_1, providers || EMPTY_ARRAY$2); });
                  };
                  for (var i = 0; i < importTypesWithProviders_1.length; i++) {
                      _loop_1(i);
                  }
              }
          }
          // Track the InjectorType and add a provider for it. It's important that this is done after the
          // def's imports.
          this.injectorDefTypes.add(defType);
          this.records.set(defType, makeRecord(def.factory, NOT_YET));
          // Next, include providers listed on the definition itself.
          var defProviders = def.providers;
          if (defProviders != null && !isDuplicate) {
              var injectorType_1 = defOrWrappedDef;
              deepForEach(defProviders, function (provider) { return _this.processProvider(provider, injectorType_1, defProviders); });
          }
          return (ngModule !== undefined &&
              defOrWrappedDef.providers !== undefined);
      };
      /**
       * Process a `SingleProvider` and add it.
       */
      R3Injector.prototype.processProvider = function (provider, ngModuleType, providers) {
          // Determine the token from the provider. Either it's its own token, or has a {provide: ...}
          // property.
          provider = resolveForwardRef(provider);
          var token = isTypeProvider(provider) ? provider : resolveForwardRef(provider && provider.provide);
          // Construct a `Record` for the provider.
          var record = providerToRecord(provider, ngModuleType, providers);
          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.
              var multiRecord_1 = this.records.get(token);
              if (multiRecord_1) {
                  // It has. Throw a nice error if
                  if (multiRecord_1.multi === undefined) {
                      throwMixedMultiProviderError();
                  }
              }
              else {
                  multiRecord_1 = makeRecord(undefined, NOT_YET, true);
                  multiRecord_1.factory = function () { return injectArgs(multiRecord_1.multi); };
                  this.records.set(token, multiRecord_1);
              }
              token = provider;
              multiRecord_1.multi.push(provider);
          }
          else {
              var existing = this.records.get(token);
              if (existing && existing.multi !== undefined) {
                  throwMixedMultiProviderError();
              }
          }
          this.records.set(token, record);
      };
      R3Injector.prototype.hydrate = function (token, record) {
          if (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.onDestroy.add(record.value);
          }
          return record.value;
      };
      R3Injector.prototype.injectableDefInScope = function (def) {
          if (!def.providedIn) {
              return false;
          }
          else if (typeof def.providedIn === 'string') {
              return def.providedIn === 'any' || (def.providedIn === this.scope);
          }
          else {
              return this.injectorDefTypes.has(def.providedIn);
          }
      };
      return R3Injector;
  }());
  function injectableDefOrInjectorDefFactory(token) {
      // Most tokens will have an injectable def directly on them, which specifies a factory directly.
      var injectableDef = getInjectableDef(token);
      var factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token);
      if (factory !== null) {
          return factory;
      }
      // If the token is an NgModule, it's also injectable but the factory is on its injector def
      // (`ɵinj`)
      var injectorDef = getInjectorDef(token);
      if (injectorDef !== null) {
          return injectorDef.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 Error("Token " + stringify(token) + " is missing a \u0275prov 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 Error('unreachable');
  }
  function getUndecoratedInjectableFactory(token) {
      // If the token has parameters then it has dependencies that we cannot resolve implicitly.
      var paramLength = token.length;
      if (paramLength > 0) {
          var args = newArray(paramLength, '?');
          throw new Error("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.
      var inheritedInjectableDef = getInheritedInjectableDef(token);
      if (inheritedInjectableDef !== null) {
          return function () { return inheritedInjectableDef.factory(token); };
      }
      else {
          return function () { return new token(); };
      }
  }
  function providerToRecord(provider, ngModuleType, providers) {
      if (isValueProvider(provider)) {
          return makeRecord(undefined, provider.useValue);
      }
      else {
          var factory = providerToFactory(provider, ngModuleType, providers);
          return makeRecord(factory, NOT_YET);
      }
  }
  /**
   * Converts a `SingleProvider` into a factory function.
   *
   * @param provider provider to convert to factory
   */
  function providerToFactory(provider, ngModuleType, providers) {
      var factory = undefined;
      if (isTypeProvider(provider)) {
          var unwrappedProvider = resolveForwardRef(provider);
          return getFactoryDef(unwrappedProvider) || injectableDefOrInjectorDefFactory(unwrappedProvider);
      }
      else {
          if (isValueProvider(provider)) {
              factory = function () { return resolveForwardRef(provider.useValue); };
          }
          else if (isFactoryProvider(provider)) {
              factory = function () { return provider.useFactory.apply(provider, __spread(injectArgs(provider.deps || []))); };
          }
          else if (isExistingProvider(provider)) {
              factory = function () { return ɵɵinject(resolveForwardRef(provider.useExisting)); };
          }
          else {
              var classRef_1 = resolveForwardRef(provider &&
                  (provider.useClass || provider.provide));
              if (!classRef_1) {
                  throwInvalidProviderError(ngModuleType, providers, provider);
              }
              if (hasDeps(provider)) {
                  factory = function () { return new ((classRef_1).bind.apply((classRef_1), __spread([void 0], injectArgs(provider.deps))))(); };
              }
              else {
                  return getFactoryDef(classRef_1) || injectableDefOrInjectorDefFactory(classRef_1);
              }
          }
      }
      return factory;
  }
  function makeRecord(factory, value, multi) {
      if (multi === void 0) { multi = false; }
      return {
          factory: factory,
          value: value,
          multi: multi ? [] : undefined,
      };
  }
  function isValueProvider(value) {
      return value !== null && typeof value == 'object' && USE_VALUE 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;
  }
  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);
  }

  /**
   * @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
   */
  function INJECTOR_IMPL__PRE_R3__(providers, parent, name) {
      return new StaticInjector(providers, parent, name);
  }
  function INJECTOR_IMPL__POST_R3__(providers, parent, name) {
      return createInjector({ name: name }, parent, providers, name);
  }
  var INJECTOR_IMPL = INJECTOR_IMPL__PRE_R3__;
  /**
   * 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
   */
  var Injector = /** @class */ (function () {
      function Injector() {
      }
      Injector.create = function (options, parent) {
          if (Array.isArray(options)) {
              return INJECTOR_IMPL(options, parent, '');
          }
          else {
              return INJECTOR_IMPL(options.providers, options.parent, options.name || '');
          }
      };
      Injector.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
      Injector.NULL = new NullInjector();
      /** @nocollapse */
      Injector.ɵprov = ɵɵdefineInjectable({
          token: Injector,
          providedIn: 'any',
          factory: function () { return ɵɵinject(INJECTOR); },
      });
      /**
       * @internal
       * @nocollapse
       */
      Injector.__NG_ELEMENT_ID__ = -1;
      return Injector;
  }());
  var IDENT = function (value) {
      return value;
  };
  var ɵ0$9 = IDENT;
  var EMPTY = [];
  var CIRCULAR$1 = IDENT;
  var MULTI_PROVIDER_FN = function () {
      return Array.prototype.slice.call(arguments);
  };
  var ɵ1$1 = MULTI_PROVIDER_FN;
  var NO_NEW_LINE$1 = 'ɵ';
  var StaticInjector = /** @class */ (function () {
      function StaticInjector(providers, parent, source) {
          if (parent === void 0) { parent = Injector.NULL; }
          if (source === void 0) { source = null; }
          this.parent = parent;
          this.source = source;
          var records = this._records = new Map();
          records.set(Injector, { token: Injector, fn: IDENT, deps: EMPTY, value: this, useNew: false });
          records.set(INJECTOR, { token: INJECTOR, fn: IDENT, deps: EMPTY, value: this, useNew: false });
          this.scope = recursivelyProcessProviders(records, providers);
      }
      StaticInjector.prototype.get = function (token, notFoundValue, flags) {
          if (flags === void 0) { flags = exports.InjectFlags.Default; }
          var records = this._records;
          var record = records.get(token);
          if (record === undefined) {
              // This means we have never seen this record, see if it is tree shakable provider.
              var injectableDef = getInjectableDef(token);
              if (injectableDef) {
                  var providedIn = injectableDef && injectableDef.providedIn;
                  if (providedIn === 'any' || providedIn != null && providedIn === this.scope) {
                      records.set(token, record = resolveProvider({ provide: token, useFactory: injectableDef.factory, deps: EMPTY }));
                  }
              }
              if (record === undefined) {
                  // Set record to null to make sure that we don't go through expensive lookup above again.
                  records.set(token, null);
              }
          }
          var lastInjector = setCurrentInjector(this);
          try {
              return tryResolveToken(token, record, records, this.parent, notFoundValue, flags);
          }
          catch (e) {
              return catchInjectorError(e, token, 'StaticInjectorError', this.source);
          }
          finally {
              setCurrentInjector(lastInjector);
          }
      };
      StaticInjector.prototype.toString = function () {
          var tokens = [], records = this._records;
          records.forEach(function (v, token) { return tokens.push(stringify(token)); });
          return "StaticInjector[" + tokens.join(', ') + "]";
      };
      return StaticInjector;
  }());
  function resolveProvider(provider) {
      var deps = computeDeps(provider);
      var fn = IDENT;
      var value = EMPTY;
      var useNew = false;
      var provide = resolveForwardRef(provider.provide);
      if (USE_VALUE in provider) {
          // We need to use USE_VALUE in provider since provider.useValue could be defined as undefined.
          value = provider.useValue;
      }
      else if (provider.useFactory) {
          fn = provider.useFactory;
      }
      else if (provider.useExisting) {
          // Just use IDENT
      }
      else if (provider.useClass) {
          useNew = true;
          fn = resolveForwardRef(provider.useClass);
      }
      else if (typeof provide == 'function') {
          useNew = true;
          fn = provide;
      }
      else {
          throw staticError('StaticProvider does not have [useValue|useFactory|useExisting|useClass] or [provide] is not newable', provider);
      }
      return { deps: deps, fn: fn, useNew: useNew, value: value };
  }
  function multiProviderMixError(token) {
      return staticError('Cannot mix multi providers and regular providers', token);
  }
  function recursivelyProcessProviders(records, provider) {
      var scope = null;
      if (provider) {
          provider = resolveForwardRef(provider);
          if (Array.isArray(provider)) {
              // if we have an array recurse into the array
              for (var i = 0; i < provider.length; i++) {
                  scope = recursivelyProcessProviders(records, provider[i]) || scope;
              }
          }
          else if (typeof provider === 'function') {
              // Functions were supported in ReflectiveInjector, but are not here. For safety give useful
              // error messages
              throw staticError('Function/Class not supported', provider);
          }
          else if (provider && typeof provider === 'object' && provider.provide) {
              // At this point we have what looks like a provider: {provide: ?, ....}
              var token = resolveForwardRef(provider.provide);
              var resolvedProvider = resolveProvider(provider);
              if (provider.multi === true) {
                  // This is a multi provider.
                  var multiProvider = records.get(token);
                  if (multiProvider) {
                      if (multiProvider.fn !== MULTI_PROVIDER_FN) {
                          throw multiProviderMixError(token);
                      }
                  }
                  else {
                      // Create a placeholder factory which will look up the constituents of the multi provider.
                      records.set(token, multiProvider = {
                          token: provider.provide,
                          deps: [],
                          useNew: false,
                          fn: MULTI_PROVIDER_FN,
                          value: EMPTY
                      });
                  }
                  // Treat the provider as the token.
                  token = provider;
                  multiProvider.deps.push({ token: token, options: 6 /* Default */ });
              }
              var record = records.get(token);
              if (record && record.fn == MULTI_PROVIDER_FN) {
                  throw multiProviderMixError(token);
              }
              if (token === INJECTOR_SCOPE) {
                  scope = resolvedProvider.value;
              }
              records.set(token, resolvedProvider);
          }
          else {
              throw staticError('Unexpected provider', provider);
          }
      }
      return scope;
  }
  function tryResolveToken(token, record, records, parent, notFoundValue, flags) {
      try {
          return resolveToken(token, record, records, parent, notFoundValue, flags);
      }
      catch (e) {
          // ensure that 'e' is of type Error.
          if (!(e instanceof Error)) {
              e = new Error(e);
          }
          var path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
          path.unshift(token);
          if (record && record.value == CIRCULAR$1) {
              // Reset the Circular flag.
              record.value = EMPTY;
          }
          throw e;
      }
  }
  function resolveToken(token, record, records, parent, notFoundValue, flags) {
      var _a;
      var value;
      if (record && !(flags & exports.InjectFlags.SkipSelf)) {
          // If we don't have a record, this implies that we don't own the provider hence don't know how
          // to resolve it.
          value = record.value;
          if (value == CIRCULAR$1) {
              throw Error(NO_NEW_LINE$1 + 'Circular dependency');
          }
          else if (value === EMPTY) {
              record.value = CIRCULAR$1;
              var obj = undefined;
              var useNew = record.useNew;
              var fn = record.fn;
              var depRecords = record.deps;
              var deps = EMPTY;
              if (depRecords.length) {
                  deps = [];
                  for (var i = 0; i < depRecords.length; i++) {
                      var depRecord = depRecords[i];
                      var options = depRecord.options;
                      var childRecord = options & 2 /* CheckSelf */ ? records.get(depRecord.token) : undefined;
                      deps.push(tryResolveToken(
                      // Current Token to resolve
                      depRecord.token, 
                      // A record which describes how to resolve the token.
                      // If undefined, this means we don't have such a record
                      childRecord, 
                      // Other records we know about.
                      records, 
                      // If we don't know how to resolve dependency and we should not check parent for it,
                      // than pass in Null injector.
                      !childRecord && !(options & 4 /* CheckParent */) ? Injector.NULL : parent, options & 1 /* Optional */ ? null : Injector.THROW_IF_NOT_FOUND, exports.InjectFlags.Default));
                  }
              }
              record.value = value = useNew ? new ((_a = fn).bind.apply(_a, __spread([void 0], deps)))() : fn.apply(obj, deps);
          }
      }
      else if (!(flags & exports.InjectFlags.Self)) {
          value = parent.get(token, notFoundValue, exports.InjectFlags.Default);
      }
      else if (!(flags & exports.InjectFlags.Optional)) {
          value = Injector.NULL.get(token, notFoundValue);
      }
      else {
          value = Injector.NULL.get(token, typeof notFoundValue !== 'undefined' ? notFoundValue : null);
      }
      return value;
  }
  function computeDeps(provider) {
      var deps = EMPTY;
      var providerDeps = provider.deps;
      if (providerDeps && providerDeps.length) {
          deps = [];
          for (var i = 0; i < providerDeps.length; i++) {
              var options = 6 /* Default */;
              var token = resolveForwardRef(providerDeps[i]);
              if (Array.isArray(token)) {
                  for (var j = 0, annotations = token; j < annotations.length; j++) {
                      var annotation = annotations[j];
                      if (annotation instanceof Optional || annotation == Optional) {
                          options = options | 1 /* Optional */;
                      }
                      else if (annotation instanceof SkipSelf || annotation == SkipSelf) {
                          options = options & ~2 /* CheckSelf */;
                      }
                      else if (annotation instanceof Self || annotation == Self) {
                          options = options & ~4 /* CheckParent */;
                      }
                      else if (annotation instanceof Inject) {
                          token = annotation.token;
                      }
                      else {
                          token = resolveForwardRef(annotation);
                      }
                  }
              }
              deps.push({ token: token, options: options });
          }
      }
      else if (provider.useExisting) {
          var token = resolveForwardRef(provider.useExisting);
          deps = [{ token: token, options: 6 /* Default */ }];
      }
      else if (!providerDeps && !(USE_VALUE in provider)) {
          // useValue & useExisting are the only ones which are exempt from deps all others need it.
          throw staticError('\'deps\' required', provider);
      }
      return deps;
  }
  function staticError(text, obj) {
      return new Error(formatError(text, obj, 'StaticInjectorError'));
  }

  /**
   * @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
   */
  function findFirstClosedCycle(keys) {
      var res = [];
      for (var 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) {
          var reversed = findFirstClosedCycle(keys.slice().reverse());
          var tokenStrs = reversed.map(function (k) { return stringify(k.token); });
          return ' (' + tokenStrs.join(' -> ') + ')';
      }
      return '';
  }
  function injectionError(injector, key, constructResolvingMessage, originalError) {
      var keys = [key];
      var errMsg = constructResolvingMessage(keys);
      var 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) {
          var 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) {
          var 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) {
      var signature = [];
      for (var i = 0, ii = params.length; i < ii; i++) {
          var 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 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
   */
  /**
   * 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
   */
  var ReflectiveKey = /** @class */ (function () {
      /**
       * Private
       */
      function ReflectiveKey(token, id) {
          this.token = token;
          this.id = id;
          if (!token) {
              throw new Error('Token must be defined!');
          }
          this.displayName = stringify(this.token);
      }
      /**
       * Retrieves a `Key` for a token.
       */
      ReflectiveKey.get = function (token) {
          return _globalKeyRegistry.get(resolveForwardRef(token));
      };
      Object.defineProperty(ReflectiveKey, "numberOfKeys", {
          /**
           * @returns the number of keys registered in the system.
           */
          get: function () {
              return _globalKeyRegistry.numberOfKeys;
          },
          enumerable: true,
          configurable: true
      });
      return ReflectiveKey;
  }());
  var KeyRegistry = /** @class */ (function () {
      function KeyRegistry() {
          this._allKeys = new Map();
      }
      KeyRegistry.prototype.get = function (token) {
          if (token instanceof ReflectiveKey)
              return token;
          if (this._allKeys.has(token)) {
              return this._allKeys.get(token);
          }
          var newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys);
          this._allKeys.set(token, newKey);
          return newKey;
      };
      Object.defineProperty(KeyRegistry.prototype, "numberOfKeys", {
          get: function () {
              return this._allKeys.size;
          },
          enumerable: true,
          configurable: true
      });
      return KeyRegistry;
  }());
  var _globalKeyRegistry = new KeyRegistry();

  /**
   * @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
   */
  /**
   * Provides access to reflection data about symbols. Used internally by Angular
   * to power dependency injection and compilation.
   */
  var Reflector = /** @class */ (function () {
      function Reflector(reflectionCapabilities) {
          this.reflectionCapabilities = reflectionCapabilities;
      }
      Reflector.prototype.updateCapabilities = function (caps) {
          this.reflectionCapabilities = caps;
      };
      Reflector.prototype.factory = function (type) {
          return this.reflectionCapabilities.factory(type);
      };
      Reflector.prototype.parameters = function (typeOrFunc) {
          return this.reflectionCapabilities.parameters(typeOrFunc);
      };
      Reflector.prototype.annotations = function (typeOrFunc) {
          return this.reflectionCapabilities.annotations(typeOrFunc);
      };
      Reflector.prototype.propMetadata = function (typeOrFunc) {
          return this.reflectionCapabilities.propMetadata(typeOrFunc);
      };
      Reflector.prototype.hasLifecycleHook = function (type, lcProperty) {
          return this.reflectionCapabilities.hasLifecycleHook(type, lcProperty);
      };
      Reflector.prototype.getter = function (name) {
          return this.reflectionCapabilities.getter(name);
      };
      Reflector.prototype.setter = function (name) {
          return this.reflectionCapabilities.setter(name);
      };
      Reflector.prototype.method = function (name) {
          return this.reflectionCapabilities.method(name);
      };
      Reflector.prototype.importUri = function (type) {
          return this.reflectionCapabilities.importUri(type);
      };
      Reflector.prototype.resourceUri = function (type) {
          return this.reflectionCapabilities.resourceUri(type);
      };
      Reflector.prototype.resolveIdentifier = function (name, moduleUrl, members, runtime) {
          return this.reflectionCapabilities.resolveIdentifier(name, moduleUrl, members, runtime);
      };
      Reflector.prototype.resolveEnum = function (identifier, name) {
          return this.reflectionCapabilities.resolveEnum(identifier, name);
      };
      return Reflector;
  }());

  /**
   * @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
   */
  /**
   * The {@link Reflector} used internally in Angular to access metadata
   * about symbols.
   */
  var reflector = new Reflector(new ReflectionCapabilities());

  /**
   * @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
   */
  /**
   * `Dependency` is used by the framework to extend DI.
   * This is internal to Angular and should not be used directly.
   */
  var ReflectiveDependency = /** @class */ (function () {
      function ReflectiveDependency(key, optional, visibility) {
          this.key = key;
          this.optional = optional;
          this.visibility = visibility;
      }
      ReflectiveDependency.fromKey = function (key) {
          return new ReflectiveDependency(key, false, null);
      };
      return ReflectiveDependency;
  }());
  var _EMPTY_LIST = [];
  var ResolvedReflectiveProvider_ = /** @class */ (function () {
      function ResolvedReflectiveProvider_(key, resolvedFactories, multiProvider) {
          this.key = key;
          this.resolvedFactories = resolvedFactories;
          this.multiProvider = multiProvider;
          this.resolvedFactory = this.resolvedFactories[0];
      }
      return ResolvedReflectiveProvider_;
  }());
  /**
   * An internal resolved representation of a factory function created by resolving `Provider`.
   * @publicApi
   */
  var ResolvedReflectiveFactory = /** @class */ (function () {
      function ResolvedReflectiveFactory(
      /**
       * 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;
      }
      return ResolvedReflectiveFactory;
  }());
  /**
   * Resolve a single provider.
   */
  function resolveReflectiveFactory(provider) {
      var factoryFn;
      var resolvedDeps;
      if (provider.useClass) {
          var useClass = resolveForwardRef(provider.useClass);
          factoryFn = reflector.factory(useClass);
          resolvedDeps = _dependenciesFor(useClass);
      }
      else if (provider.useExisting) {
          factoryFn = function (aliasInstance) { return aliasInstance; };
          resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))];
      }
      else if (provider.useFactory) {
          factoryFn = provider.useFactory;
          resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
      }
      else {
          factoryFn = function () { return 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) {
      var normalized = _normalizeProviders(providers, []);
      var resolved = normalized.map(resolveReflectiveProvider);
      var 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 (var i = 0; i < providers.length; i++) {
          var provider = providers[i];
          var existing = normalizedProvidersMap.get(provider.key.id);
          if (existing) {
              if (provider.multiProvider !== existing.multiProvider) {
                  throw mixingMultiProvidersWithRegularProvidersError(existing, provider);
              }
              if (provider.multiProvider) {
                  for (var j = 0; j < provider.resolvedFactories.length; j++) {
                      existing.resolvedFactories.push(provider.resolvedFactories[j]);
                  }
              }
              else {
                  normalizedProvidersMap.set(provider.key.id, provider);
              }
          }
          else {
              var resolvedProvider = void 0;
              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(function (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 {
          var params_1 = dependencies.map(function (t) { return [t]; });
          return dependencies.map(function (t) { return _extractToken(typeOrFunc, t, params_1); });
      }
  }
  function _dependenciesFor(typeOrFunc) {
      var params = reflector.parameters(typeOrFunc);
      if (!params)
          return [];
      if (params.some(function (p) { return p == null; })) {
          throw noAnnotationError(typeOrFunc, params);
      }
      return params.map(function (p) { return _extractToken(typeOrFunc, p, params); });
  }
  function _extractToken(typeOrFunc, metadata, params) {
      var token = null;
      var optional = false;
      if (!Array.isArray(metadata)) {
          if (metadata instanceof Inject) {
              return _createDependency(metadata.token, optional, null);
          }
          else {
              return _createDependency(metadata, optional, null);
          }
      }
      var visibility = null;
      for (var i = 0; i < metadata.length; ++i) {
          var 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 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
   */
  // Threshold for the dynamic version
  var 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.
   *
   * @deprecated from v5 - slow and brings in a lot of code, Use `Injector.create` instead.
   * @publicApi
   */
  var ReflectiveInjector = /** @class */ (function () {
      function 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");
       * });
       * ```
       *
       */
      ReflectiveInjector.resolve = function (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);
       * ```
       */
      ReflectiveInjector.resolveAndCreate = function (providers, parent) {
          var 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);
       * ```
       */
      ReflectiveInjector.fromResolvedProviders = function (providers, parent) {
          return new ReflectiveInjector_(providers, parent);
      };
      return ReflectiveInjector;
  }());
  var ReflectiveInjector_ = /** @class */ (function () {
      /**
       * Private
       */
      function ReflectiveInjector_(_providers, _parent) {
          /** @internal */
          this._constructionCounter = 0;
          this._providers = _providers;
          this.parent = _parent || null;
          var len = _providers.length;
          this.keyIds = [];
          this.objs = [];
          for (var i = 0; i < len; i++) {
              this.keyIds[i] = _providers[i].key.id;
              this.objs[i] = UNDEFINED;
          }
      }
      ReflectiveInjector_.prototype.get = function (token, notFoundValue) {
          if (notFoundValue === void 0) { notFoundValue = THROW_IF_NOT_FOUND; }
          return this._getByKey(ReflectiveKey.get(token), null, notFoundValue);
      };
      ReflectiveInjector_.prototype.resolveAndCreateChild = function (providers) {
          var ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
          return this.createChildFromResolved(ResolvedReflectiveProviders);
      };
      ReflectiveInjector_.prototype.createChildFromResolved = function (providers) {
          var inj = new ReflectiveInjector_(providers);
          inj.parent = this;
          return inj;
      };
      ReflectiveInjector_.prototype.resolveAndInstantiate = function (provider) {
          return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]);
      };
      ReflectiveInjector_.prototype.instantiateResolved = function (provider) {
          return this._instantiateProvider(provider);
      };
      ReflectiveInjector_.prototype.getProviderAtIndex = function (index) {
          if (index < 0 || index >= this._providers.length) {
              throw outOfBoundsError(index);
          }
          return this._providers[index];
      };
      /** @internal */
      ReflectiveInjector_.prototype._new = function (provider) {
          if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
              throw cyclicDependencyError(this, provider.key);
          }
          return this._instantiateProvider(provider);
      };
      ReflectiveInjector_.prototype._getMaxNumberOfObjects = function () {
          return this.objs.length;
      };
      ReflectiveInjector_.prototype._instantiateProvider = function (provider) {
          if (provider.multiProvider) {
              var res = [];
              for (var 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]);
          }
      };
      ReflectiveInjector_.prototype._instantiate = function (provider, ResolvedReflectiveFactory) {
          var _this = this;
          var factory = ResolvedReflectiveFactory.factory;
          var deps;
          try {
              deps =
                  ResolvedReflectiveFactory.dependencies.map(function (dep) { return _this._getByReflectiveDependency(dep); });
          }
          catch (e) {
              if (e.addKey) {
                  e.addKey(this, provider.key);
              }
              throw e;
          }
          var obj;
          try {
              obj = factory.apply(void 0, __spread(deps));
          }
          catch (e) {
              throw instantiationError(this, e, e.stack, provider.key);
          }
          return obj;
      };
      ReflectiveInjector_.prototype._getByReflectiveDependency = function (dep) {
          return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND);
      };
      ReflectiveInjector_.prototype._getByKey = function (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);
          }
      };
      ReflectiveInjector_.prototype._getObjByKeyId = function (keyId) {
          for (var 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 */
      ReflectiveInjector_.prototype._throwOrNull = function (key, notFoundValue) {
          if (notFoundValue !== THROW_IF_NOT_FOUND) {
              return notFoundValue;
          }
          else {
              throw noProviderError(this, key);
          }
      };
      /** @internal */
      ReflectiveInjector_.prototype._getByKeySelf = function (key, notFoundValue) {
          var obj = this._getObjByKeyId(key.id);
          return (obj !== UNDEFINED) ? obj : this._throwOrNull(key, notFoundValue);
      };
      /** @internal */
      ReflectiveInjector_.prototype._getByKeyDefault = function (key, notFoundValue, visibility) {
          var inj;
          if (visibility instanceof SkipSelf) {
              inj = this.parent;
          }
          else {
              inj = this;
          }
          while (inj instanceof ReflectiveInjector_) {
              var inj_ = inj;
              var 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);
          }
      };
      Object.defineProperty(ReflectiveInjector_.prototype, "displayName", {
          get: function () {
              var providers = _mapProviders(this, function (b) { return ' "' + b.key.displayName + '" '; })
                  .join(', ');
              return "ReflectiveInjector(providers: [" + providers + "])";
          },
          enumerable: true,
          configurable: true
      });
      ReflectiveInjector_.prototype.toString = function () {
          return this.displayName;
      };
      ReflectiveInjector_.INJECTOR_KEY = ReflectiveKey.get(Injector);
      return ReflectiveInjector_;
  }());
  function _mapProviders(injector, fn) {
      var res = [];
      for (var i = 0; i < injector._providers.length; ++i) {
          res[i] = fn(injector.getProviderAtIndex(i));
      }
      return res;
  }

  /**
   * @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
   */

  /**
   * @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
   */

  /**
   * @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
   */
  /**
   * 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.
   */
  var ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken('AnalyzeForEntryComponents');
  /**
   * Base class for query metadata.
   *
   * @see `ContentChildren`.
   * @see `ContentChild`.
   * @see `ViewChildren`.
   * @see `ViewChild`.
   *
   * @publicApi
   */
  var Query = /** @class */ (function () {
      function Query() {
      }
      return Query;
  }());
  var ɵ0$a = function (selector, data) {
      if (data === void 0) { data = {}; }
      return (__assign({ selector: selector, first: false, isViewQuery: false, descendants: false }, data));
  };
  /**
   * ContentChildren decorator and metadata.
   *
   *
   * @Annotation
   * @publicApi
   */
  var ContentChildren = makePropDecorator('ContentChildren', ɵ0$a, Query);
  var ɵ1$2 = function (selector, data) {
      if (data === void 0) { data = {}; }
      return (__assign({ selector: selector, first: true, isViewQuery: false, descendants: true }, data));
  };
  /**
   * ContentChild decorator and metadata.
   *
   *
   * @Annotation
   *
   * @publicApi
   */
  var ContentChild = makePropDecorator('ContentChild', ɵ1$2, Query);
  var ɵ2 = function (selector, data) {
      if (data === void 0) { data = {}; }
      return (__assign({ selector: selector, first: false, isViewQuery: true, descendants: true }, data));
  };
  /**
   * ViewChildren decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var ViewChildren = makePropDecorator('ViewChildren', ɵ2, Query);
  var ɵ3 = function (selector, data) {
      return (__assign({ selector: selector, first: true, isViewQuery: true, descendants: true }, data));
  };
  /**
   * ViewChild decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var ViewChild = makePropDecorator('ViewChild', ɵ3, Query);

  /**
   * @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
   */
  /**
   * 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.
      var componentResolved = [];
      // Cache so that we don't fetch the same resource more than once.
      var urlMap = new Map();
      function cachedResourceResolve(url) {
          var promise = urlMap.get(url);
          if (!promise) {
              var resp = resourceResolver(url);
              urlMap.set(url, promise = resp.then(unwrapResponse));
          }
          return promise;
      }
      componentResourceResolutionQueue.forEach(function (component, type) {
          var promises = [];
          if (component.templateUrl) {
              promises.push(cachedResourceResolve(component.templateUrl).then(function (template) {
                  component.template = template;
              }));
          }
          var styleUrls = component.styleUrls;
          var styles = component.styles || (component.styles = []);
          var styleOffset = component.styles.length;
          styleUrls && styleUrls.forEach(function (styleUrl, index) {
              styles.push(''); // pre-allocate array.
              promises.push(cachedResourceResolve(styleUrl).then(function (style) {
                  styles[styleOffset + index] = style;
                  styleUrls.splice(styleUrls.indexOf(styleUrl), 1);
                  if (styleUrls.length == 0) {
                      component.styleUrls = undefined;
                  }
              }));
          });
          var fullyResolved = Promise.all(promises).then(function () { return componentDefResolved(type); });
          componentResolved.push(fullyResolved);
      });
      clearResolutionOfComponentResourcesQueue();
      return Promise.all(componentResolved).then(function () { return undefined; });
  }
  var componentResourceResolutionQueue = new Map();
  // Track when existing ɵcmp for a Type is waiting on resources.
  var 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() {
      var old = componentResourceResolutionQueue;
      componentResourceResolutionQueue = new Map();
      return old;
  }
  function restoreComponentResolutionQueue(queue) {
      componentDefPendingResolution.clear();
      queue.forEach(function (_, type) { return 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 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
   */
  /**
   * 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.
   */
  function computeStaticStyling(tNode, attrs) {
      ngDevMode &&
          assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only');
      var styles = tNode.styles;
      var classes = tNode.classes;
      var mode = 0;
      for (var i = 0; i < attrs.length; i++) {
          var value = attrs[i];
          if (typeof value === 'number') {
              mode = value;
          }
          else if (mode == 1 /* Classes */) {
              classes = concatStringsWithSpace(classes, value);
          }
          else if (mode == 2 /* Styles */) {
              var style = value;
              var styleValue = attrs[++i];
              styles = concatStringsWithSpace(styles, style + ': ' + styleValue + ';');
          }
      }
      styles !== null && (tNode.styles = styles);
      classes !== null && (tNode.classes = classes);
  }

  /**
   * @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
   */
  var _symbolIterator = null;
  function getSymbolIterator() {
      if (!_symbolIterator) {
          var Symbol_1 = _global['Symbol'];
          if (Symbol_1 && Symbol_1.iterator) {
              _symbolIterator = Symbol_1.iterator;
          }
          else {
              // es6-shim specific logic
              var keys = Object.getOwnPropertyNames(Map.prototype);
              for (var i = 0; i < keys.length; ++i) {
                  var key = keys[i];
                  if (key !== 'entries' && key !== 'size' &&
                      Map.prototype[key] === Map.prototype['entries']) {
                      _symbolIterator = key;
                  }
              }
          }
      }
      return _symbolIterator;
  }

  /**
   * @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
   */
  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) {
      var iterator1 = a[getSymbolIterator()]();
      var iterator2 = b[getSymbolIterator()]();
      while (true) {
          var item1 = iterator1.next();
          var 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 (var i = 0; i < obj.length; i++) {
              fn(obj[i]);
          }
      }
      else {
          var iterator = obj[getSymbolIterator()]();
          var item = void 0;
          while (!((item = iterator.next()).done)) {
              fn(item.value);
          }
      }
  }
  function isJsObject(o) {
      return o !== null && (typeof o === 'function' || typeof o === 'object');
  }

  /**
   * @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 has NaN !== NaN
  function looseIdentical(a, b) {
      return a === b || typeof a === 'number' && typeof b === 'number' && isNaN(a) && isNaN(b);
  }
  function devModeEqual(a, b) {
      var isListLikeIterableA = isListLikeIterable(a);
      var isListLikeIterableB = isListLikeIterable(b);
      if (isListLikeIterableA && isListLikeIterableB) {
          return areIterablesEqual(a, b, devModeEqual);
      }
      else {
          var isAObject = a && (typeof a === 'object' || typeof a === 'function');
          var isBObject = b && (typeof b === 'object' || typeof b === 'function');
          if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
              return true;
          }
          else {
              return looseIdentical(a, b);
          }
      }
  }

  /**
   * @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
   */
  function devModeEqual$1(a, b) {
      var isListLikeIterableA = isListLikeIterable$1(a);
      var isListLikeIterableB = isListLikeIterable$1(b);
      if (isListLikeIterableA && isListLikeIterableB) {
          return areIterablesEqual$1(a, b, devModeEqual$1);
      }
      else {
          var isAObject = a && (typeof a === 'object' || typeof a === 'function');
          var isBObject = b && (typeof b === 'object' || typeof b === 'function');
          if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
              return true;
          }
          else {
              return looseIdentical(a, b);
          }
      }
  }
  /**
   * Indicates that the result of a {@link Pipe} transformation has changed even though the
   * reference has not changed.
   *
   * Wrapped values are unwrapped automatically during the change detection, and the unwrapped value
   * is stored.
   *
   * Example:
   *
   * ```
   * if (this._latestValue === this._latestReturnedValue) {
   *    return this._latestReturnedValue;
   *  } else {
   *    this._latestReturnedValue = this._latestValue;
   *    return WrappedValue.wrap(this._latestValue); // this will force update
   *  }
   * ```
   *
   * @publicApi
   */
  var WrappedValue = /** @class */ (function () {
      function WrappedValue(value) {
          this.wrapped = value;
      }
      /** Creates a wrapped value. */
      WrappedValue.wrap = function (value) {
          return new WrappedValue(value);
      };
      /**
       * Returns the underlying value of a wrapped value.
       * Returns the given `value` when it is not wrapped.
       **/
      WrappedValue.unwrap = function (value) {
          return WrappedValue.isWrapped(value) ? value.wrapped : value;
      };
      /** Returns true if `value` is a wrapped value. */
      WrappedValue.isWrapped = function (value) {
          return value instanceof WrappedValue;
      };
      return WrappedValue;
  }());
  function isListLikeIterable$1(obj) {
      if (!isJsObject$1(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$1(a, b, comparator) {
      var iterator1 = a[getSymbolIterator()]();
      var iterator2 = b[getSymbolIterator()]();
      while (true) {
          var item1 = iterator1.next();
          var 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$1(obj, fn) {
      if (Array.isArray(obj)) {
          for (var i = 0; i < obj.length; i++) {
              fn(obj[i]);
          }
      }
      else {
          var iterator = obj[getSymbolIterator()]();
          var item = void 0;
          while (!((item = iterator.next()).done)) {
              fn(item.value);
          }
      }
  }
  function isJsObject$1(o) {
      return o !== null && (typeof o === 'function' || typeof o === 'object');
  }

  /**
   * @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
   */
  // 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 && assertDataInRange(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");
      var oldValue = lView[bindingIndex];
      if (Object.is(oldValue, value)) {
          return false;
      }
      else {
          if (ngDevMode && getCheckNoChangesMode()) {
              // View engine didn't report undefined values as changed on the first checkNoChanges pass
              // (before the change detection was run).
              var oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
              if (!devModeEqual$1(oldValueToCompare, value)) {
                  var 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) {
      var 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) {
      var 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) {
      var different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
      return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
  }

  /**
   * @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
   */
  /**
   * 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) {
      var lView = getLView();
      var bindingIndex = nextBindingIndex();
      if (bindingUpdated(lView, bindingIndex, value)) {
          var tView = getTView();
          var tNode = getSelectedTNode();
          elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
          ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
      }
      return ɵɵattribute;
  }

  /**
   * @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
   */
  /**
   * 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');
      var isBindingUpdated = false;
      var bindingIndex = getBindingIndex();
      for (var 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
      var content = values[0];
      for (var 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) {
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var bindingIndex = getBindingIndex();
      var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation1(lView, prefix, v0, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var 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) {
      var lView = getLView();
      var interpolated = interpolationV(lView, values);
      if (interpolated !== NO_CHANGE) {
          var tNode = getSelectedTNode();
          elementAttributeInternal(tNode, lView, attrName, interpolated, sanitizer, namespace);
          if (ngDevMode) {
              var interpolationInBetween = [values[0]]; // prefix
              for (var i = 2; i < values.length; i += 2) {
                  interpolationInBetween.push(values[i]);
              }
              storePropertyBindingMetadata.apply(void 0, __spread([getTView().data, tNode, 'attr.' + attrName,
                  getBindingIndex() - interpolationInBetween.length + 1], interpolationInBetween));
          }
      }
      return ɵɵattributeInterpolateV;
  }

  /**
   * @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
   */
  /**
   * 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) {
      var view = getComponentViewByInstance(component);
      detectChangesInternal(view[TVIEW], view, component);
  }
  /**
   * Marks the component as dirty (needing change detection). Marking a component dirty will
   * schedule a change detection on it at some point in the future.
   *
   * Marking an already dirty component as dirty won't do anything. Only one outstanding change
   * detection can be scheduled per component tree.
   *
   * @param component Component to mark as dirty.
   */
  function markDirty(component) {
      ngDevMode && assertDefined(component, 'component');
      var rootView = markViewDirty(getComponentViewByInstance(component));
      ngDevMode && assertDefined(rootView[CONTEXT], 'rootContext should be defined');
      scheduleTick(rootView[CONTEXT], 1 /* DetectChanges */);
  }
  /**
   * Used to perform change detection on the whole application.
   *
   * This is equivalent to `detectChanges`, but invoked on root component. Additionally, `tick`
   * executes lifecycle hooks and conditionally checks components based on their
   * `ChangeDetectionStrategy` and dirtiness.
   *
   * The preferred way to trigger change detection is to call `markDirty`. `markDirty` internally
   * schedules `tick` using a scheduler in order to coalesce multiple `markDirty` calls into a
   * single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
   * be changed when calling `renderComponent` and providing the `scheduler` option.
   */
  function tick(component) {
      var rootView = getRootView(component);
      var rootContext = rootView[CONTEXT];
      tickRootContext(rootContext);
  }

  /**
   * @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
   */
  function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
      ngDevMode && assertFirstCreatePass(tView);
      ngDevMode && ngDevMode.firstCreatePass++;
      var tViewConsts = tView.consts;
      // TODO(pk): refactor getOrCreateTNode to have the "create" only version
      var tNode = getOrCreateTNode(tView, lView[T_HOST], index, 0 /* Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
      resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
      registerPostOrderHooks(tView, tNode);
      var embeddedTView = tNode.tViews = createTView(2 /* Embedded */, -1, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
      var embeddedTViewNode = createTNode(tView, null, 2 /* View */, -1, null, null);
      embeddedTViewNode.injectorIndex = tNode.injectorIndex;
      embeddedTView.node = embeddedTViewNode;
      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) {
      var lView = getLView();
      var tView = getTView();
      var adjustedIndex = index + HEADER_OFFSET;
      var tNode = tView.firstCreatePass ?
          templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
          tView.data[adjustedIndex];
      setPreviousOrParentTNode(tNode, false);
      var 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 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
   */
  /** 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
      var adjustedIndex = index + HEADER_OFFSET;
      if (adjustedIndex >= tView.data.length) {
          tView.data[adjustedIndex] = null;
          tView.blueprint[adjustedIndex] = null;
      }
      lView[adjustedIndex] = 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) {
      var contextLView = getContextLView();
      return load(contextLView, index);
  }

  /**
   * @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
   */
  function ɵɵdirectiveInject(token, flags) {
      if (flags === void 0) { flags = exports.InjectFlags.Default; }
      var 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)
          return ɵɵinject(token, flags);
      var tNode = getPreviousOrParentTNode();
      return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
  }
  /**
   * Facade for the attribute injection from DI.
   *
   * @codeGenApi
   */
  function ɵɵinjectAttribute(attrNameToInject) {
      return injectAttributeImpl(getPreviousOrParentTNode(), attrNameToInject);
  }
  /**
   * 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() {
      var msg = ngDevMode ? "This constructor was not compatible with Dependency Injection." : 'invalid';
      throw new Error(msg);
  }

  /**
   * @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
   */
  /**
   * 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) {
      var lView = getLView();
      var bindingIndex = nextBindingIndex();
      if (bindingUpdated(lView, bindingIndex, value)) {
          var tView = getTView();
          var 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) {
      var inputs = tNode.inputs;
      var property = isClassBased ? 'class' : 'style';
      // We support both 'class' and `className` hence the fallback.
      setInputsForProperty(tView, lView, inputs[property], property, value);
  }

  /**
   * @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
   */
  function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) {
      ngDevMode && assertFirstCreatePass(tView);
      ngDevMode && ngDevMode.firstCreatePass++;
      var tViewConsts = tView.consts;
      var attrs = getConstant(tViewConsts, attrsIndex);
      var tNode = getOrCreateTNode(tView, lView[T_HOST], index, 3 /* Element */, name, attrs);
      var hasDirectives = resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
      ngDevMode && warnAboutUnknownElement(tView, lView, native, tNode, hasDirectives);
      if (tNode.mergedAttrs !== null) {
          computeStaticStyling(tNode, tNode.mergedAttrs);
      }
      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.
   *
   * 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) {
      var lView = getLView();
      var tView = getTView();
      var adjustedIndex = HEADER_OFFSET + index;
      ngDevMode &&
          assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
      ngDevMode && ngDevMode.rendererCreateElement++;
      ngDevMode && assertDataInRange(lView, adjustedIndex);
      var renderer = lView[RENDERER];
      var native = lView[adjustedIndex] = elementCreate(name, renderer, getNamespace());
      var tNode = tView.firstCreatePass ?
          elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) :
          tView.data[adjustedIndex];
      setPreviousOrParentTNode(tNode, true);
      var mergedAttrs = tNode.mergedAttrs;
      if (mergedAttrs !== null) {
          setUpAttributes(renderer, native, mergedAttrs);
      }
      var classes = tNode.classes;
      if (classes !== null) {
          writeDirectClass(renderer, native, classes);
      }
      var styles = tNode.styles;
      if (styles !== null) {
          writeDirectStyle(renderer, native, styles);
      }
      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);
      }
  }
  /**
   * Mark the end of the element.
   *
   * @codeGenApi
   */
  function ɵɵelementEnd() {
      var previousOrParentTNode = getPreviousOrParentTNode();
      ngDevMode && assertDefined(previousOrParentTNode, 'No parent node to close.');
      if (getIsParent()) {
          setIsNotParent();
      }
      else {
          ngDevMode && assertHasParent(getPreviousOrParentTNode());
          previousOrParentTNode = previousOrParentTNode.parent;
          setPreviousOrParentTNode(previousOrParentTNode, false);
      }
      var tNode = previousOrParentTNode;
      ngDevMode && assertNodeType(tNode, 3 /* Element */);
      decreaseElementDepthCount();
      var tView = getTView();
      if (tView.firstCreatePass) {
          registerPostOrderHooks(tView, previousOrParentTNode);
          if (isContentQueryHost(previousOrParentTNode)) {
              tView.queries.elementEnd(previousOrParentTNode);
          }
      }
      if (tNode.classes !== null && hasClassInput(tNode)) {
          setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classes, true);
      }
      if (tNode.styles !== null && hasStyleInput(tNode)) {
          setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.styles, false);
      }
  }
  /**
   * 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.
   *
   * @codeGenApi
   */
  function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
      ɵɵelementStart(index, name, attrsIndex, localRefsIndex);
      ɵɵelementEnd();
  }
  function warnAboutUnknownElement(tView, lView, element, tNode, hasDirectives) {
      var schemas = tView.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;
      var tagName = tNode.tagName;
      // 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.
          var 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(tView, lView, tagName)) {
              var warning = "'" + tagName + "' is not a known element:\n";
              warning += "1. If '" + tagName + "' is an Angular component, then verify that it is part of this module.\n";
              if (tagName && tagName.indexOf('-') > -1) {
                  warning += "2. If '" + tagName + "' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.";
              }
              else {
                  warning +=
                      "2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.";
              }
              console.warn(warning);
          }
      }
  }

  /**
   * @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
   */
  function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
      ngDevMode && ngDevMode.firstCreatePass++;
      var tViewConsts = tView.consts;
      var attrs = getConstant(tViewConsts, attrsIndex);
      var tNode = getOrCreateTNode(tView, lView[T_HOST], index, 4 /* 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);
      }
      var 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.
   *
   * 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) {
      var lView = getLView();
      var tView = getTView();
      var adjustedIndex = index + HEADER_OFFSET;
      ngDevMode && assertDataInRange(lView, adjustedIndex);
      ngDevMode &&
          assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings');
      var tNode = tView.firstCreatePass ?
          elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) :
          tView.data[adjustedIndex];
      setPreviousOrParentTNode(tNode, true);
      ngDevMode && ngDevMode.rendererCreateComment++;
      var 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);
      }
  }
  /**
   * Mark the end of the <ng-container>.
   *
   * @codeGenApi
   */
  function ɵɵelementContainerEnd() {
      var previousOrParentTNode = getPreviousOrParentTNode();
      var tView = getTView();
      if (getIsParent()) {
          setIsNotParent();
      }
      else {
          ngDevMode && assertHasParent(previousOrParentTNode);
          previousOrParentTNode = previousOrParentTNode.parent;
          setPreviousOrParentTNode(previousOrParentTNode, false);
      }
      ngDevMode && assertNodeType(previousOrParentTNode, 4 /* ElementContainer */);
      if (tView.firstCreatePass) {
          registerPostOrderHooks(tView, previousOrParentTNode);
          if (isContentQueryHost(previousOrParentTNode)) {
              tView.queries.elementEnd(previousOrParentTNode);
          }
      }
  }
  /**
   * 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.
   *
   * @codeGenApi
   */
  function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
      ɵɵelementContainerStart(index, attrsIndex, localRefsIndex);
      ɵɵelementContainerEnd();
  }

  /**
   * 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 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
   */
  /**
   * 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 an Observable
   */
  function isObservable(obj) {
      // TODO: use isObservable once we update pass rxjs 6.1
      // https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md#610-2018-05-03
      return !!obj && typeof obj.subscribe === 'function';
  }

  /**
   * @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
   */
  /**
   * 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) {
      if (useCapture === void 0) { useCapture = false; }
      var lView = getLView();
      var tView = getTView();
      var tNode = getPreviousOrParentTNode();
      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 ɵɵcomponentHostSyntheticListener(eventName, listenerFn, useCapture, eventTargetResolver) {
      if (useCapture === void 0) { useCapture = false; }
      var tNode = getPreviousOrParentTNode();
      var lView = getLView();
      var tView = getTView();
      var currentDef = getCurrentDirectiveDef(tView.data);
      var renderer = loadComponentRenderer(currentDef, tNode, lView);
      listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver);
      return ɵɵcomponentHostSyntheticListener;
  }
  /**
   * 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) {
      var tCleanup = tView.cleanup;
      if (tCleanup != null) {
          for (var i = 0; i < tCleanup.length - 1; i += 2) {
              var 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.
                  var lCleanup = lView[CLEANUP];
                  var 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) {
      if (useCapture === void 0) { useCapture = false; }
      var isTNodeDirectiveHost = isDirectiveHost(tNode);
      var firstCreatePass = tView.firstCreatePass;
      var tCleanup = firstCreatePass && (tView.cleanup || (tView.cleanup = []));
      // 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.
      var lCleanup = getLCleanup(lView);
      ngDevMode &&
          assertNodeOfPossibleTypes(tNode, 3 /* Element */, 0 /* Container */, 4 /* ElementContainer */);
      var processOutputs = true;
      // add native event listener - applicable to elements only
      if (tNode.type === 3 /* Element */) {
          var native = getNativeByTNode(tNode, lView);
          var resolved = eventTargetResolver ? eventTargetResolver(native) : EMPTY_OBJ;
          var target = resolved.target || native;
          var lCleanupIndex = lCleanup.length;
          var idxOrTargetGetter = eventTargetResolver ?
              function (_lView) { return eventTargetResolver(unwrapRNode(_lView[tNode.index])).target; } :
              tNode.index;
          // In order to match current behavior, native DOM event listeners must be added for all
          // events (including outputs).
          if (isProceduralRenderer(renderer)) {
              // 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.
              var 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.
                  var lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener;
                  lastListenerFn.__ngNextListenerFn__ = listenerFn;
                  existingListener.__ngLastListenerFn__ = listenerFn;
                  processOutputs = false;
              }
              else {
                  // The first argument of `listen` function in Procedural Renderer is:
                  // - either a target name (as a string) in case of global target (window, document, body)
                  // - or element reference (in all other cases)
                  listenerFn = wrapListener(tNode, lView, listenerFn, false /** preventDefault */);
                  var cleanupFn = renderer.listen(resolved.name || target, eventName, listenerFn);
                  ngDevMode && ngDevMode.rendererAddEventListener++;
                  lCleanup.push(listenerFn, cleanupFn);
                  tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
              }
          }
          else {
              listenerFn = wrapListener(tNode, lView, listenerFn, true /** preventDefault */);
              target.addEventListener(eventName, listenerFn, useCapture);
              ngDevMode && ngDevMode.rendererAddEventListener++;
              lCleanup.push(listenerFn);
              tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, useCapture);
          }
      }
      // subscribe to directive outputs
      var outputs = tNode.outputs;
      var props;
      if (processOutputs && outputs !== null && (props = outputs[eventName])) {
          var propsLength = props.length;
          if (propsLength) {
              for (var i = 0; i < propsLength; i += 2) {
                  var index = props[i];
                  ngDevMode && assertDataInRange(lView, index);
                  var minifiedName = props[i + 1];
                  var directiveInstance = lView[index];
                  var output = directiveInstance[minifiedName];
                  if (ngDevMode && !isObservable(output)) {
                      throw new Error("@Output " + minifiedName + " not initialized in '" + directiveInstance.constructor.name + "'.");
                  }
                  var subscription = output.subscribe(listenerFn);
                  var idx = lCleanup.length;
                  lCleanup.push(listenerFn, subscription);
                  tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));
              }
          }
      }
  }
  function executeListenerWithErrorHandling(lView, listenerFn, e) {
      try {
          // Only explicitly returning false from a listener should preventDefault
          return listenerFn(e) !== false;
      }
      catch (error) {
          handleError(lView, error);
          return false;
      }
  }
  /**
   * 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, 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).
          var startView = tNode.flags & 2 /* isComponentHost */ ?
              getComponentLViewByIndex(tNode.index, lView) :
              lView;
          // See interfaces/view.ts for more on LViewFlags.ManualOnPush
          if ((lView[FLAGS] & 32 /* ManualOnPush */) === 0) {
              markViewDirty(startView);
          }
          var result = executeListenerWithErrorHandling(lView, listenerFn, e);
          // A just-invoked listener function might have coalesced listeners so we need to check for
          // their presence and invoke as needed.
          var nextListenerFn = wrapListenerIn_markDirtyAndPreventDefault.__ngNextListenerFn__;
          while (nextListenerFn) {
              // We should prevent default if any of the listeners explicitly return false
              result = executeListenerWithErrorHandling(lView, 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 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
   */

  /**
   * @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
   */
  /**
   * 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) {
      if (level === void 0) { level = 1; }
      return nextContextImpl(level);
  }

  /**
   * @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
   */
  /**
   * 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) {
      var wildcardNgContentIndex = null;
      var ngProjectAsAttrVal = getProjectAsAttrValue(tNode);
      for (var i = 0; i < projectionSlots.length; i++) {
          var 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) {
      var 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.
          var numProjectionSlots = projectionSlots ? projectionSlots.length : 1;
          var projectionHeads = componentNode.projection =
              newArray(numProjectionSlots, null);
          var tails = projectionHeads.slice();
          var componentChild = componentNode.child;
          while (componentChild !== null) {
              var 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;
          }
      }
  }
  var delayProjection = false;
  function setDelayProjection(value) {
      delayProjection = value;
  }
  /**
   * 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, attrs) {
      if (selectorIndex === void 0) { selectorIndex = 0; }
      var lView = getLView();
      var tView = getTView();
      var tProjectionNode = getOrCreateTNode(tView, lView[T_HOST], nodeIndex, 1 /* 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
      setIsNotParent();
      // We might need to delay the projection of nodes if they are in the middle of an i18n block
      if (!delayProjection) {
          // 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) {
      var lView = getLView();
      var interpolatedValue = interpolation1(lView, prefix, v0, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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) {
      var lView = getLView();
      var interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var 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 inbetween 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) {
      var lView = getLView();
      var interpolatedValue = interpolationV(lView, values);
      if (interpolatedValue !== NO_CHANGE) {
          var tView = getTView();
          var tNode = getSelectedTNode();
          elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
          if (ngDevMode) {
              var interpolationInBetween = [values[0]]; // prefix
              for (var i = 2; i < values.length; i += 2) {
                  interpolationInBetween.push(values[i]);
              }
              storePropertyBindingMetadata.apply(void 0, __spread([tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1], interpolationInBetween));
          }
      }
      return ɵɵpropertyInterpolateV;
  }

  /**
   * @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
   */
  /**
   * 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.
   */
  var EMPTY_OBJ$1 = {};
  var EMPTY_ARRAY$3 = [];
  // 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$1);
      // tslint:disable-next-line:no-toplevel-property-access
      Object.freeze(EMPTY_ARRAY$3);
  }

  /**
   * @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
   */
  /**
   * 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.
   */
  var __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());
      var tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
      var tmplHead = getTStylingRangePrev(tBindings);
      var tmplTail = getTStylingRangeNext(tBindings);
      tData[index] = tStylingKeyWithStatic;
      var isKeyDuplicateOfStatic = false;
      var tStylingKey;
      if (Array.isArray(tStylingKeyWithStatic)) {
          // We are case when the `TStylingKey` contains static fields as well.
          var 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.
          var 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
              var 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) {
      var 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) {
      var tStylingAtIndex = tData[index + 1];
      var isMap = tStylingKey === null;
      var cursor = isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex);
      var 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 && assertDataInRange(tData, cursor);
          var tStylingValueAtCursor = tData[cursor];
          var 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 weather 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 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
   */
  // Global state of the parser. (This makes parser non-reentrant, but that is not an issue)
  var 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) {
      var 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) {
      var end = parserState.textEnd;
      var 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 /* COLON */);
      index = parserState.value = consumeWhitespace(text, index, end);
      index = parserState.valueEnd = consumeStyleValue(text, index, end);
      return consumeSeparator(text, index, end, 59 /* 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 /* 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 /* 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) {
      var ch;
      while (startIndex < endIndex &&
          ((ch = text.charCodeAt(startIndex)) === 45 /* DASH */ || ch === 95 /* UNDERSCORE */ ||
              ((ch & -33 /* UPPER_CASE */) >= 65 /* A */ && (ch & -33 /* UPPER_CASE */) <= 90 /* Z */))) {
          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) {
      var ch1 = -1; // 1st previous character
      var ch2 = -1; // 2nd previous character
      var ch3 = -1; // 3rd previous character
      var i = startIndex;
      var lastChIndex = i;
      while (i < endIndex) {
          var ch = text.charCodeAt(i++);
          if (ch === 59 /* SEMI_COLON */) {
              return lastChIndex;
          }
          else if (ch === 34 /* DOUBLE_QUOTE */ || ch === 39 /* 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 /* U */ &&
              ch2 === 82 /* R */ && ch1 === 76 /* L */ && ch === 40 /* OPEN_PAREN */) {
              lastChIndex = i = consumeQuotedText(text, 41 /* CLOSE_PAREN */, i, endIndex);
          }
          else if (ch > 32 /* SPACE */) {
              // if we have a non-whitespace character then capture its location
              lastChIndex = i;
          }
          ch3 = ch2;
          ch2 = ch1;
          ch1 = ch & -33 /* 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) {
      var ch1 = -1; // 1st previous character
      var index = startIndex;
      while (index < endIndex) {
          var ch = text.charCodeAt(index++);
          if (ch == quoteCharCode && ch1 !== 92 /* BACK_SLASH */) {
              return index;
          }
          if (ch == 92 /* BACK_SLASH */ && ch1 === 92 /* 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.substr(index + 1) +
          ("'. Expecting '" + expecting + "'."));
  }

  /**
   * @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
   */
  /**
   * Sets the current style sanitizer function which will then be used
   * within all follow-up prop and map-based style binding instructions
   * for the given element.
   *
   * Note that once styling has been applied to the element (i.e. once
   * `advance(n)` is executed or the hostBindings/template function exits)
   * then the active `sanitizerFn` will be set to `null`. This means that
   * once styling is applied to another element then a another call to
   * `styleSanitizer` will need to be made.
   *
   * @param sanitizerFn The sanitization function that will be used to
   *       process style prop/value entries.
   *
   * @codeGenApi
   */
  function ɵɵstyleSanitizer(sanitizer) {
      setCurrentStyleSanitizer(sanitizer);
  }
  /**
   * 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 when a suffix is provided then the underlying sanitizer will
   *        be ignored.
   *
   * 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 (var 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 (var 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 suffixOrSanitizer suffix or sanitization function
   * @param isClassBased `true` if `class` change (`false` if `style`)
   */
  function checkStylingProperty(prop, value, suffixOrSanitizer, isClassBased) {
      var lView = getLView();
      var tView = getTView();
      // Styling instructions use 2 slots per binding.
      // 1. one for the value / TStylingKey
      // 2. one for the intermittent-value / TStylingRange
      var bindingIndex = incrementBindingIndex(2);
      if (tView.firstUpdatePass) {
          stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);
      }
      if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
          // This is a work around. Once PR#34480 lands the sanitizer is passed explicitly and this line
          // can be removed.
          var styleSanitizer = void 0;
          if (suffixOrSanitizer == null) {
              if (styleSanitizer = getCurrentStyleSanitizer()) {
                  suffixOrSanitizer = styleSanitizer;
              }
          }
          var tNode = tView.data[getSelectedIndex() + HEADER_OFFSET];
          updateStyling(tView, tNode, lView, lView[RENDERER], prop, lView[bindingIndex + 1] = normalizeAndApplySuffixOrSanitizer(value, suffixOrSanitizer), 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 pass in version which does sanitization. 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) {
      var tView = getTView();
      var bindingIndex = incrementBindingIndex(2);
      if (tView.firstUpdatePass) {
          stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
      }
      var 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.
          var tNode = tView.data[getSelectedIndex() + HEADER_OFFSET];
          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.
                  var 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.
              var staticPrefix = isClassBased ? tNode.classes : tNode.styles;
              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);
      var 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.
          var tNode = tData[getSelectedIndex() + HEADER_OFFSET];
          var 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) {
      var hostDirectiveDef = getCurrentDirectiveDef(tData);
      var 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).
          var 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.
          var directiveStylingLast = tNode.directiveStylingLast;
          var 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
                  var 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) {
      var 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) {
      var 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) {
      var residual = undefined;
      var 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 (var i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {
          var 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..
      var currentDirective = null;
      var directiveEnd = tNode.directiveEnd;
      var 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) {
      var desiredMarker = isClassBased ? 1 /* Classes */ : 2 /* Styles */;
      var currentMarker = -1 /* ImplicitAttributes */;
      if (attrs !== null) {
          for (var i = 0; i < attrs.length; i++) {
              var 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 pass in version which does sanitization. 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$3;
      var styleKeyValueArray = [];
      var unwrappedValue = unwrapSafeValue(value);
      if (Array.isArray(unwrappedValue)) {
          for (var i = 0; i < unwrappedValue.length; i++) {
              keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
          }
      }
      else if (typeof unwrappedValue === 'object') {
          for (var 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` taking style sanitization into account.
   *
   * See: `keyValueArraySet` for details
   *
   * @param keyValueArray KeyValueArray to add to.
   * @param key Style key to add. (This key will be checked if it needs sanitization)
   * @param value The value to set (If key needs sanitization it will be sanitized)
   */
  function styleKeyValueArraySet(keyValueArray, key, value) {
      if (stylePropNeedsSanitization(key)) {
          value = ɵɵsanitizeStyle(value);
      }
      keyValueArraySet(keyValueArray, key, 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$3;
      }
      var oldIndex = 0;
      var newIndex = 0;
      var oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;
      var 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?');
          var oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;
          var newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;
          var setKey = null;
          var 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 /* Element */) {
          // 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;
      }
      var tData = tView.data;
      var tRange = tData[bindingIndex + 1];
      var 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);
              }
          }
          var 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 (converted to `KeyValueArray` if map and sanitized) is stored at `index +
   * 1`.
   *    The advantage of storing the sanitized value is that once the value is written we don't need
   *    to worry about sanitizing it later or keeping track of the sanitizer.
   *
   * @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.
      var isPrevDirection = tNode === null;
      var value = undefined;
      while (index > 0) {
          var rawKey = tData[index];
          var containsStatics = Array.isArray(rawKey);
          // Unwrap the key if we contain static values.
          var key = containsStatics ? rawKey[1] : rawKey;
          var isStylingMap = key === null;
          var 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$3 : undefined;
          }
          var 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;
              }
          }
          var 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
          var 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;
  }
  /**
   * Sanitizes or adds suffix to the value.
   *
   * If value is `null`/`undefined` no suffix is added
   * @param value
   * @param suffixOrSanitizer
   */
  function normalizeAndApplySuffixOrSanitizer(value, suffixOrSanitizer) {
      if (value == null /** || value === undefined */) {
          // do nothing
      }
      else if (typeof suffixOrSanitizer === 'function') {
          // sanitize the value.
          value = suffixOrSanitizer(value);
      }
      else if (typeof suffixOrSanitizer === 'string') {
          value = value + suffixOrSanitizer;
      }
      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 /* hasClassInput */ : 32 /* hasStyleInput */)) !== 0;
  }

  /**
   * @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
   */
  /**
   * 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) {
      if (value === void 0) { value = ''; }
      var lView = getLView();
      var tView = getTView();
      var adjustedIndex = index + HEADER_OFFSET;
      ngDevMode &&
          assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings');
      ngDevMode && assertDataInRange(lView, adjustedIndex);
      var tNode = tView.firstCreatePass ?
          getOrCreateTNode(tView, lView[T_HOST], index, 3 /* Element */, null, null) :
          tView.data[adjustedIndex];
      var textNative = lView[adjustedIndex] = createTextNode(value, lView[RENDERER]);
      appendChild(tView, lView, textNative, tNode);
      // Text nodes are self closing.
      setPreviousOrParentTNode(tNode, false);
  }

  /**
   * @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
   */
  /**
   *
   * 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var interpolated = interpolationV(lView, values);
      if (interpolated !== NO_CHANGE) {
          textBindingInternal(lView, getSelectedIndex(), interpolated);
      }
      return ɵɵtextInterpolateV;
  }

  /**
   * @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
   */
  /**
   *
   * 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var interpolatedValue = interpolationV(lView, values);
      checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
  }

  /**
   * @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
   */
  /**
   *
   * 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var interpolatedValue = interpolationV(lView, values);
      ɵɵstyleMap(interpolatedValue);
  }

  /**
   * @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
   */
  /**
   *
   * 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var 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) {
      var lView = getLView();
      var interpolatedValue = interpolationV(lView, values);
      checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
      return ɵɵstylePropInterpolateV;
  }

  /**
   * @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
   */
  /**
   * 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) {
      var lView = getLView();
      var bindingIndex = nextBindingIndex();
      if (bindingUpdated(lView, bindingIndex, value)) {
          var tView = getTView();
          var 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 ɵɵupdateSyntheticHostBinding(propName, value, sanitizer) {
      var lView = getLView();
      var bindingIndex = nextBindingIndex();
      if (bindingUpdated(lView, bindingIndex, value)) {
          var tView = getTView();
          var tNode = getSelectedTNode();
          var currentDef = getCurrentDirectiveDef(tView.data);
          var renderer = loadComponentRenderer(currentDef, tNode, lView);
          elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true);
          ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
      }
      return ɵɵupdateSyntheticHostBinding;
  }

  /**
   * @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
   */

  /**
   * @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
   */
  /**
   * Retrieves the component instance associated with a given DOM element.
   *
   * @usageNotes
   * Given the following DOM structure:
   * ```html
   * <my-app>
   *   <div>
   *     <child-comp></child-comp>
   *   </div>
   * </my-app>
   * ```
   * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
   * associated with this DOM element.
   *
   * Calling the function on `<my-app>` 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) {
      assertDomElement(element);
      var context = loadLContext(element, false);
      if (context === null)
          return null;
      if (context.component === undefined) {
          context.component = getComponentAtNodeIndex(context.nodeIndex, context.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);
      var context = loadLContext(element, false);
      return context === null ? null : context.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) {
      var context = loadLContext(elementOrDir, false);
      if (context === null)
          return null;
      var lView = context.lView;
      var parent;
      ngDevMode && assertLView(lView);
      while (lView[HOST] === null && (parent = getLViewParent(lView))) {
          // As long as lView[HOST] is null we know we are part of sub-template such as `*ngIf`
          lView = parent;
      }
      return lView[FLAGS] & 512 /* 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) {
      return __spread(getRootContext(elementOrDir).components);
  }
  /**
   * 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) {
      var context = loadLContext(elementOrDir, false);
      if (context === null)
          return Injector.NULL;
      var tNode = context.lView[TVIEW].data[context.nodeIndex];
      return new NodeInjector(tNode, context.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) {
      var context = loadLContext(element, false);
      if (context === null)
          return [];
      var lView = context.lView;
      var tView = lView[TVIEW];
      var tNode = tView.data[context.nodeIndex];
      var providerTokens = [];
      var startIndex = tNode.providerIndexes & 65535 /* ProvidersStartIndexMask */;
      var endIndex = tNode.directiveEnd;
      for (var i = startIndex; i < endIndex; i++) {
          var 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 element. Does not include
   * component instances.
   *
   * @usageNotes
   * Given the following DOM structure:
   * ```
   * <my-app>
   *   <button my-button></button>
   *   <my-comp></my-comp>
   * </my-app>
   * ```
   * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
   * directive that is associated with the DOM element.
   *
   * Calling `getDirectives` on `<my-comp>` will return an empty array.
   *
   * @param element DOM element for which to get the directives.
   * @returns Array of directives associated with the element.
   *
   * @publicApi
   * @globalApi ng
   */
  function getDirectives(element) {
      var context = loadLContext(element);
      if (context.directives === undefined) {
          context.directives = getDirectivesAtNodeIndex(context.nodeIndex, context.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 ? [] : __spread(context.directives);
  }
  function loadLContext(target, throwOnNotFound) {
      if (throwOnNotFound === void 0) { throwOnNotFound = true; }
      var context = getLContext(target);
      if (!context && throwOnNotFound) {
          throw new Error(ngDevMode ? "Unable to find context associated with " + stringifyForError(target) :
              'Invalid ng target');
      }
      return context;
  }
  /**
   * 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) {
      var context = loadLContext(target, false);
      if (context === null)
          return {};
      if (context.localRefs === undefined) {
          context.localRefs = discoverLocalRefs(context.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) {
      var hostElement = getHostElement(component);
      return hostElement.textContent || '';
  }
  function loadLContextFromNode(node) {
      if (!(node instanceof Node))
          throw new Error('Expecting instance of DOM Element');
      return loadLContext(node);
  }
  /**
   * 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:
   * ```
   * <my-app>
   *   <div (click)="doSomething()"></div>
   * </my-app>
   *
   * ```
   * Calling `getListeners` on `<div>` will return an object that looks as follows:
   * ```
   * {
   *   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) {
      assertDomElement(element);
      var lContext = loadLContext(element, false);
      if (lContext === null)
          return [];
      var lView = lContext.lView;
      var tView = lView[TVIEW];
      var lCleanup = lView[CLEANUP];
      var tCleanup = tView.cleanup;
      var listeners = [];
      if (tCleanup && lCleanup) {
          for (var i = 0; i < tCleanup.length;) {
              var firstParam = tCleanup[i++];
              var secondParam = tCleanup[i++];
              if (typeof firstParam === 'string') {
                  var name_1 = firstParam;
                  var listenerElement = unwrapRNode(lView[secondParam]);
                  var callback = lCleanup[tCleanup[i++]];
                  var 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
                  var type = (typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0) ? 'dom' : 'output';
                  var useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
                  if (element == listenerElement) {
                      listeners.push({ element: element, name: name_1, callback: callback, useCapture: useCapture, type: 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(element) {
      var debugNode = null;
      var lContext = loadLContextFromNode(element);
      var lView = lContext.lView;
      var nodeIndex = lContext.nodeIndex;
      if (nodeIndex !== -1) {
          var 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.
          var tNode = isLView(valueInLView) ? valueInLView[T_HOST] :
              getTNode(lView[TVIEW], nodeIndex - HEADER_OFFSET);
          debugNode = buildDebugNode(tNode, lView, nodeIndex);
      }
      return debugNode;
  }
  /**
   * 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) {
      var lContext = loadLContext(target);
      var nodeIndx = lContext.nodeIndex;
      var lView = lContext.lView;
      var 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 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
   */
  /**
   * 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) {
      markDirty(component);
      getRootComponents(component).forEach(function (rootComponent) { return detectChanges(rootComponent); });
  }

  /**
   * @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
   */
  /**
   * 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 --config=ivy
   *   //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).
   * */
  var GLOBAL_PUBLISH_EXPANDO_KEY = 'ng';
  var _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() {
      if (!_published) {
          _published = true;
          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....')`).
          var w = _global;
          ngDevMode && assertDefined(fn, 'function not defined');
          if (w) {
              var container = w[GLOBAL_PUBLISH_EXPANDO_KEY];
              if (!container) {
                  container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {};
              }
              container[name] = fn;
          }
      }
  }

  /**
   * @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
   */
  var ɵ0$b = function (token, notFoundValue) {
      throw new Error('NullInjector: Not found: ' + stringifyForError(token));
  };
  // TODO: A hack to not pull in the NullInjector from @angular/core.
  var NULL_INJECTOR$1 = {
      get: ɵ0$b
  };
  /**
   * Bootstraps a Component into an existing host element and returns an instance
   * of the component.
   *
   * Use this function to bootstrap a component into the DOM tree. Each invocation
   * of this function will create a separate tree of components, injectors and
   * change detection cycles and lifetimes. To dynamically insert a new component
   * into an existing tree such that it shares the same injection, change detection
   * and object lifetime, use {@link ViewContainer#createComponent}.
   *
   * @param componentType Component to bootstrap
   * @param options Optional parameters which control bootstrapping
   */
  function renderComponent$1(componentType /* Type as workaround for: Microsoft/TypeScript/issues/4881 */, opts) {
      if (opts === void 0) { opts = {}; }
      ngDevMode && publishDefaultGlobalUtils();
      ngDevMode && assertComponentType(componentType);
      var rendererFactory = opts.rendererFactory || domRendererFactory3;
      var sanitizer = opts.sanitizer || null;
      var componentDef = getComponentDef(componentType);
      if (componentDef.type != componentType)
          componentDef.type = componentType;
      // The first index of the first selector is the tag name.
      var componentTag = componentDef.selectors[0][0];
      var hostRenderer = rendererFactory.createRenderer(null, null);
      var hostRNode = locateHostElement(hostRenderer, opts.host || componentTag, componentDef.encapsulation);
      var rootFlags = componentDef.onPush ? 64 /* Dirty */ | 512 /* IsRoot */ :
          16 /* CheckAlways */ | 512 /* IsRoot */;
      var rootContext = createRootContext(opts.scheduler, opts.playerHandler);
      var renderer = rendererFactory.createRenderer(hostRNode, componentDef);
      var rootTView = createTView(0 /* Root */, -1, null, 1, 0, null, null, null, null, null);
      var rootView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, undefined, opts.injector || null);
      enterView(rootView, null);
      var component;
      try {
          if (rendererFactory.begin)
              rendererFactory.begin();
          var componentView = createRootComponentView(hostRNode, componentDef, rootView, rendererFactory, renderer, sanitizer);
          component = createRootComponent(componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
          // create mode pass
          renderView(rootTView, rootView, null);
          // update mode pass
          refreshView(rootTView, rootView, null, null);
      }
      finally {
          leaveView();
          if (rendererFactory.end)
              rendererFactory.end();
      }
      return component;
  }
  /**
   * 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 hostRenderer The current renderer
   * @param sanitizer The sanitizer, if provided
   *
   * @returns Component view created
   */
  function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) {
      var tView = rootView[TVIEW];
      ngDevMode && assertDataInRange(rootView, 0 + HEADER_OFFSET);
      rootView[0 + HEADER_OFFSET] = rNode;
      var tNode = getOrCreateTNode(tView, null, 0, 3 /* Element */, null, null);
      var mergedAttrs = tNode.mergedAttrs = def.hostAttrs;
      if (mergedAttrs !== null) {
          computeStaticStyling(tNode, mergedAttrs);
          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);
              }
          }
      }
      var viewRenderer = rendererFactory.createRenderer(rNode, def);
      var componentView = createLView(rootView, getOrCreateTComponentView(def), null, def.onPush ? 64 /* Dirty */ : 16 /* CheckAlways */, rootView[HEADER_OFFSET], tNode, rendererFactory, viewRenderer, sanitizer);
      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[HEADER_OFFSET] = 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, rootContext, hostFeatures) {
      var tView = rootLView[TVIEW];
      // Create directive instance with factory() and store at next index in viewData
      var component = instantiateRootComponent(tView, rootLView, componentDef);
      rootContext.components.push(component);
      componentView[CONTEXT] = component;
      hostFeatures && hostFeatures.forEach(function (feature) { return feature(component, componentDef); });
      // We want to generate an empty QueryList for root content queries for backwards
      // compatibility with ViewEngine.
      if (componentDef.contentQueries) {
          componentDef.contentQueries(1 /* Create */, component, rootLView.length - 1);
      }
      var rootTNode = getPreviousOrParentTNode();
      if (tView.firstCreatePass &&
          (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
          var elementIndex = rootTNode.index - HEADER_OFFSET;
          setSelectedIndex(elementIndex);
          var rootTView = rootLView[TVIEW];
          addHostBindingsToExpandoInstructions(rootTView, componentDef);
          growHostVarsSpace(rootTView, rootLView, componentDef.hostVars);
          invokeHostBindingsInCreationMode(componentDef, component);
      }
      return component;
  }
  function createRootContext(scheduler, playerHandler) {
      return {
          components: [],
          scheduler: scheduler || defaultScheduler,
          clean: CLEAN_PROMISE,
          playerHandler: playerHandler || null,
          flags: 0 /* Empty */
      };
  }
  /**
   * 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(component, def) {
      var rootTView = readPatchedLView(component)[TVIEW];
      var dirIndex = rootTView.data.length - 1;
      // TODO(misko): replace `as TNode` with createTNode call. (needs refactoring to lose dep on
      // LNode).
      registerPostOrderHooks(rootTView, { directiveStart: dirIndex, directiveEnd: dirIndex + 1 });
  }
  /**
   * Wait on component until it is rendered.
   *
   * This function returns a `Promise` which is resolved when the component's
   * change detection is executed. This is determined by finding the scheduler
   * associated with the `component`'s render tree and waiting until the scheduler
   * flushes. If nothing is scheduled, the function returns a resolved promise.
   *
   * Example:
   * ```
   * await whenRendered(myComponent);
   * ```
   *
   * @param component Component to wait upon
   * @returns Promise which resolves when the component is rendered.
   */
  function whenRendered(component) {
      return getRootContext(component).clean;
  }

  /**
   * @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
   */
  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) {
      var superType = getSuperType(definition.type);
      var shouldInheritFields = true;
      var inheritanceChain = [definition];
      while (superType) {
          var 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 Error('Directives cannot inherit Components');
              }
              // 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.
                  var writeableDef = definition;
                  writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
                  writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
                  writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
                  // Merge hostBindings
                  var superHostBindings = superDef.hostBindings;
                  superHostBindings && inheritHostBindings(definition, superHostBindings);
                  // Merge queries
                  var superViewQuery = superDef.viewQuery;
                  var 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).
                      var defData = definition.data;
                      defData.animation = (defData.animation || []).concat(superDef.data.animation);
                  }
                  // Inherit hooks
                  // Assume super class inheritance feature has already run.
                  writeableDef.afterContentChecked =
                      writeableDef.afterContentChecked || superDef.afterContentChecked;
                  writeableDef.afterContentInit = definition.afterContentInit || superDef.afterContentInit;
                  writeableDef.afterViewChecked = definition.afterViewChecked || superDef.afterViewChecked;
                  writeableDef.afterViewInit = definition.afterViewInit || superDef.afterViewInit;
                  writeableDef.doCheck = definition.doCheck || superDef.doCheck;
                  writeableDef.onDestroy = definition.onDestroy || superDef.onDestroy;
                  writeableDef.onInit = definition.onInit || superDef.onInit;
              }
              // Run parent features
              var features = superDef.features;
              if (features) {
                  for (var i = 0; i < features.length; i++) {
                      var 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) {
      var hostVars = 0;
      var hostAttrs = null;
      // We process the inheritance order from the base to the leaves here.
      for (var i = inheritanceChain.length - 1; i >= 0; i--) {
          var 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) {
      var prevViewQuery = definition.viewQuery;
      if (prevViewQuery) {
          definition.viewQuery = function (rf, ctx) {
              superViewQuery(rf, ctx);
              prevViewQuery(rf, ctx);
          };
      }
      else {
          definition.viewQuery = superViewQuery;
      }
  }
  function inheritContentQueries(definition, superContentQueries) {
      var prevContentQueries = definition.contentQueries;
      if (prevContentQueries) {
          definition.contentQueries = function (rf, ctx, directiveIndex) {
              superContentQueries(rf, ctx, directiveIndex);
              prevContentQueries(rf, ctx, directiveIndex);
          };
      }
      else {
          definition.contentQueries = superContentQueries;
      }
  }
  function inheritHostBindings(definition, superHostBindings) {
      var prevHostBindings = definition.hostBindings;
      if (prevHostBindings) {
          definition.hostBindings = function (rf, ctx) {
              superHostBindings(rf, ctx);
              prevHostBindings(rf, ctx);
          };
      }
      else {
          definition.hostBindings = superHostBindings;
      }
  }

  /**
   * @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
   */
  /**
   * Fields which exist on either directive or component definitions, and need to be copied from
   * parent to child classes by the `ɵɵCopyDefinitionFeature`.
   */
  var COPY_DIRECTIVE_FIELDS = [
      // The child class should use the providers of its parent.
      'providersResolver',
  ];
  /**
   * 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.
   */
  var 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) {
      var e_1, _a, e_2, _b;
      var superType = getSuperType(definition.type);
      var 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.
      var defAny = definition;
      try {
          // Copy over any fields that apply to either directives or components.
          for (var COPY_DIRECTIVE_FIELDS_1 = __values(COPY_DIRECTIVE_FIELDS), COPY_DIRECTIVE_FIELDS_1_1 = COPY_DIRECTIVE_FIELDS_1.next(); !COPY_DIRECTIVE_FIELDS_1_1.done; COPY_DIRECTIVE_FIELDS_1_1 = COPY_DIRECTIVE_FIELDS_1.next()) {
              var field = COPY_DIRECTIVE_FIELDS_1_1.value;
              defAny[field] = superDef[field];
          }
      }
      catch (e_1_1) { e_1 = { error: e_1_1 }; }
      finally {
          try {
              if (COPY_DIRECTIVE_FIELDS_1_1 && !COPY_DIRECTIVE_FIELDS_1_1.done && (_a = COPY_DIRECTIVE_FIELDS_1.return)) _a.call(COPY_DIRECTIVE_FIELDS_1);
          }
          finally { if (e_1) throw e_1.error; }
      }
      if (isComponentDef(superDef)) {
          try {
              // Copy over any component-specific fields.
              for (var COPY_COMPONENT_FIELDS_1 = __values(COPY_COMPONENT_FIELDS), COPY_COMPONENT_FIELDS_1_1 = COPY_COMPONENT_FIELDS_1.next(); !COPY_COMPONENT_FIELDS_1_1.done; COPY_COMPONENT_FIELDS_1_1 = COPY_COMPONENT_FIELDS_1.next()) {
                  var field = COPY_COMPONENT_FIELDS_1_1.value;
                  defAny[field] = superDef[field];
              }
          }
          catch (e_2_1) { e_2 = { error: e_2_1 }; }
          finally {
              try {
                  if (COPY_COMPONENT_FIELDS_1_1 && !COPY_COMPONENT_FIELDS_1_1.done && (_b = COPY_COMPONENT_FIELDS_1.return)) _b.call(COPY_COMPONENT_FIELDS_1);
              }
              finally { if (e_2) throw e_2.error; }
          }
      }
  }

  /**
   * @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
   */
  /**
   * 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
   */
  var SimpleChange = /** @class */ (function () {
      function SimpleChange(previousValue, currentValue, firstChange) {
          this.previousValue = previousValue;
          this.currentValue = currentValue;
          this.firstChange = firstChange;
      }
      /**
       * Check whether the new value is the first value assigned.
       */
      SimpleChange.prototype.isFirstChange = function () {
          return this.firstChange;
      };
      return SimpleChange;
  }());

  /**
   * @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
   */
  var PRIVATE_PREFIX = '__ngOnChanges_';
  /**
   * 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(definition) {
      if (definition.type.prototype.ngOnChanges) {
          definition.setInput = ngOnChangesSetInput;
          definition.onChanges = wrapOnChanges();
      }
  }
  // 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;
  function wrapOnChanges() {
      return function wrapOnChangesHook_inPreviousChangesStorage() {
          var simpleChangesStore = getSimpleChangesStore(this);
          var current = simpleChangesStore && simpleChangesStore.current;
          if (current) {
              var 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 (var key in current) {
                      previous[key] = current[key];
                  }
              }
              simpleChangesStore.current = null;
              this.ngOnChanges(current);
          }
      };
  }
  function ngOnChangesSetInput(instance, value, publicName, privateName) {
      var simpleChangesStore = getSimpleChangesStore(instance) ||
          setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
      var current = simpleChangesStore.current || (simpleChangesStore.current = {});
      var previous = simpleChangesStore.previous;
      var declaredName = this.declaredInputs[publicName];
      var previousChange = previous[declaredName];
      current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
      instance[privateName] = value;
  }
  var 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 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
   */
  /**
   * 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) {
      var tView = getTView();
      if (tView.firstCreatePass) {
          var isComponent = isComponentDef(def);
          // The list of view providers is processed first, and the flags are updated
          resolveProvider$1(viewProviders, tView.data, tView.blueprint, isComponent, true);
          // Then, the list of providers is processed, and the flags are updated
          resolveProvider$1(providers, tView.data, tView.blueprint, isComponent, false);
      }
  }
  /**
   * Resolves a provider and publishes it to the DI system.
   */
  function resolveProvider$1(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 (var i = 0; i < provider.length; i++) {
              resolveProvider$1(provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
          }
      }
      else {
          var tView = getTView();
          var lView = getLView();
          var token = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
          var providerFactory = providerToFactory(provider);
          var tNode = getPreviousOrParentTNode();
          var beginIndex = tNode.providerIndexes & 65535 /* ProvidersStartIndexMask */;
          var endIndex = tNode.directiveStart;
          var cptViewProvidersCount = tNode.providerIndexes >> 16 /* CptViewProvidersCountShift */;
          if (isTypeProvider(provider) || !provider.multi) {
              // Single provider case: the factory is created and pushed immediately
              var factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject);
              var 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 += 65536 /* 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.
              var existingProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);
              var existingViewProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);
              var doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 &&
                  lInjectablesBlueprint[existingProvidersFactoryIndex];
              var doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 &&
                  lInjectablesBlueprint[existingViewProvidersFactoryIndex];
              if (isViewProvider && !doesViewProvidersFactoryExist ||
                  !isViewProvider && !doesProvidersFactoryExist) {
                  // Cases 1.a and 2.a
                  diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
                  var 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 += 65536 /* CptViewProvidersCountShifter */;
                  }
                  lInjectablesBlueprint.push(factory);
                  lView.push(factory);
              }
              else {
                  // Cases 1.b and 2.b
                  var 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) {
      var providerIsTypeProvider = isTypeProvider(provider);
      if (providerIsTypeProvider || isClassProvider(provider)) {
          var prototype = (provider.useClass || provider).prototype;
          var ngOnDestroy = prototype.ngOnDestroy;
          if (ngOnDestroy) {
              var hooks = tView.destroyHooks || (tView.destroyHooks = []);
              if (!providerIsTypeProvider && provider.multi) {
                  ngDevMode &&
                      assertDefined(indexInFactory, 'indexInFactory when registering multi factory destroy hook');
                  var 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 (var 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) {
      var factories = this.multi;
      var result;
      if (this.providerFactory) {
          var componentCount = this.providerFactory.componentProviders;
          var 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 (var 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 (var i = 0; i < factories.length; i++) {
          var factory = factories[i];
          result.push(factory());
      }
      return result;
  }
  /**
   * Creates a multi factory.
   */
  function multiFactory(factoryFn, index, isViewProvider, isComponent, f) {
      var 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) {
      if (viewProviders === void 0) { viewProviders = []; }
      return function (definition) {
          definition.providersResolver =
              function (def, processProvidersFn) {
                  return providersResolver(def, //
                  processProvidersFn ? processProvidersFn(providers) : providers, //
                  viewProviders);
              };
      };
  }

  /**
   * @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
   */
  /**
   * 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
   */
  var ComponentRef = /** @class */ (function () {
      function ComponentRef() {
      }
      return ComponentRef;
  }());
  /**
   * 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
   */
  var ComponentFactory = /** @class */ (function () {
      function ComponentFactory() {
      }
      return ComponentFactory;
  }());

  /**
   * @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
   */
  function noComponentFactoryError(component) {
      var error = Error("No component factory found for " + stringify(component) + ". Did you add it to @NgModule.entryComponents?");
      error[ERROR_COMPONENT] = component;
      return error;
  }
  var ERROR_COMPONENT = 'ngComponent';
  function getComponent$1(error) {
      return error[ERROR_COMPONENT];
  }
  var _NullComponentFactoryResolver = /** @class */ (function () {
      function _NullComponentFactoryResolver() {
      }
      _NullComponentFactoryResolver.prototype.resolveComponentFactory = function (component) {
          throw noComponentFactoryError(component);
      };
      return _NullComponentFactoryResolver;
  }());
  /**
   * 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.
   *
   * @see [Dynamic Components](guide/dynamic-component-loader)
   * @publicApi
   */
  var ComponentFactoryResolver = /** @class */ (function () {
      function ComponentFactoryResolver() {
      }
      ComponentFactoryResolver.NULL = new _NullComponentFactoryResolver();
      return ComponentFactoryResolver;
  }());
  var CodegenComponentFactoryResolver = /** @class */ (function () {
      function CodegenComponentFactoryResolver(factories, _parent, _ngModule) {
          this._parent = _parent;
          this._ngModule = _ngModule;
          this._factories = new Map();
          for (var i = 0; i < factories.length; i++) {
              var factory = factories[i];
              this._factories.set(factory.componentType, factory);
          }
      }
      CodegenComponentFactoryResolver.prototype.resolveComponentFactory = function (component) {
          var factory = this._factories.get(component);
          if (!factory && this._parent) {
              factory = this._parent.resolveComponentFactory(component);
          }
          if (!factory) {
              throw noComponentFactoryError(component);
          }
          return new ComponentFactoryBoundToModule(factory, this._ngModule);
      };
      return CodegenComponentFactoryResolver;
  }());
  var ComponentFactoryBoundToModule = /** @class */ (function (_super) {
      __extends(ComponentFactoryBoundToModule, _super);
      function ComponentFactoryBoundToModule(factory, ngModule) {
          var _this = _super.call(this) || this;
          _this.factory = factory;
          _this.ngModule = ngModule;
          _this.selector = factory.selector;
          _this.componentType = factory.componentType;
          _this.ngContentSelectors = factory.ngContentSelectors;
          _this.inputs = factory.inputs;
          _this.outputs = factory.outputs;
          return _this;
      }
      ComponentFactoryBoundToModule.prototype.create = function (injector, projectableNodes, rootSelectorOrNode, ngModule) {
          return this.factory.create(injector, projectableNodes, rootSelectorOrNode, ngModule || this.ngModule);
      };
      return ComponentFactoryBoundToModule;
  }(ComponentFactory));

  /**
   * @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
   */
  function noop() {
      var args = [];
      for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
      }
      // Do nothing.
  }

  /**
   * @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
   */
  /**
   * 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](http://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.
  var ElementRef = /** @class */ (function () {
      function ElementRef(nativeElement) {
          this.nativeElement = nativeElement;
      }
      /**
       * @internal
       * @nocollapse
       */
      ElementRef.__NG_ELEMENT_ID__ = function () { return SWITCH_ELEMENT_REF_FACTORY(ElementRef); };
      return ElementRef;
  }());
  var SWITCH_ELEMENT_REF_FACTORY__POST_R3__ = injectElementRef;
  var SWITCH_ELEMENT_REF_FACTORY__PRE_R3__ = noop;
  var SWITCH_ELEMENT_REF_FACTORY = SWITCH_ELEMENT_REF_FACTORY__PRE_R3__;

  /**
   * @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
   */
  var Renderer2Interceptor = new InjectionToken('Renderer2Interceptor');
  /**
   * Creates and initializes a custom renderer that implements the `Renderer2` base class.
   *
   * @publicApi
   */
  var RendererFactory2 = /** @class */ (function () {
      function RendererFactory2() {
      }
      return RendererFactory2;
  }());
  (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";
  })(exports.RendererStyleFlags2 || (exports.RendererStyleFlags2 = {}));
  /**
   * 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
   */
  var Renderer2 = /** @class */ (function () {
      function Renderer2() {
      }
      /**
       * @internal
       * @nocollapse
       */
      Renderer2.__NG_ELEMENT_ID__ = function () { return SWITCH_RENDERER2_FACTORY(); };
      return Renderer2;
  }());
  var SWITCH_RENDERER2_FACTORY__POST_R3__ = injectRenderer2;
  var SWITCH_RENDERER2_FACTORY__PRE_R3__ = noop;
  var SWITCH_RENDERER2_FACTORY = SWITCH_RENDERER2_FACTORY__PRE_R3__;

  /**
   * @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
   */
  /**
   * Sanitizer is used by the views to sanitize potentially dangerous values.
   *
   * @publicApi
   */
  var Sanitizer = /** @class */ (function () {
      function Sanitizer() {
      }
      /** @nocollapse */
      Sanitizer.ɵprov = ɵɵdefineInjectable({
          token: Sanitizer,
          providedIn: 'root',
          factory: function () { return null; },
      });
      return Sanitizer;
  }());

  /**
   * @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
   */
  /**
   * @description Represents the version of Angular
   *
   * @publicApi
   */
  var Version = /** @class */ (function () {
      function Version(full) {
          this.full = full;
          this.major = full.split('.')[0];
          this.minor = full.split('.')[1];
          this.patch = full.split('.').slice(2).join('.');
      }
      return Version;
  }());
  /**
   * @publicApi
   */
  var VERSION = new Version('9.1.7');

  /**
   * @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
   */
  var DefaultIterableDifferFactory = /** @class */ (function () {
      function DefaultIterableDifferFactory() {
      }
      DefaultIterableDifferFactory.prototype.supports = function (obj) {
          return isListLikeIterable$1(obj);
      };
      DefaultIterableDifferFactory.prototype.create = function (trackByFn) {
          return new DefaultIterableDiffer(trackByFn);
      };
      return DefaultIterableDifferFactory;
  }());
  var trackByIdentity = function (index, item) { return item; };
  var ɵ0$c = trackByIdentity;
  /**
   * @deprecated v4.0.0 - Should not be part of public API.
   * @publicApi
   */
  var DefaultIterableDiffer = /** @class */ (function () {
      function DefaultIterableDiffer(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;
      }
      DefaultIterableDiffer.prototype.forEachItem = function (fn) {
          var record;
          for (record = this._itHead; record !== null; record = record._next) {
              fn(record);
          }
      };
      DefaultIterableDiffer.prototype.forEachOperation = function (fn) {
          var nextIt = this._itHead;
          var nextRemove = this._removalsHead;
          var addRemoveOffset = 0;
          var moveOffsets = null;
          while (nextIt || nextRemove) {
              // Figure out which is the next record to process
              // Order: remove, add, move
              var record = !nextRemove ||
                  nextIt &&
                      nextIt.currentIndex <
                          getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets) ?
                  nextIt :
                  nextRemove;
              var adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets);
              var 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 = [];
                      var localMovePreviousIndex = adjPreviousIndex - addRemoveOffset;
                      var localCurrentIndex = currentIndex - addRemoveOffset;
                      if (localMovePreviousIndex != localCurrentIndex) {
                          for (var i = 0; i < localMovePreviousIndex; i++) {
                              var offset = i < moveOffsets.length ? moveOffsets[i] : (moveOffsets[i] = 0);
                              var index = offset + i;
                              if (localCurrentIndex <= index && index < localMovePreviousIndex) {
                                  moveOffsets[i] = offset + 1;
                              }
                          }
                          var previousIndex = record.previousIndex;
                          moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex;
                      }
                  }
              }
              if (adjPreviousIndex !== currentIndex) {
                  fn(record, adjPreviousIndex, currentIndex);
              }
          }
      };
      DefaultIterableDiffer.prototype.forEachPreviousItem = function (fn) {
          var record;
          for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
              fn(record);
          }
      };
      DefaultIterableDiffer.prototype.forEachAddedItem = function (fn) {
          var record;
          for (record = this._additionsHead; record !== null; record = record._nextAdded) {
              fn(record);
          }
      };
      DefaultIterableDiffer.prototype.forEachMovedItem = function (fn) {
          var record;
          for (record = this._movesHead; record !== null; record = record._nextMoved) {
              fn(record);
          }
      };
      DefaultIterableDiffer.prototype.forEachRemovedItem = function (fn) {
          var record;
          for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
              fn(record);
          }
      };
      DefaultIterableDiffer.prototype.forEachIdentityChange = function (fn) {
          var record;
          for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {
              fn(record);
          }
      };
      DefaultIterableDiffer.prototype.diff = function (collection) {
          if (collection == null)
              collection = [];
          if (!isListLikeIterable$1(collection)) {
              throw new Error("Error trying to diff '" + stringify(collection) + "'. Only arrays and iterables are allowed");
          }
          if (this.check(collection)) {
              return this;
          }
          else {
              return null;
          }
      };
      DefaultIterableDiffer.prototype.onDestroy = function () { };
      DefaultIterableDiffer.prototype.check = function (collection) {
          var _this = this;
          this._reset();
          var record = this._itHead;
          var mayBeDirty = false;
          var index;
          var item;
          var itemTrackBy;
          if (Array.isArray(collection)) {
              this.length = collection.length;
              for (var index_1 = 0; index_1 < this.length; index_1++) {
                  item = collection[index_1];
                  itemTrackBy = this._trackByFn(index_1, item);
                  if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
                      record = this._mismatch(record, item, itemTrackBy, index_1);
                      mayBeDirty = true;
                  }
                  else {
                      if (mayBeDirty) {
                          // TODO(misko): can we limit this to duplicates only?
                          record = this._verifyReinsertion(record, item, itemTrackBy, index_1);
                      }
                      if (!looseIdentical(record.item, item))
                          this._addIdentityChange(record, item);
                  }
                  record = record._next;
              }
          }
          else {
              index = 0;
              iterateListLike$1(collection, function (item) {
                  itemTrackBy = _this._trackByFn(index, item);
                  if (record === null || !looseIdentical(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 (!looseIdentical(record.item, item))
                          _this._addIdentityChange(record, item);
                  }
                  record = record._next;
                  index++;
              });
              this.length = index;
          }
          this._truncate(record);
          this.collection = collection;
          return this.isDirty;
      };
      Object.defineProperty(DefaultIterableDiffer.prototype, "isDirty", {
          /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity
           * changes.
           */
          get: function () {
              return this._additionsHead !== null || this._movesHead !== null ||
                  this._removalsHead !== null || this._identityChangesHead !== null;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * 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
       */
      DefaultIterableDiffer.prototype._reset = function () {
          if (this.isDirty) {
              var record = void 0;
              var nextRecord = void 0;
              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 = nextRecord) {
                  record.previousIndex = record.currentIndex;
                  nextRecord = record._nextMoved;
              }
              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
       */
      DefaultIterableDiffer.prototype._mismatch = function (record, item, itemTrackBy, index) {
          // The previous record after which we will append the current one.
          var 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);
          }
          // Attempt to see if we have seen the item before.
          record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
          if (record !== null) {
              // We have seen this before, 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 (!looseIdentical(record.item, item))
                  this._addIdentityChange(record, item);
              this._moveAfter(record, previousRecord, index);
          }
          else {
              // Never seen it, check evicted 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 (!looseIdentical(record.item, item))
                      this._addIdentityChange(record, item);
                  this._reinsertAfter(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
       */
      DefaultIterableDiffer.prototype._verifyReinsertion = function (record, item, itemTrackBy, index) {
          var 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
       */
      DefaultIterableDiffer.prototype._truncate = function (record) {
          // Anything after that needs to be removed;
          while (record !== null) {
              var 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 */
      DefaultIterableDiffer.prototype._reinsertAfter = function (record, prevRecord, index) {
          if (this._unlinkedRecords !== null) {
              this._unlinkedRecords.remove(record);
          }
          var prev = record._prevRemoved;
          var 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 */
      DefaultIterableDiffer.prototype._moveAfter = function (record, prevRecord, index) {
          this._unlink(record);
          this._insertAfter(record, prevRecord, index);
          this._addToMoves(record, index);
          return record;
      };
      /** @internal */
      DefaultIterableDiffer.prototype._addAfter = function (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 */
      DefaultIterableDiffer.prototype._insertAfter = function (record, prevRecord, index) {
          // TODO(vicb):
          // assert(record != prevRecord);
          // assert(record._next === null);
          // assert(record._prev === null);
          var 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 */
      DefaultIterableDiffer.prototype._remove = function (record) {
          return this._addToRemovals(this._unlink(record));
      };
      /** @internal */
      DefaultIterableDiffer.prototype._unlink = function (record) {
          if (this._linkedRecords !== null) {
              this._linkedRecords.remove(record);
          }
          var prev = record._prev;
          var 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 */
      DefaultIterableDiffer.prototype._addToMoves = function (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;
      };
      DefaultIterableDiffer.prototype._addToRemovals = function (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 */
      DefaultIterableDiffer.prototype._addIdentityChange = function (record, item) {
          record.item = item;
          if (this._identityChangesTail === null) {
              this._identityChangesTail = this._identityChangesHead = record;
          }
          else {
              this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
          }
          return record;
      };
      return DefaultIterableDiffer;
  }());
  var IterableChangeRecord_ = /** @class */ (function () {
      function IterableChangeRecord_(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;
      }
      return IterableChangeRecord_;
  }());
  // A linked list of CollectionChangeRecords with the same IterableChangeRecord_.item
  var _DuplicateItemRecordList = /** @class */ (function () {
      function _DuplicateItemRecordList() {
          /** @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.
       */
      _DuplicateItemRecordList.prototype.add = function (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
      _DuplicateItemRecordList.prototype.get = function (trackById, atOrAfterIndex) {
          var record;
          for (record = this._head; record !== null; record = record._nextDup) {
              if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex) &&
                  looseIdentical(record.trackById, trackById)) {
                  return record;
              }
          }
          return null;
      };
      /**
       * Remove one {@link IterableChangeRecord_} from the list of duplicates.
       *
       * Returns whether the list of duplicates is empty.
       */
      _DuplicateItemRecordList.prototype.remove = function (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;
          //});
          var prev = record._prevDup;
          var 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;
      };
      return _DuplicateItemRecordList;
  }());
  var _DuplicateMap = /** @class */ (function () {
      function _DuplicateMap() {
          this.map = new Map();
      }
      _DuplicateMap.prototype.put = function (record) {
          var key = record.trackById;
          var 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`.
       */
      _DuplicateMap.prototype.get = function (trackById, atOrAfterIndex) {
          var key = trackById;
          var 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.
       */
      _DuplicateMap.prototype.remove = function (record) {
          var key = record.trackById;
          var recordList = this.map.get(key);
          // Remove the list of duplicates when it gets empty
          if (recordList.remove(record)) {
              this.map.delete(key);
          }
          return record;
      };
      Object.defineProperty(_DuplicateMap.prototype, "isEmpty", {
          get: function () {
              return this.map.size === 0;
          },
          enumerable: true,
          configurable: true
      });
      _DuplicateMap.prototype.clear = function () {
          this.map.clear();
      };
      return _DuplicateMap;
  }());
  function getPreviousIndex(item, addRemoveOffset, moveOffsets) {
      var previousIndex = item.previousIndex;
      if (previousIndex === null)
          return previousIndex;
      var moveOffset = 0;
      if (moveOffsets && previousIndex < moveOffsets.length) {
          moveOffset = moveOffsets[previousIndex];
      }
      return previousIndex + addRemoveOffset + moveOffset;
  }

  /**
   * @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
   */
  var DefaultKeyValueDifferFactory = /** @class */ (function () {
      function DefaultKeyValueDifferFactory() {
      }
      DefaultKeyValueDifferFactory.prototype.supports = function (obj) {
          return obj instanceof Map || isJsObject$1(obj);
      };
      DefaultKeyValueDifferFactory.prototype.create = function () {
          return new DefaultKeyValueDiffer();
      };
      return DefaultKeyValueDifferFactory;
  }());
  var DefaultKeyValueDiffer = /** @class */ (function () {
      function DefaultKeyValueDiffer() {
          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;
      }
      Object.defineProperty(DefaultKeyValueDiffer.prototype, "isDirty", {
          get: function () {
              return this._additionsHead !== null || this._changesHead !== null ||
                  this._removalsHead !== null;
          },
          enumerable: true,
          configurable: true
      });
      DefaultKeyValueDiffer.prototype.forEachItem = function (fn) {
          var record;
          for (record = this._mapHead; record !== null; record = record._next) {
              fn(record);
          }
      };
      DefaultKeyValueDiffer.prototype.forEachPreviousItem = function (fn) {
          var record;
          for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {
              fn(record);
          }
      };
      DefaultKeyValueDiffer.prototype.forEachChangedItem = function (fn) {
          var record;
          for (record = this._changesHead; record !== null; record = record._nextChanged) {
              fn(record);
          }
      };
      DefaultKeyValueDiffer.prototype.forEachAddedItem = function (fn) {
          var record;
          for (record = this._additionsHead; record !== null; record = record._nextAdded) {
              fn(record);
          }
      };
      DefaultKeyValueDiffer.prototype.forEachRemovedItem = function (fn) {
          var record;
          for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
              fn(record);
          }
      };
      DefaultKeyValueDiffer.prototype.diff = function (map) {
          if (!map) {
              map = new Map();
          }
          else if (!(map instanceof Map || isJsObject$1(map))) {
              throw new Error("Error trying to diff '" + stringify(map) + "'. Only maps and objects are allowed");
          }
          return this.check(map) ? this : null;
      };
      DefaultKeyValueDiffer.prototype.onDestroy = function () { };
      /**
       * Check the current state of the map vs the previous.
       * The algorithm is optimised for when the keys do no change.
       */
      DefaultKeyValueDiffer.prototype.check = function (map) {
          var _this = this;
          this._reset();
          var insertBefore = this._mapHead;
          this._appendAfter = null;
          this._forEach(map, function (value, key) {
              if (insertBefore && insertBefore.key === key) {
                  _this._maybeAddToChanges(insertBefore, value);
                  _this._appendAfter = insertBefore;
                  insertBefore = insertBefore._next;
              }
              else {
                  var 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 (var 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.
       */
      DefaultKeyValueDiffer.prototype._insertBeforeOrAppend = function (before, record) {
          if (before) {
              var 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;
      };
      DefaultKeyValueDiffer.prototype._getOrCreateRecordForKey = function (key, value) {
          if (this._records.has(key)) {
              var record_1 = this._records.get(key);
              this._maybeAddToChanges(record_1, value);
              var prev = record_1._prev;
              var next = record_1._next;
              if (prev) {
                  prev._next = next;
              }
              if (next) {
                  next._prev = prev;
              }
              record_1._next = null;
              record_1._prev = null;
              return record_1;
          }
          var record = new KeyValueChangeRecord_(key);
          this._records.set(key, record);
          record.currentValue = value;
          this._addToAdditions(record);
          return record;
      };
      /** @internal */
      DefaultKeyValueDiffer.prototype._reset = function () {
          if (this.isDirty) {
              var record = void 0;
              // 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
      DefaultKeyValueDiffer.prototype._maybeAddToChanges = function (record, newValue) {
          if (!looseIdentical(newValue, record.currentValue)) {
              record.previousValue = record.currentValue;
              record.currentValue = newValue;
              this._addToChanges(record);
          }
      };
      DefaultKeyValueDiffer.prototype._addToAdditions = function (record) {
          if (this._additionsHead === null) {
              this._additionsHead = this._additionsTail = record;
          }
          else {
              this._additionsTail._nextAdded = record;
              this._additionsTail = record;
          }
      };
      DefaultKeyValueDiffer.prototype._addToChanges = function (record) {
          if (this._changesHead === null) {
              this._changesHead = this._changesTail = record;
          }
          else {
              this._changesTail._nextChanged = record;
              this._changesTail = record;
          }
      };
      /** @internal */
      DefaultKeyValueDiffer.prototype._forEach = function (obj, fn) {
          if (obj instanceof Map) {
              obj.forEach(fn);
          }
          else {
              Object.keys(obj).forEach(function (k) { return fn(obj[k], k); });
          }
      };
      return DefaultKeyValueDiffer;
  }());
  var KeyValueChangeRecord_ = /** @class */ (function () {
      function KeyValueChangeRecord_(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;
      }
      return KeyValueChangeRecord_;
  }());

  /**
   * @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
   */
  /**
   * A repository of different iterable diffing strategies used by NgFor, NgClass, and others.
   *
   * @publicApi
   */
  var IterableDiffers = /** @class */ (function () {
      function IterableDiffers(factories) {
          this.factories = factories;
      }
      IterableDiffers.create = function (factories, parent) {
          if (parent != null) {
              var 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()])
       *   ]
       * })
       * ```
       */
      IterableDiffers.extend = function (factories) {
          return {
              provide: IterableDiffers,
              useFactory: function (parent) {
                  if (!parent) {
                      // Typically would occur when calling IterableDiffers.extend inside of dependencies passed
                      // to
                      // bootstrap(), which would override default pipes instead of extending them.
                      throw new Error('Cannot extend IterableDiffers without a parent injector');
                  }
                  return IterableDiffers.create(factories, parent);
              },
              // Dependency technically isn't optional, but we can provide a better error message this way.
              deps: [[IterableDiffers, new SkipSelf(), new Optional()]]
          };
      };
      IterableDiffers.prototype.find = function (iterable) {
          var factory = this.factories.find(function (f) { return f.supports(iterable); });
          if (factory != null) {
              return factory;
          }
          else {
              throw new Error("Cannot find a differ supporting object '" + iterable + "' of type '" + getTypeNameForDebugging(iterable) + "'");
          }
      };
      /** @nocollapse */
      IterableDiffers.ɵprov = ɵɵdefineInjectable({
          token: IterableDiffers,
          providedIn: 'root',
          factory: function () { return new IterableDiffers([new DefaultIterableDifferFactory()]); }
      });
      return IterableDiffers;
  }());
  function getTypeNameForDebugging(type) {
      return type['name'] || typeof type;
  }

  /**
   * @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
   */
  /**
   * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
   *
   * @publicApi
   */
  var KeyValueDiffers = /** @class */ (function () {
      function KeyValueDiffers(factories) {
          this.factories = factories;
      }
      KeyValueDiffers.create = function (factories, parent) {
          if (parent) {
              var 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()])
       *   ]
       * })
       * ```
       */
      KeyValueDiffers.extend = function (factories) {
          return {
              provide: KeyValueDiffers,
              useFactory: function (parent) {
                  if (!parent) {
                      // Typically would occur when calling KeyValueDiffers.extend inside of dependencies passed
                      // to bootstrap(), which would override default pipes instead of extending them.
                      throw new Error('Cannot extend KeyValueDiffers without a parent injector');
                  }
                  return KeyValueDiffers.create(factories, parent);
              },
              // Dependency technically isn't optional, but we can provide a better error message this way.
              deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
          };
      };
      KeyValueDiffers.prototype.find = function (kv) {
          var factory = this.factories.find(function (f) { return f.supports(kv); });
          if (factory) {
              return factory;
          }
          throw new Error("Cannot find a differ supporting object '" + kv + "'");
      };
      /** @nocollapse */
      KeyValueDiffers.ɵprov = ɵɵdefineInjectable({
          token: KeyValueDiffers,
          providedIn: 'root',
          factory: function () { return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]); }
      });
      return KeyValueDiffers;
  }());

  /**
   * @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
   */
  /**
   * Structural diffing for `Object`s and `Map`s.
   */
  var keyValDiff = [new DefaultKeyValueDifferFactory()];
  /**
   * Structural diffing for `Iterable` types such as `Array`s.
   */
  var iterableDiff = [new DefaultIterableDifferFactory()];
  var defaultIterableDiffers = new IterableDiffers(iterableDiff);
  var defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);

  /**
   * @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
   */
  /**
   * 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
   */
  var TemplateRef = /** @class */ (function () {
      function TemplateRef() {
      }
      /**
       * @internal
       * @nocollapse
       */
      TemplateRef.__NG_ELEMENT_ID__ = function () { return SWITCH_TEMPLATE_REF_FACTORY(TemplateRef, ElementRef); };
      return TemplateRef;
  }());
  var SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef;
  var SWITCH_TEMPLATE_REF_FACTORY__PRE_R3__ = noop;
  var SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__PRE_R3__;

  /**
   * @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
   */
  /**
   * 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
   */
  var ViewContainerRef = /** @class */ (function () {
      function ViewContainerRef() {
      }
      /**
       * @internal
       * @nocollapse
       */
      ViewContainerRef.__NG_ELEMENT_ID__ = function () { return SWITCH_VIEW_CONTAINER_REF_FACTORY(ViewContainerRef, ElementRef); };
      return ViewContainerRef;
  }());
  var SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__ = injectViewContainerRef;
  var SWITCH_VIEW_CONTAINER_REF_FACTORY__PRE_R3__ = noop;
  var SWITCH_VIEW_CONTAINER_REF_FACTORY = SWITCH_VIEW_CONTAINER_REF_FACTORY__PRE_R3__;

  /**
   * @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
   */
  function expressionChangedAfterItHasBeenCheckedError(context, oldValue, currValue, isFirstCheck) {
      var msg = "ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '" + oldValue + "'. Current value: '" + currValue + "'.";
      if (isFirstCheck) {
          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 ?";
      }
      return viewDebugError(msg, context);
  }
  function viewWrappedDebugError(err, context) {
      if (!(err instanceof Error)) {
          // errors that are not Error instances don't have a stack,
          // so it is ok to wrap them into a new Error object...
          err = new Error(err.toString());
      }
      _addDebugContext(err, context);
      return err;
  }
  function viewDebugError(msg, context) {
      var err = new Error(msg);
      _addDebugContext(err, context);
      return err;
  }
  function _addDebugContext(err, context) {
      err[ERROR_DEBUG_CONTEXT] = context;
      err[ERROR_LOGGER] = context.logError.bind(context);
  }
  function isViewDebugError(err) {
      return !!getDebugContext(err);
  }
  function viewDestroyedError(action) {
      return new Error("ViewDestroyedError: Attempt to use a destroyed view: " + action);
  }

  /**
   * @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
   */
  // Called before each cycle of a view's check to detect whether this is in the
  // initState for which we need to call ngOnInit, ngAfterContentInit or ngAfterViewInit
  // lifecycle methods. Returns true if this check cycle should call lifecycle
  // methods.
  function shiftInitState(view, priorInitState, newInitState) {
      // Only update the InitState if we are currently in the prior state.
      // For example, only move into CallingInit if we are in BeforeInit. Only
      // move into CallingContentInit if we are in CallingInit. Normally this will
      // always be true because of how checkCycle is called in checkAndUpdateView.
      // However, if checkAndUpdateView is called recursively or if an exception is
      // thrown while checkAndUpdateView is running, checkAndUpdateView starts over
      // from the beginning. This ensures the state is monotonically increasing,
      // terminating in the AfterInit state, which ensures the Init methods are called
      // at least once and only once.
      var state = view.state;
      var initState = state & 1792 /* InitState_Mask */;
      if (initState === priorInitState) {
          view.state = (state & ~1792 /* InitState_Mask */) | newInitState;
          view.initIndex = -1;
          return true;
      }
      return initState === newInitState;
  }
  // Returns true if the lifecycle init method should be called for the node with
  // the given init index.
  function shouldCallLifecycleInitHook(view, initState, index) {
      if ((view.state & 1792 /* InitState_Mask */) === initState && view.initIndex <= index) {
          view.initIndex = index + 1;
          return true;
      }
      return false;
  }
  /**
   * Node instance data.
   *
   * We have a separate type per NodeType to save memory
   * (TextData | ElementData | ProviderData | PureExpressionData | QueryList<any>)
   *
   * To keep our code monomorphic,
   * we prohibit using `NodeData` directly but enforce the use of accessors (`asElementData`, ...).
   * This way, no usage site can get a `NodeData` from view.nodes and then use it for different
   * purposes.
   */
  var NodeData = /** @class */ (function () {
      function NodeData() {
      }
      return NodeData;
  }());
  /**
   * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
   */
  function asTextData(view, index) {
      return view.nodes[index];
  }
  /**
   * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
   */
  function asElementData(view, index) {
      return view.nodes[index];
  }
  /**
   * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
   */
  function asProviderData(view, index) {
      return view.nodes[index];
  }
  /**
   * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
   */
  function asPureExpressionData(view, index) {
      return view.nodes[index];
  }
  /**
   * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
   */
  function asQueryList(view, index) {
      return view.nodes[index];
  }
  var DebugContext = /** @class */ (function () {
      function DebugContext() {
      }
      return DebugContext;
  }());
  /**
   * This object is used to prevent cycles in the source files and to have a place where
   * debug mode can hook it. It is lazily filled when `isDevMode` is known.
   */
  var Services = {
      setCurrentNode: undefined,
      createRootView: undefined,
      createEmbeddedView: undefined,
      createComponentView: undefined,
      createNgModuleRef: undefined,
      overrideProvider: undefined,
      overrideComponentView: undefined,
      clearOverrides: undefined,
      checkAndUpdateView: undefined,
      checkNoChangesView: undefined,
      destroyView: undefined,
      resolveDep: undefined,
      createDebugContext: undefined,
      handleEvent: undefined,
      updateDirectives: undefined,
      updateRenderer: undefined,
      dirtyParentQueries: undefined,
  };

  /**
   * @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
   */
  var NOOP = function () { };
  var _tokenKeyCache = new Map();
  function tokenKey(token) {
      var key = _tokenKeyCache.get(token);
      if (!key) {
          key = stringify(token) + '_' + _tokenKeyCache.size;
          _tokenKeyCache.set(token, key);
      }
      return key;
  }
  function unwrapValue(view, nodeIdx, bindingIdx, value) {
      if (WrappedValue.isWrapped(value)) {
          value = WrappedValue.unwrap(value);
          var globalBindingIdx = view.def.nodes[nodeIdx].bindingIndex + bindingIdx;
          var oldValue = WrappedValue.unwrap(view.oldValues[globalBindingIdx]);
          view.oldValues[globalBindingIdx] = new WrappedValue(oldValue);
      }
      return value;
  }
  var UNDEFINED_RENDERER_TYPE_ID = '$$undefined';
  var EMPTY_RENDERER_TYPE_ID = '$$empty';
  // Attention: this function is called as top level function.
  // Putting any logic in here will destroy closure tree shaking!
  function createRendererType2(values) {
      return {
          id: UNDEFINED_RENDERER_TYPE_ID,
          styles: values.styles,
          encapsulation: values.encapsulation,
          data: values.data
      };
  }
  var _renderCompCount$1 = 0;
  function resolveRendererType2(type) {
      if (type && type.id === UNDEFINED_RENDERER_TYPE_ID) {
          // first time we see this RendererType2. Initialize it...
          var isFilled = ((type.encapsulation != null && type.encapsulation !== exports.ViewEncapsulation.None) ||
              type.styles.length || Object.keys(type.data).length);
          if (isFilled) {
              type.id = "c" + _renderCompCount$1++;
          }
          else {
              type.id = EMPTY_RENDERER_TYPE_ID;
          }
      }
      if (type && type.id === EMPTY_RENDERER_TYPE_ID) {
          type = null;
      }
      return type || null;
  }
  function checkBinding(view, def, bindingIdx, value) {
      var oldValues = view.oldValues;
      if ((view.state & 2 /* FirstCheck */) ||
          !looseIdentical(oldValues[def.bindingIndex + bindingIdx], value)) {
          return true;
      }
      return false;
  }
  function checkAndUpdateBinding(view, def, bindingIdx, value) {
      if (checkBinding(view, def, bindingIdx, value)) {
          view.oldValues[def.bindingIndex + bindingIdx] = value;
          return true;
      }
      return false;
  }
  function checkBindingNoChanges(view, def, bindingIdx, value) {
      var oldValue = view.oldValues[def.bindingIndex + bindingIdx];
      if ((view.state & 1 /* BeforeFirstCheck */) || !devModeEqual$1(oldValue, value)) {
          var bindingName = def.bindings[bindingIdx].name;
          throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, def.nodeIndex), bindingName + ": " + oldValue, bindingName + ": " + value, (view.state & 1 /* BeforeFirstCheck */) !== 0);
      }
  }
  function markParentViewsForCheck(view) {
      var currView = view;
      while (currView) {
          if (currView.def.flags & 2 /* OnPush */) {
              currView.state |= 8 /* ChecksEnabled */;
          }
          currView = currView.viewContainerParent || currView.parent;
      }
  }
  function markParentViewsForCheckProjectedViews(view, endView) {
      var currView = view;
      while (currView && currView !== endView) {
          currView.state |= 64 /* CheckProjectedViews */;
          currView = currView.viewContainerParent || currView.parent;
      }
  }
  function dispatchEvent(view, nodeIndex, eventName, event) {
      try {
          var nodeDef = view.def.nodes[nodeIndex];
          var startView = nodeDef.flags & 33554432 /* ComponentView */ ?
              asElementData(view, nodeIndex).componentView :
              view;
          markParentViewsForCheck(startView);
          return Services.handleEvent(view, nodeIndex, eventName, event);
      }
      catch (e) {
          // Attention: Don't rethrow, as it would cancel Observable subscriptions!
          view.root.errorHandler.handleError(e);
      }
  }
  function declaredViewContainer(view) {
      if (view.parent) {
          var parentView = view.parent;
          return asElementData(parentView, view.parentNodeDef.nodeIndex);
      }
      return null;
  }
  /**
   * for component views, this is the host element.
   * for embedded views, this is the index of the parent node
   * that contains the view container.
   */
  function viewParentEl(view) {
      var parentView = view.parent;
      if (parentView) {
          return view.parentNodeDef.parent;
      }
      else {
          return null;
      }
  }
  function renderNode(view, def) {
      switch (def.flags & 201347067 /* Types */) {
          case 1 /* TypeElement */:
              return asElementData(view, def.nodeIndex).renderElement;
          case 2 /* TypeText */:
              return asTextData(view, def.nodeIndex).renderText;
      }
  }
  function elementEventFullName(target, name) {
      return target ? target + ":" + name : name;
  }
  function isComponentView(view) {
      return !!view.parent && !!(view.parentNodeDef.flags & 32768 /* Component */);
  }
  function isEmbeddedView(view) {
      return !!view.parent && !(view.parentNodeDef.flags & 32768 /* Component */);
  }
  function filterQueryId(queryId) {
      return 1 << (queryId % 32);
  }
  function splitMatchedQueriesDsl(matchedQueriesDsl) {
      var matchedQueries = {};
      var matchedQueryIds = 0;
      var references = {};
      if (matchedQueriesDsl) {
          matchedQueriesDsl.forEach(function (_a) {
              var _b = __read(_a, 2), queryId = _b[0], valueType = _b[1];
              if (typeof queryId === 'number') {
                  matchedQueries[queryId] = valueType;
                  matchedQueryIds |= filterQueryId(queryId);
              }
              else {
                  references[queryId] = valueType;
              }
          });
      }
      return { matchedQueries: matchedQueries, references: references, matchedQueryIds: matchedQueryIds };
  }
  function splitDepsDsl(deps, sourceName) {
      return deps.map(function (value) {
          var _a;
          var token;
          var flags;
          if (Array.isArray(value)) {
              _a = __read(value, 2), flags = _a[0], token = _a[1];
          }
          else {
              flags = 0 /* None */;
              token = value;
          }
          if (token && (typeof token === 'function' || typeof token === 'object') && sourceName) {
              Object.defineProperty(token, SOURCE, { value: sourceName, configurable: true });
          }
          return { flags: flags, token: token, tokenKey: tokenKey(token) };
      });
  }
  function getParentRenderElement(view, renderHost, def) {
      var renderParent = def.renderParent;
      if (renderParent) {
          if ((renderParent.flags & 1 /* TypeElement */) === 0 ||
              (renderParent.flags & 33554432 /* ComponentView */) === 0 ||
              (renderParent.element.componentRendererType &&
                  renderParent.element.componentRendererType.encapsulation === exports.ViewEncapsulation.Native)) {
              // only children of non components, or children of components with native encapsulation should
              // be attached.
              return asElementData(view, def.renderParent.nodeIndex).renderElement;
          }
      }
      else {
          return renderHost;
      }
  }
  var DEFINITION_CACHE = new WeakMap();
  function resolveDefinition(factory) {
      var value = DEFINITION_CACHE.get(factory);
      if (!value) {
          value = factory(function () { return NOOP; });
          value.factory = factory;
          DEFINITION_CACHE.set(factory, value);
      }
      return value;
  }
  function rootRenderNodes(view) {
      var renderNodes = [];
      visitRootRenderNodes(view, 0 /* Collect */, undefined, undefined, renderNodes);
      return renderNodes;
  }
  function visitRootRenderNodes(view, action, parentNode, nextSibling, target) {
      // We need to re-compute the parent node in case the nodes have been moved around manually
      if (action === 3 /* RemoveChild */) {
          parentNode = view.renderer.parentNode(renderNode(view, view.def.lastRenderRootNode));
      }
      visitSiblingRenderNodes(view, action, 0, view.def.nodes.length - 1, parentNode, nextSibling, target);
  }
  function visitSiblingRenderNodes(view, action, startIndex, endIndex, parentNode, nextSibling, target) {
      for (var i = startIndex; i <= endIndex; i++) {
          var nodeDef = view.def.nodes[i];
          if (nodeDef.flags & (1 /* TypeElement */ | 2 /* TypeText */ | 8 /* TypeNgContent */)) {
              visitRenderNode(view, nodeDef, action, parentNode, nextSibling, target);
          }
          // jump to next sibling
          i += nodeDef.childCount;
      }
  }
  function visitProjectedRenderNodes(view, ngContentIndex, action, parentNode, nextSibling, target) {
      var compView = view;
      while (compView && !isComponentView(compView)) {
          compView = compView.parent;
      }
      var hostView = compView.parent;
      var hostElDef = viewParentEl(compView);
      var startIndex = hostElDef.nodeIndex + 1;
      var endIndex = hostElDef.nodeIndex + hostElDef.childCount;
      for (var i = startIndex; i <= endIndex; i++) {
          var nodeDef = hostView.def.nodes[i];
          if (nodeDef.ngContentIndex === ngContentIndex) {
              visitRenderNode(hostView, nodeDef, action, parentNode, nextSibling, target);
          }
          // jump to next sibling
          i += nodeDef.childCount;
      }
      if (!hostView.parent) {
          // a root view
          var projectedNodes = view.root.projectableNodes[ngContentIndex];
          if (projectedNodes) {
              for (var i = 0; i < projectedNodes.length; i++) {
                  execRenderNodeAction(view, projectedNodes[i], action, parentNode, nextSibling, target);
              }
          }
      }
  }
  function visitRenderNode(view, nodeDef, action, parentNode, nextSibling, target) {
      if (nodeDef.flags & 8 /* TypeNgContent */) {
          visitProjectedRenderNodes(view, nodeDef.ngContent.index, action, parentNode, nextSibling, target);
      }
      else {
          var rn = renderNode(view, nodeDef);
          if (action === 3 /* RemoveChild */ && (nodeDef.flags & 33554432 /* ComponentView */) &&
              (nodeDef.bindingFlags & 48 /* CatSyntheticProperty */)) {
              // Note: we might need to do both actions.
              if (nodeDef.bindingFlags & (16 /* SyntheticProperty */)) {
                  execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
              }
              if (nodeDef.bindingFlags & (32 /* SyntheticHostProperty */)) {
                  var compView = asElementData(view, nodeDef.nodeIndex).componentView;
                  execRenderNodeAction(compView, rn, action, parentNode, nextSibling, target);
              }
          }
          else {
              execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
          }
          if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
              var embeddedViews = asElementData(view, nodeDef.nodeIndex).viewContainer._embeddedViews;
              for (var k = 0; k < embeddedViews.length; k++) {
                  visitRootRenderNodes(embeddedViews[k], action, parentNode, nextSibling, target);
              }
          }
          if (nodeDef.flags & 1 /* TypeElement */ && !nodeDef.element.name) {
              visitSiblingRenderNodes(view, action, nodeDef.nodeIndex + 1, nodeDef.nodeIndex + nodeDef.childCount, parentNode, nextSibling, target);
          }
      }
  }
  function execRenderNodeAction(view, renderNode, action, parentNode, nextSibling, target) {
      var renderer = view.renderer;
      switch (action) {
          case 1 /* AppendChild */:
              renderer.appendChild(parentNode, renderNode);
              break;
          case 2 /* InsertBefore */:
              renderer.insertBefore(parentNode, renderNode, nextSibling);
              break;
          case 3 /* RemoveChild */:
              renderer.removeChild(parentNode, renderNode);
              break;
          case 0 /* Collect */:
              target.push(renderNode);
              break;
      }
  }
  var NS_PREFIX_RE = /^:([^:]+):(.+)$/;
  function splitNamespace(name) {
      if (name[0] === ':') {
          var match = name.match(NS_PREFIX_RE);
          return [match[1], match[2]];
      }
      return ['', name];
  }
  function calcBindingFlags(bindings) {
      var flags = 0;
      for (var i = 0; i < bindings.length; i++) {
          flags |= bindings[i].flags;
      }
      return flags;
  }
  function interpolate(valueCount, constAndInterp) {
      var result = '';
      for (var i = 0; i < valueCount * 2; i = i + 2) {
          result = result + constAndInterp[i] + _toStringWithNull(constAndInterp[i + 1]);
      }
      return result + constAndInterp[valueCount * 2];
  }
  function inlineInterpolate(valueCount, c0, a1, c1, a2, c2, a3, c3, a4, c4, a5, c5, a6, c6, a7, c7, a8, c8, a9, c9) {
      switch (valueCount) {
          case 1:
              return c0 + _toStringWithNull(a1) + c1;
          case 2:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2;
          case 3:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3;
          case 4:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3 + _toStringWithNull(a4) + c4;
          case 5:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5;
          case 6:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) + c6;
          case 7:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
                  c6 + _toStringWithNull(a7) + c7;
          case 8:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
                  c6 + _toStringWithNull(a7) + c7 + _toStringWithNull(a8) + c8;
          case 9:
              return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
                  c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
                  c6 + _toStringWithNull(a7) + c7 + _toStringWithNull(a8) + c8 + _toStringWithNull(a9) + c9;
          default:
              throw new Error("Does not support more than 9 expressions");
      }
  }
  function _toStringWithNull(v) {
      return v != null ? v.toString() : '';
  }
  var EMPTY_ARRAY$4 = [];
  var EMPTY_MAP = {};

  /**
   * @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
   */
  var UNDEFINED_VALUE = {};
  var InjectorRefTokenKey = tokenKey(Injector);
  var INJECTORRefTokenKey = tokenKey(INJECTOR);
  var NgModuleRefTokenKey = tokenKey(NgModuleRef);
  function moduleProvideDef(flags, token, value, deps) {
      // Need to resolve forwardRefs as e.g. for `useValue` we
      // lowered the expression and then stopped evaluating it,
      // i.e. also didn't unwrap it.
      value = resolveForwardRef(value);
      var depDefs = splitDepsDsl(deps, stringify(token));
      return {
          // will bet set by the module definition
          index: -1,
          deps: depDefs,
          flags: flags,
          token: token,
          value: value
      };
  }
  function moduleDef(providers) {
      var providersByKey = {};
      var modules = [];
      var scope = null;
      for (var i = 0; i < providers.length; i++) {
          var provider = providers[i];
          if (provider.token === INJECTOR_SCOPE) {
              scope = provider.value;
          }
          if (provider.flags & 1073741824 /* TypeNgModule */) {
              modules.push(provider.token);
          }
          provider.index = i;
          providersByKey[tokenKey(provider.token)] = provider;
      }
      return {
          // Will be filled later...
          factory: null,
          providersByKey: providersByKey,
          providers: providers,
          modules: modules,
          scope: scope,
      };
  }
  function initNgModule(data) {
      var def = data._def;
      var providers = data._providers = newArray(def.providers.length);
      for (var i = 0; i < def.providers.length; i++) {
          var provDef = def.providers[i];
          if (!(provDef.flags & 4096 /* LazyProvider */)) {
              // Make sure the provider has not been already initialized outside this loop.
              if (providers[i] === undefined) {
                  providers[i] = _createProviderInstance(data, provDef);
              }
          }
      }
  }
  function resolveNgModuleDep(data, depDef, notFoundValue) {
      if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
      var former = setCurrentInjector(data);
      try {
          if (depDef.flags & 8 /* Value */) {
              return depDef.token;
          }
          if (depDef.flags & 2 /* Optional */) {
              notFoundValue = null;
          }
          if (depDef.flags & 1 /* SkipSelf */) {
              return data._parent.get(depDef.token, notFoundValue);
          }
          var tokenKey_1 = depDef.tokenKey;
          switch (tokenKey_1) {
              case InjectorRefTokenKey:
              case INJECTORRefTokenKey:
              case NgModuleRefTokenKey:
                  return data;
          }
          var providerDef = data._def.providersByKey[tokenKey_1];
          var injectableDef = void 0;
          if (providerDef) {
              var providerInstance = data._providers[providerDef.index];
              if (providerInstance === undefined) {
                  providerInstance = data._providers[providerDef.index] =
                      _createProviderInstance(data, providerDef);
              }
              return providerInstance === UNDEFINED_VALUE ? undefined : providerInstance;
          }
          else if ((injectableDef = getInjectableDef(depDef.token)) && targetsModule(data, injectableDef)) {
              var index = data._providers.length;
              data._def.providers[index] = data._def.providersByKey[depDef.tokenKey] = {
                  flags: 1024 /* TypeFactoryProvider */ | 4096 /* LazyProvider */,
                  value: injectableDef.factory,
                  deps: [],
                  index: index,
                  token: depDef.token,
              };
              data._providers[index] = UNDEFINED_VALUE;
              return (data._providers[index] =
                  _createProviderInstance(data, data._def.providersByKey[depDef.tokenKey]));
          }
          else if (depDef.flags & 4 /* Self */) {
              return notFoundValue;
          }
          return data._parent.get(depDef.token, notFoundValue);
      }
      finally {
          setCurrentInjector(former);
      }
  }
  function moduleTransitivelyPresent(ngModule, scope) {
      return ngModule._def.modules.indexOf(scope) > -1;
  }
  function targetsModule(ngModule, def) {
      var providedIn = def.providedIn;
      return providedIn != null &&
          (providedIn === 'any' || providedIn === ngModule._def.scope ||
              moduleTransitivelyPresent(ngModule, providedIn));
  }
  function _createProviderInstance(ngModule, providerDef) {
      var injectable;
      switch (providerDef.flags & 201347067 /* Types */) {
          case 512 /* TypeClassProvider */:
              injectable = _createClass(ngModule, providerDef.value, providerDef.deps);
              break;
          case 1024 /* TypeFactoryProvider */:
              injectable = _callFactory(ngModule, providerDef.value, providerDef.deps);
              break;
          case 2048 /* TypeUseExistingProvider */:
              injectable = resolveNgModuleDep(ngModule, providerDef.deps[0]);
              break;
          case 256 /* TypeValueProvider */:
              injectable = providerDef.value;
              break;
      }
      // The read of `ngOnDestroy` here is slightly expensive as it's megamorphic, so it should be
      // avoided if possible. The sequence of checks here determines whether ngOnDestroy needs to be
      // checked. It might not if the `injectable` isn't an object or if NodeFlags.OnDestroy is already
      // set (ngOnDestroy was detected statically).
      if (injectable !== UNDEFINED_VALUE && injectable !== null && typeof injectable === 'object' &&
          !(providerDef.flags & 131072 /* OnDestroy */) && typeof injectable.ngOnDestroy === 'function') {
          providerDef.flags |= 131072 /* OnDestroy */;
      }
      return injectable === undefined ? UNDEFINED_VALUE : injectable;
  }
  function _createClass(ngModule, ctor, deps) {
      var len = deps.length;
      switch (len) {
          case 0:
              return new ctor();
          case 1:
              return new ctor(resolveNgModuleDep(ngModule, deps[0]));
          case 2:
              return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
          case 3:
              return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2]));
          default:
              var depValues = [];
              for (var i = 0; i < len; i++) {
                  depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
              }
              return new (ctor.bind.apply(ctor, __spread([void 0], depValues)))();
      }
  }
  function _callFactory(ngModule, factory, deps) {
      var len = deps.length;
      switch (len) {
          case 0:
              return factory();
          case 1:
              return factory(resolveNgModuleDep(ngModule, deps[0]));
          case 2:
              return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
          case 3:
              return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2]));
          default:
              var depValues = [];
              for (var i = 0; i < len; i++) {
                  depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
              }
              return factory.apply(void 0, __spread(depValues));
      }
  }
  function callNgModuleLifecycle(ngModule, lifecycles) {
      var def = ngModule._def;
      var destroyed = new Set();
      for (var i = 0; i < def.providers.length; i++) {
          var provDef = def.providers[i];
          if (provDef.flags & 131072 /* OnDestroy */) {
              var instance = ngModule._providers[i];
              if (instance && instance !== UNDEFINED_VALUE) {
                  var onDestroy = instance.ngOnDestroy;
                  if (typeof onDestroy === 'function' && !destroyed.has(instance)) {
                      onDestroy.apply(instance);
                      destroyed.add(instance);
                  }
              }
          }
      }
  }

  /**
   * @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
   */
  function attachEmbeddedView(parentView, elementData, viewIndex, view) {
      var embeddedViews = elementData.viewContainer._embeddedViews;
      if (viewIndex === null || viewIndex === undefined) {
          viewIndex = embeddedViews.length;
      }
      view.viewContainerParent = parentView;
      addToArray(embeddedViews, viewIndex, view);
      attachProjectedView(elementData, view);
      Services.dirtyParentQueries(view);
      var prevView = viewIndex > 0 ? embeddedViews[viewIndex - 1] : null;
      renderAttachEmbeddedView(elementData, prevView, view);
  }
  function attachProjectedView(vcElementData, view) {
      var dvcElementData = declaredViewContainer(view);
      if (!dvcElementData || dvcElementData === vcElementData ||
          view.state & 16 /* IsProjectedView */) {
          return;
      }
      // Note: For performance reasons, we
      // - add a view to template._projectedViews only 1x throughout its lifetime,
      //   and remove it not until the view is destroyed.
      //   (hard, as when a parent view is attached/detached we would need to attach/detach all
      //    nested projected views as well, even across component boundaries).
      // - don't track the insertion order of views in the projected views array
      //   (hard, as when the views of the same template are inserted different view containers)
      view.state |= 16 /* IsProjectedView */;
      var projectedViews = dvcElementData.template._projectedViews;
      if (!projectedViews) {
          projectedViews = dvcElementData.template._projectedViews = [];
      }
      projectedViews.push(view);
      // Note: we are changing the NodeDef here as we cannot calculate
      // the fact whether a template is used for projection during compilation.
      markNodeAsProjectedTemplate(view.parent.def, view.parentNodeDef);
  }
  function markNodeAsProjectedTemplate(viewDef, nodeDef) {
      if (nodeDef.flags & 4 /* ProjectedTemplate */) {
          return;
      }
      viewDef.nodeFlags |= 4 /* ProjectedTemplate */;
      nodeDef.flags |= 4 /* ProjectedTemplate */;
      var parentNodeDef = nodeDef.parent;
      while (parentNodeDef) {
          parentNodeDef.childFlags |= 4 /* ProjectedTemplate */;
          parentNodeDef = parentNodeDef.parent;
      }
  }
  function detachEmbeddedView(elementData, viewIndex) {
      var embeddedViews = elementData.viewContainer._embeddedViews;
      if (viewIndex == null || viewIndex >= embeddedViews.length) {
          viewIndex = embeddedViews.length - 1;
      }
      if (viewIndex < 0) {
          return null;
      }
      var view = embeddedViews[viewIndex];
      view.viewContainerParent = null;
      removeFromArray(embeddedViews, viewIndex);
      // See attachProjectedView for why we don't update projectedViews here.
      Services.dirtyParentQueries(view);
      renderDetachView$1(view);
      return view;
  }
  function detachProjectedView(view) {
      if (!(view.state & 16 /* IsProjectedView */)) {
          return;
      }
      var dvcElementData = declaredViewContainer(view);
      if (dvcElementData) {
          var projectedViews = dvcElementData.template._projectedViews;
          if (projectedViews) {
              removeFromArray(projectedViews, projectedViews.indexOf(view));
              Services.dirtyParentQueries(view);
          }
      }
  }
  function moveEmbeddedView(elementData, oldViewIndex, newViewIndex) {
      var embeddedViews = elementData.viewContainer._embeddedViews;
      var view = embeddedViews[oldViewIndex];
      removeFromArray(embeddedViews, oldViewIndex);
      if (newViewIndex == null) {
          newViewIndex = embeddedViews.length;
      }
      addToArray(embeddedViews, newViewIndex, view);
      // Note: Don't need to change projectedViews as the order in there
      // as always invalid...
      Services.dirtyParentQueries(view);
      renderDetachView$1(view);
      var prevView = newViewIndex > 0 ? embeddedViews[newViewIndex - 1] : null;
      renderAttachEmbeddedView(elementData, prevView, view);
      return view;
  }
  function renderAttachEmbeddedView(elementData, prevView, view) {
      var prevRenderNode = prevView ? renderNode(prevView, prevView.def.lastRenderRootNode) : elementData.renderElement;
      var parentNode = view.renderer.parentNode(prevRenderNode);
      var nextSibling = view.renderer.nextSibling(prevRenderNode);
      // Note: We can't check if `nextSibling` is present, as on WebWorkers it will always be!
      // However, browsers automatically do `appendChild` when there is no `nextSibling`.
      visitRootRenderNodes(view, 2 /* InsertBefore */, parentNode, nextSibling, undefined);
  }
  function renderDetachView$1(view) {
      visitRootRenderNodes(view, 3 /* RemoveChild */, null, null, undefined);
  }

  /**
   * @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
   */
  var EMPTY_CONTEXT = {};
  // Attention: this function is called as top level function.
  // Putting any logic in here will destroy closure tree shaking!
  function createComponentFactory(selector, componentType, viewDefFactory, inputs, outputs, ngContentSelectors) {
      return new ComponentFactory_(selector, componentType, viewDefFactory, inputs, outputs, ngContentSelectors);
  }
  function getComponentViewDefinitionFactory(componentFactory) {
      return componentFactory.viewDefFactory;
  }
  var ComponentFactory_ = /** @class */ (function (_super) {
      __extends(ComponentFactory_, _super);
      function ComponentFactory_(selector, componentType, viewDefFactory, _inputs, _outputs, ngContentSelectors) {
          var _this = 
          // Attention: this ctor is called as top level function.
          // Putting any logic in here will destroy closure tree shaking!
          _super.call(this) || this;
          _this.selector = selector;
          _this.componentType = componentType;
          _this._inputs = _inputs;
          _this._outputs = _outputs;
          _this.ngContentSelectors = ngContentSelectors;
          _this.viewDefFactory = viewDefFactory;
          return _this;
      }
      Object.defineProperty(ComponentFactory_.prototype, "inputs", {
          get: function () {
              var inputsArr = [];
              var inputs = this._inputs;
              for (var propName in inputs) {
                  var templateName = inputs[propName];
                  inputsArr.push({ propName: propName, templateName: templateName });
              }
              return inputsArr;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ComponentFactory_.prototype, "outputs", {
          get: function () {
              var outputsArr = [];
              for (var propName in this._outputs) {
                  var templateName = this._outputs[propName];
                  outputsArr.push({ propName: propName, templateName: templateName });
              }
              return outputsArr;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * Creates a new component.
       */
      ComponentFactory_.prototype.create = function (injector, projectableNodes, rootSelectorOrNode, ngModule) {
          if (!ngModule) {
              throw new Error('ngModule should be provided');
          }
          var viewDef = resolveDefinition(this.viewDefFactory);
          var componentNodeIndex = viewDef.nodes[0].element.componentProvider.nodeIndex;
          var view = Services.createRootView(injector, projectableNodes || [], rootSelectorOrNode, viewDef, ngModule, EMPTY_CONTEXT);
          var component = asProviderData(view, componentNodeIndex).instance;
          if (rootSelectorOrNode) {
              view.renderer.setAttribute(asElementData(view, 0).renderElement, 'ng-version', VERSION.full);
          }
          return new ComponentRef_(view, new ViewRef_(view), component);
      };
      return ComponentFactory_;
  }(ComponentFactory));
  var ComponentRef_ = /** @class */ (function (_super) {
      __extends(ComponentRef_, _super);
      function ComponentRef_(_view, _viewRef, _component) {
          var _this = _super.call(this) || this;
          _this._view = _view;
          _this._viewRef = _viewRef;
          _this._component = _component;
          _this._elDef = _this._view.def.nodes[0];
          _this.hostView = _viewRef;
          _this.changeDetectorRef = _viewRef;
          _this.instance = _component;
          return _this;
      }
      Object.defineProperty(ComponentRef_.prototype, "location", {
          get: function () {
              return new ElementRef(asElementData(this._view, this._elDef.nodeIndex).renderElement);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ComponentRef_.prototype, "injector", {
          get: function () {
              return new Injector_(this._view, this._elDef);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ComponentRef_.prototype, "componentType", {
          get: function () {
              return this._component.constructor;
          },
          enumerable: true,
          configurable: true
      });
      ComponentRef_.prototype.destroy = function () {
          this._viewRef.destroy();
      };
      ComponentRef_.prototype.onDestroy = function (callback) {
          this._viewRef.onDestroy(callback);
      };
      return ComponentRef_;
  }(ComponentRef));
  function createViewContainerData(view, elDef, elData) {
      return new ViewContainerRef_(view, elDef, elData);
  }
  var ViewContainerRef_ = /** @class */ (function () {
      function ViewContainerRef_(_view, _elDef, _data) {
          this._view = _view;
          this._elDef = _elDef;
          this._data = _data;
          /**
           * @internal
           */
          this._embeddedViews = [];
      }
      Object.defineProperty(ViewContainerRef_.prototype, "element", {
          get: function () {
              return new ElementRef(this._data.renderElement);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ViewContainerRef_.prototype, "injector", {
          get: function () {
              return new Injector_(this._view, this._elDef);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ViewContainerRef_.prototype, "parentInjector", {
          /** @deprecated No replacement */
          get: function () {
              var view = this._view;
              var elDef = this._elDef.parent;
              while (!elDef && view) {
                  elDef = viewParentEl(view);
                  view = view.parent;
              }
              return view ? new Injector_(view, elDef) : new Injector_(this._view, null);
          },
          enumerable: true,
          configurable: true
      });
      ViewContainerRef_.prototype.clear = function () {
          var len = this._embeddedViews.length;
          for (var i = len - 1; i >= 0; i--) {
              var view = detachEmbeddedView(this._data, i);
              Services.destroyView(view);
          }
      };
      ViewContainerRef_.prototype.get = function (index) {
          var view = this._embeddedViews[index];
          if (view) {
              var ref = new ViewRef_(view);
              ref.attachToViewContainerRef(this);
              return ref;
          }
          return null;
      };
      Object.defineProperty(ViewContainerRef_.prototype, "length", {
          get: function () {
              return this._embeddedViews.length;
          },
          enumerable: true,
          configurable: true
      });
      ViewContainerRef_.prototype.createEmbeddedView = function (templateRef, context, index) {
          var viewRef = templateRef.createEmbeddedView(context || {});
          this.insert(viewRef, index);
          return viewRef;
      };
      ViewContainerRef_.prototype.createComponent = function (componentFactory, index, injector, projectableNodes, ngModuleRef) {
          var contextInjector = injector || this.parentInjector;
          if (!ngModuleRef && !(componentFactory instanceof ComponentFactoryBoundToModule)) {
              ngModuleRef = contextInjector.get(NgModuleRef);
          }
          var componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
          this.insert(componentRef.hostView, index);
          return componentRef;
      };
      ViewContainerRef_.prototype.insert = function (viewRef, index) {
          if (viewRef.destroyed) {
              throw new Error('Cannot insert a destroyed View in a ViewContainer!');
          }
          var viewRef_ = viewRef;
          var viewData = viewRef_._view;
          attachEmbeddedView(this._view, this._data, index, viewData);
          viewRef_.attachToViewContainerRef(this);
          return viewRef;
      };
      ViewContainerRef_.prototype.move = function (viewRef, currentIndex) {
          if (viewRef.destroyed) {
              throw new Error('Cannot move a destroyed View in a ViewContainer!');
          }
          var previousIndex = this._embeddedViews.indexOf(viewRef._view);
          moveEmbeddedView(this._data, previousIndex, currentIndex);
          return viewRef;
      };
      ViewContainerRef_.prototype.indexOf = function (viewRef) {
          return this._embeddedViews.indexOf(viewRef._view);
      };
      ViewContainerRef_.prototype.remove = function (index) {
          var viewData = detachEmbeddedView(this._data, index);
          if (viewData) {
              Services.destroyView(viewData);
          }
      };
      ViewContainerRef_.prototype.detach = function (index) {
          var view = detachEmbeddedView(this._data, index);
          return view ? new ViewRef_(view) : null;
      };
      return ViewContainerRef_;
  }());
  function createChangeDetectorRef(view) {
      return new ViewRef_(view);
  }
  var ViewRef_ = /** @class */ (function () {
      function ViewRef_(_view) {
          this._view = _view;
          this._viewContainerRef = null;
          this._appRef = null;
      }
      Object.defineProperty(ViewRef_.prototype, "rootNodes", {
          get: function () {
              return rootRenderNodes(this._view);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ViewRef_.prototype, "context", {
          get: function () {
              return this._view.context;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ViewRef_.prototype, "destroyed", {
          get: function () {
              return (this._view.state & 128 /* Destroyed */) !== 0;
          },
          enumerable: true,
          configurable: true
      });
      ViewRef_.prototype.markForCheck = function () {
          markParentViewsForCheck(this._view);
      };
      ViewRef_.prototype.detach = function () {
          this._view.state &= ~4 /* Attached */;
      };
      ViewRef_.prototype.detectChanges = function () {
          var fs = this._view.root.rendererFactory;
          if (fs.begin) {
              fs.begin();
          }
          try {
              Services.checkAndUpdateView(this._view);
          }
          finally {
              if (fs.end) {
                  fs.end();
              }
          }
      };
      ViewRef_.prototype.checkNoChanges = function () {
          Services.checkNoChangesView(this._view);
      };
      ViewRef_.prototype.reattach = function () {
          this._view.state |= 4 /* Attached */;
      };
      ViewRef_.prototype.onDestroy = function (callback) {
          if (!this._view.disposables) {
              this._view.disposables = [];
          }
          this._view.disposables.push(callback);
      };
      ViewRef_.prototype.destroy = function () {
          if (this._appRef) {
              this._appRef.detachView(this);
          }
          else if (this._viewContainerRef) {
              this._viewContainerRef.detach(this._viewContainerRef.indexOf(this));
          }
          Services.destroyView(this._view);
      };
      ViewRef_.prototype.detachFromAppRef = function () {
          this._appRef = null;
          renderDetachView$1(this._view);
          Services.dirtyParentQueries(this._view);
      };
      ViewRef_.prototype.attachToAppRef = function (appRef) {
          if (this._viewContainerRef) {
              throw new Error('This view is already attached to a ViewContainer!');
          }
          this._appRef = appRef;
      };
      ViewRef_.prototype.attachToViewContainerRef = function (vcRef) {
          if (this._appRef) {
              throw new Error('This view is already attached directly to the ApplicationRef!');
          }
          this._viewContainerRef = vcRef;
      };
      return ViewRef_;
  }());
  function createTemplateData(view, def) {
      return new TemplateRef_(view, def);
  }
  var TemplateRef_ = /** @class */ (function (_super) {
      __extends(TemplateRef_, _super);
      function TemplateRef_(_parentView, _def) {
          var _this = _super.call(this) || this;
          _this._parentView = _parentView;
          _this._def = _def;
          return _this;
      }
      TemplateRef_.prototype.createEmbeddedView = function (context) {
          return new ViewRef_(Services.createEmbeddedView(this._parentView, this._def, this._def.element.template, context));
      };
      Object.defineProperty(TemplateRef_.prototype, "elementRef", {
          get: function () {
              return new ElementRef(asElementData(this._parentView, this._def.nodeIndex).renderElement);
          },
          enumerable: true,
          configurable: true
      });
      return TemplateRef_;
  }(TemplateRef));
  function createInjector$1(view, elDef) {
      return new Injector_(view, elDef);
  }
  var Injector_ = /** @class */ (function () {
      function Injector_(view, elDef) {
          this.view = view;
          this.elDef = elDef;
      }
      Injector_.prototype.get = function (token, notFoundValue) {
          if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
          var allowPrivateServices = this.elDef ? (this.elDef.flags & 33554432 /* ComponentView */) !== 0 : false;
          return Services.resolveDep(this.view, this.elDef, allowPrivateServices, { flags: 0 /* None */, token: token, tokenKey: tokenKey(token) }, notFoundValue);
      };
      return Injector_;
  }());
  function nodeValue(view, index) {
      var def = view.def.nodes[index];
      if (def.flags & 1 /* TypeElement */) {
          var elData = asElementData(view, def.nodeIndex);
          return def.element.template ? elData.template : elData.renderElement;
      }
      else if (def.flags & 2 /* TypeText */) {
          return asTextData(view, def.nodeIndex).renderText;
      }
      else if (def.flags & (20224 /* CatProvider */ | 16 /* TypePipe */)) {
          return asProviderData(view, def.nodeIndex).instance;
      }
      throw new Error("Illegal state: read nodeValue for node index " + index);
  }
  function createNgModuleRef(moduleType, parent, bootstrapComponents, def) {
      return new NgModuleRef_(moduleType, parent, bootstrapComponents, def);
  }
  var NgModuleRef_ = /** @class */ (function () {
      function NgModuleRef_(_moduleType, _parent, _bootstrapComponents, _def) {
          this._moduleType = _moduleType;
          this._parent = _parent;
          this._bootstrapComponents = _bootstrapComponents;
          this._def = _def;
          this._destroyListeners = [];
          this._destroyed = false;
          this.injector = this;
          initNgModule(this);
      }
      NgModuleRef_.prototype.get = function (token, notFoundValue, injectFlags) {
          if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
          if (injectFlags === void 0) { injectFlags = exports.InjectFlags.Default; }
          var flags = 0 /* None */;
          if (injectFlags & exports.InjectFlags.SkipSelf) {
              flags |= 1 /* SkipSelf */;
          }
          else if (injectFlags & exports.InjectFlags.Self) {
              flags |= 4 /* Self */;
          }
          return resolveNgModuleDep(this, { token: token, tokenKey: tokenKey(token), flags: flags }, notFoundValue);
      };
      Object.defineProperty(NgModuleRef_.prototype, "instance", {
          get: function () {
              return this.get(this._moduleType);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(NgModuleRef_.prototype, "componentFactoryResolver", {
          get: function () {
              return this.get(ComponentFactoryResolver);
          },
          enumerable: true,
          configurable: true
      });
      NgModuleRef_.prototype.destroy = function () {
          if (this._destroyed) {
              throw new Error("The ng module " + stringify(this.instance.constructor) + " has already been destroyed.");
          }
          this._destroyed = true;
          callNgModuleLifecycle(this, 131072 /* OnDestroy */);
          this._destroyListeners.forEach(function (listener) { return listener(); });
      };
      NgModuleRef_.prototype.onDestroy = function (callback) {
          this._destroyListeners.push(callback);
      };
      return NgModuleRef_;
  }());

  /**
   * @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
   */
  var Renderer2TokenKey = tokenKey(Renderer2);
  var ElementRefTokenKey = tokenKey(ElementRef);
  var ViewContainerRefTokenKey = tokenKey(ViewContainerRef);
  var TemplateRefTokenKey = tokenKey(TemplateRef);
  var ChangeDetectorRefTokenKey = tokenKey(ChangeDetectorRef);
  var InjectorRefTokenKey$1 = tokenKey(Injector);
  var INJECTORRefTokenKey$1 = tokenKey(INJECTOR);
  function directiveDef(checkIndex, flags, matchedQueries, childCount, ctor, deps, props, outputs) {
      var bindings = [];
      if (props) {
          for (var prop in props) {
              var _a = __read(props[prop], 2), bindingIndex = _a[0], nonMinifiedName = _a[1];
              bindings[bindingIndex] = {
                  flags: 8 /* TypeProperty */,
                  name: prop,
                  nonMinifiedName: nonMinifiedName,
                  ns: null,
                  securityContext: null,
                  suffix: null
              };
          }
      }
      var outputDefs = [];
      if (outputs) {
          for (var propName in outputs) {
              outputDefs.push({ type: 1 /* DirectiveOutput */, propName: propName, target: null, eventName: outputs[propName] });
          }
      }
      flags |= 16384 /* TypeDirective */;
      return _def(checkIndex, flags, matchedQueries, childCount, ctor, ctor, deps, bindings, outputDefs);
  }
  function pipeDef(flags, ctor, deps) {
      flags |= 16 /* TypePipe */;
      return _def(-1, flags, null, 0, ctor, ctor, deps);
  }
  function providerDef(flags, matchedQueries, token, value, deps) {
      return _def(-1, flags, matchedQueries, 0, token, value, deps);
  }
  function _def(checkIndex, flags, matchedQueriesDsl, childCount, token, value, deps, bindings, outputs) {
      var _a = splitMatchedQueriesDsl(matchedQueriesDsl), matchedQueries = _a.matchedQueries, references = _a.references, matchedQueryIds = _a.matchedQueryIds;
      if (!outputs) {
          outputs = [];
      }
      if (!bindings) {
          bindings = [];
      }
      // Need to resolve forwardRefs as e.g. for `useValue` we
      // lowered the expression and then stopped evaluating it,
      // i.e. also didn't unwrap it.
      value = resolveForwardRef(value);
      var depDefs = splitDepsDsl(deps, stringify(token));
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          checkIndex: checkIndex,
          flags: flags,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          matchedQueries: matchedQueries,
          matchedQueryIds: matchedQueryIds,
          references: references,
          ngContentIndex: -1,
          childCount: childCount,
          bindings: bindings,
          bindingFlags: calcBindingFlags(bindings),
          outputs: outputs,
          element: null,
          provider: { token: token, value: value, deps: depDefs },
          text: null,
          query: null,
          ngContent: null
      };
  }
  function createProviderInstance(view, def) {
      return _createProviderInstance$1(view, def);
  }
  function createPipeInstance(view, def) {
      // deps are looked up from component.
      var compView = view;
      while (compView.parent && !isComponentView(compView)) {
          compView = compView.parent;
      }
      // pipes can see the private services of the component
      var allowPrivateServices = true;
      // pipes are always eager and classes!
      return createClass(compView.parent, viewParentEl(compView), allowPrivateServices, def.provider.value, def.provider.deps);
  }
  function createDirectiveInstance(view, def) {
      // components can see other private services, other directives can't.
      var allowPrivateServices = (def.flags & 32768 /* Component */) > 0;
      // directives are always eager and classes!
      var instance = createClass(view, def.parent, allowPrivateServices, def.provider.value, def.provider.deps);
      if (def.outputs.length) {
          for (var i = 0; i < def.outputs.length; i++) {
              var output = def.outputs[i];
              var outputObservable = instance[output.propName];
              if (isObservable(outputObservable)) {
                  var subscription = outputObservable.subscribe(eventHandlerClosure(view, def.parent.nodeIndex, output.eventName));
                  view.disposables[def.outputIndex + i] = subscription.unsubscribe.bind(subscription);
              }
              else {
                  throw new Error("@Output " + output.propName + " not initialized in '" + instance.constructor.name + "'.");
              }
          }
      }
      return instance;
  }
  function eventHandlerClosure(view, index, eventName) {
      return function (event) { return dispatchEvent(view, index, eventName, event); };
  }
  function checkAndUpdateDirectiveInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var providerData = asProviderData(view, def.nodeIndex);
      var directive = providerData.instance;
      var changed = false;
      var changes = undefined;
      var bindLen = def.bindings.length;
      if (bindLen > 0 && checkBinding(view, def, 0, v0)) {
          changed = true;
          changes = updateProp(view, providerData, def, 0, v0, changes);
      }
      if (bindLen > 1 && checkBinding(view, def, 1, v1)) {
          changed = true;
          changes = updateProp(view, providerData, def, 1, v1, changes);
      }
      if (bindLen > 2 && checkBinding(view, def, 2, v2)) {
          changed = true;
          changes = updateProp(view, providerData, def, 2, v2, changes);
      }
      if (bindLen > 3 && checkBinding(view, def, 3, v3)) {
          changed = true;
          changes = updateProp(view, providerData, def, 3, v3, changes);
      }
      if (bindLen > 4 && checkBinding(view, def, 4, v4)) {
          changed = true;
          changes = updateProp(view, providerData, def, 4, v4, changes);
      }
      if (bindLen > 5 && checkBinding(view, def, 5, v5)) {
          changed = true;
          changes = updateProp(view, providerData, def, 5, v5, changes);
      }
      if (bindLen > 6 && checkBinding(view, def, 6, v6)) {
          changed = true;
          changes = updateProp(view, providerData, def, 6, v6, changes);
      }
      if (bindLen > 7 && checkBinding(view, def, 7, v7)) {
          changed = true;
          changes = updateProp(view, providerData, def, 7, v7, changes);
      }
      if (bindLen > 8 && checkBinding(view, def, 8, v8)) {
          changed = true;
          changes = updateProp(view, providerData, def, 8, v8, changes);
      }
      if (bindLen > 9 && checkBinding(view, def, 9, v9)) {
          changed = true;
          changes = updateProp(view, providerData, def, 9, v9, changes);
      }
      if (changes) {
          directive.ngOnChanges(changes);
      }
      if ((def.flags & 65536 /* OnInit */) &&
          shouldCallLifecycleInitHook(view, 256 /* InitState_CallingOnInit */, def.nodeIndex)) {
          directive.ngOnInit();
      }
      if (def.flags & 262144 /* DoCheck */) {
          directive.ngDoCheck();
      }
      return changed;
  }
  function checkAndUpdateDirectiveDynamic(view, def, values) {
      var providerData = asProviderData(view, def.nodeIndex);
      var directive = providerData.instance;
      var changed = false;
      var changes = undefined;
      for (var i = 0; i < values.length; i++) {
          if (checkBinding(view, def, i, values[i])) {
              changed = true;
              changes = updateProp(view, providerData, def, i, values[i], changes);
          }
      }
      if (changes) {
          directive.ngOnChanges(changes);
      }
      if ((def.flags & 65536 /* OnInit */) &&
          shouldCallLifecycleInitHook(view, 256 /* InitState_CallingOnInit */, def.nodeIndex)) {
          directive.ngOnInit();
      }
      if (def.flags & 262144 /* DoCheck */) {
          directive.ngDoCheck();
      }
      return changed;
  }
  function _createProviderInstance$1(view, def) {
      // private services can see other private services
      var allowPrivateServices = (def.flags & 8192 /* PrivateProvider */) > 0;
      var providerDef = def.provider;
      switch (def.flags & 201347067 /* Types */) {
          case 512 /* TypeClassProvider */:
              return createClass(view, def.parent, allowPrivateServices, providerDef.value, providerDef.deps);
          case 1024 /* TypeFactoryProvider */:
              return callFactory(view, def.parent, allowPrivateServices, providerDef.value, providerDef.deps);
          case 2048 /* TypeUseExistingProvider */:
              return resolveDep(view, def.parent, allowPrivateServices, providerDef.deps[0]);
          case 256 /* TypeValueProvider */:
              return providerDef.value;
      }
  }
  function createClass(view, elDef, allowPrivateServices, ctor, deps) {
      var len = deps.length;
      switch (len) {
          case 0:
              return new ctor();
          case 1:
              return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]));
          case 2:
              return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]));
          case 3:
              return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2]));
          default:
              var depValues = [];
              for (var i = 0; i < len; i++) {
                  depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i]));
              }
              return new (ctor.bind.apply(ctor, __spread([void 0], depValues)))();
      }
  }
  function callFactory(view, elDef, allowPrivateServices, factory, deps) {
      var len = deps.length;
      switch (len) {
          case 0:
              return factory();
          case 1:
              return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]));
          case 2:
              return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]));
          case 3:
              return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2]));
          default:
              var depValues = [];
              for (var i = 0; i < len; i++) {
                  depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i]));
              }
              return factory.apply(void 0, __spread(depValues));
      }
  }
  // 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)
  var NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
  function resolveDep(view, elDef, allowPrivateServices, depDef, notFoundValue) {
      if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
      if (depDef.flags & 8 /* Value */) {
          return depDef.token;
      }
      var startView = view;
      if (depDef.flags & 2 /* Optional */) {
          notFoundValue = null;
      }
      var tokenKey = depDef.tokenKey;
      if (tokenKey === ChangeDetectorRefTokenKey) {
          // directives on the same element as a component should be able to control the change detector
          // of that component as well.
          allowPrivateServices = !!(elDef && elDef.element.componentView);
      }
      if (elDef && (depDef.flags & 1 /* SkipSelf */)) {
          allowPrivateServices = false;
          elDef = elDef.parent;
      }
      var searchView = view;
      while (searchView) {
          if (elDef) {
              switch (tokenKey) {
                  case Renderer2TokenKey: {
                      var compView = findCompView(searchView, elDef, allowPrivateServices);
                      return compView.renderer;
                  }
                  case ElementRefTokenKey:
                      return new ElementRef(asElementData(searchView, elDef.nodeIndex).renderElement);
                  case ViewContainerRefTokenKey:
                      return asElementData(searchView, elDef.nodeIndex).viewContainer;
                  case TemplateRefTokenKey: {
                      if (elDef.element.template) {
                          return asElementData(searchView, elDef.nodeIndex).template;
                      }
                      break;
                  }
                  case ChangeDetectorRefTokenKey: {
                      var cdView = findCompView(searchView, elDef, allowPrivateServices);
                      return createChangeDetectorRef(cdView);
                  }
                  case InjectorRefTokenKey$1:
                  case INJECTORRefTokenKey$1:
                      return createInjector$1(searchView, elDef);
                  default:
                      var providerDef_1 = (allowPrivateServices ? elDef.element.allProviders :
                          elDef.element.publicProviders)[tokenKey];
                      if (providerDef_1) {
                          var providerData = asProviderData(searchView, providerDef_1.nodeIndex);
                          if (!providerData) {
                              providerData = { instance: _createProviderInstance$1(searchView, providerDef_1) };
                              searchView.nodes[providerDef_1.nodeIndex] = providerData;
                          }
                          return providerData.instance;
                      }
              }
          }
          allowPrivateServices = isComponentView(searchView);
          elDef = viewParentEl(searchView);
          searchView = searchView.parent;
          if (depDef.flags & 4 /* Self */) {
              searchView = null;
          }
      }
      var value = startView.root.injector.get(depDef.token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);
      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 startView.root.ngModule.injector.get(depDef.token, notFoundValue);
  }
  function findCompView(view, elDef, allowPrivateServices) {
      var compView;
      if (allowPrivateServices) {
          compView = asElementData(view, elDef.nodeIndex).componentView;
      }
      else {
          compView = view;
          while (compView.parent && !isComponentView(compView)) {
              compView = compView.parent;
          }
      }
      return compView;
  }
  function updateProp(view, providerData, def, bindingIdx, value, changes) {
      if (def.flags & 32768 /* Component */) {
          var compView = asElementData(view, def.parent.nodeIndex).componentView;
          if (compView.def.flags & 2 /* OnPush */) {
              compView.state |= 8 /* ChecksEnabled */;
          }
      }
      var binding = def.bindings[bindingIdx];
      var propName = binding.name;
      // Note: This is still safe with Closure Compiler as
      // the user passed in the property name as an object has to `providerDef`,
      // so Closure Compiler will have renamed the property correctly already.
      providerData.instance[propName] = value;
      if (def.flags & 524288 /* OnChanges */) {
          changes = changes || {};
          var oldValue = WrappedValue.unwrap(view.oldValues[def.bindingIndex + bindingIdx]);
          var binding_1 = def.bindings[bindingIdx];
          changes[binding_1.nonMinifiedName] =
              new SimpleChange(oldValue, value, (view.state & 2 /* FirstCheck */) !== 0);
      }
      view.oldValues[def.bindingIndex + bindingIdx] = value;
      return changes;
  }
  // This function calls the ngAfterContentCheck, ngAfterContentInit,
  // ngAfterViewCheck, and ngAfterViewInit lifecycle hooks (depending on the node
  // flags in lifecycle). Unlike ngDoCheck, ngOnChanges and ngOnInit, which are
  // called during a pre-order traversal of the view tree (that is calling the
  // parent hooks before the child hooks) these events are sent in using a
  // post-order traversal of the tree (children before parents). This changes the
  // meaning of initIndex in the view state. For ngOnInit, initIndex tracks the
  // expected nodeIndex which a ngOnInit should be called. When sending
  // ngAfterContentInit and ngAfterViewInit it is the expected count of
  // ngAfterContentInit or ngAfterViewInit methods that have been called. This
  // ensure that despite being called recursively or after picking up after an
  // exception, the ngAfterContentInit or ngAfterViewInit will be called on the
  // correct nodes. Consider for example, the following (where E is an element
  // and D is a directive)
  //  Tree:       pre-order index  post-order index
  //    E1        0                6
  //      E2      1                1
  //       D3     2                0
  //      E4      3                5
  //       E5     4                4
  //        E6    5                2
  //        E7    6                3
  // As can be seen, the post-order index has an unclear relationship to the
  // pre-order index (postOrderIndex === preOrderIndex - parentCount +
  // childCount). Since number of calls to ngAfterContentInit and ngAfterViewInit
  // are stable (will be the same for the same view regardless of exceptions or
  // recursion) we just need to count them which will roughly correspond to the
  // post-order index (it skips elements and directives that do not have
  // lifecycle hooks).
  //
  // For example, if an exception is raised in the E6.onAfterViewInit() the
  // initIndex is left at 3 (by shouldCallLifecycleInitHook() which set it to
  // initIndex + 1). When checkAndUpdateView() is called again D3, E2 and E6 will
  // not have their ngAfterViewInit() called but, starting with E7, the rest of
  // the view will begin getting ngAfterViewInit() called until a check and
  // pass is complete.
  //
  // This algorthim also handles recursion. Consider if E4's ngAfterViewInit()
  // indirectly calls E1's ChangeDetectorRef.detectChanges(). The expected
  // initIndex is set to 6, the recusive checkAndUpdateView() starts walk again.
  // D3, E2, E6, E7, E5 and E4 are skipped, ngAfterViewInit() is called on E1.
  // When the recursion returns the initIndex will be 7 so E1 is skipped as it
  // has already been called in the recursively called checkAnUpdateView().
  function callLifecycleHooksChildrenFirst(view, lifecycles) {
      if (!(view.def.nodeFlags & lifecycles)) {
          return;
      }
      var nodes = view.def.nodes;
      var initIndex = 0;
      for (var i = 0; i < nodes.length; i++) {
          var nodeDef = nodes[i];
          var parent_1 = nodeDef.parent;
          if (!parent_1 && nodeDef.flags & lifecycles) {
              // matching root node (e.g. a pipe)
              callProviderLifecycles(view, i, nodeDef.flags & lifecycles, initIndex++);
          }
          if ((nodeDef.childFlags & lifecycles) === 0) {
              // no child matches one of the lifecycles
              i += nodeDef.childCount;
          }
          while (parent_1 && (parent_1.flags & 1 /* TypeElement */) &&
              i === parent_1.nodeIndex + parent_1.childCount) {
              // last child of an element
              if (parent_1.directChildFlags & lifecycles) {
                  initIndex = callElementProvidersLifecycles(view, parent_1, lifecycles, initIndex);
              }
              parent_1 = parent_1.parent;
          }
      }
  }
  function callElementProvidersLifecycles(view, elDef, lifecycles, initIndex) {
      for (var i = elDef.nodeIndex + 1; i <= elDef.nodeIndex + elDef.childCount; i++) {
          var nodeDef = view.def.nodes[i];
          if (nodeDef.flags & lifecycles) {
              callProviderLifecycles(view, i, nodeDef.flags & lifecycles, initIndex++);
          }
          // only visit direct children
          i += nodeDef.childCount;
      }
      return initIndex;
  }
  function callProviderLifecycles(view, index, lifecycles, initIndex) {
      var providerData = asProviderData(view, index);
      if (!providerData) {
          return;
      }
      var provider = providerData.instance;
      if (!provider) {
          return;
      }
      Services.setCurrentNode(view, index);
      if (lifecycles & 1048576 /* AfterContentInit */ &&
          shouldCallLifecycleInitHook(view, 512 /* InitState_CallingAfterContentInit */, initIndex)) {
          provider.ngAfterContentInit();
      }
      if (lifecycles & 2097152 /* AfterContentChecked */) {
          provider.ngAfterContentChecked();
      }
      if (lifecycles & 4194304 /* AfterViewInit */ &&
          shouldCallLifecycleInitHook(view, 768 /* InitState_CallingAfterViewInit */, initIndex)) {
          provider.ngAfterViewInit();
      }
      if (lifecycles & 8388608 /* AfterViewChecked */) {
          provider.ngAfterViewChecked();
      }
      if (lifecycles & 131072 /* OnDestroy */) {
          provider.ngOnDestroy();
      }
  }

  /**
   * @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
   */
  var ComponentFactoryResolver$1 = /** @class */ (function (_super) {
      __extends(ComponentFactoryResolver, _super);
      /**
       * @param ngModule The NgModuleRef to which all resolved factories are bound.
       */
      function ComponentFactoryResolver(ngModule) {
          var _this = _super.call(this) || this;
          _this.ngModule = ngModule;
          return _this;
      }
      ComponentFactoryResolver.prototype.resolveComponentFactory = function (component) {
          ngDevMode && assertComponentType(component);
          var componentDef = getComponentDef(component);
          return new ComponentFactory$1(componentDef, this.ngModule);
      };
      return ComponentFactoryResolver;
  }(ComponentFactoryResolver));
  function toRefArray(map) {
      var array = [];
      for (var nonMinified in map) {
          if (map.hasOwnProperty(nonMinified)) {
              var minified = map[nonMinified];
              array.push({ propName: minified, templateName: nonMinified });
          }
      }
      return array;
  }
  function getNamespace$1(elementName) {
      var name = elementName.toLowerCase();
      return name === 'svg' ? SVG_NAMESPACE : (name === 'math' ? MATH_ML_NAMESPACE : null);
  }
  /**
   * A change detection scheduler token for {@link RootContext}. This token is the default value used
   * for the default `RootContext` found in the {@link ROOT_CONTEXT} token.
   */
  var SCHEDULER = new InjectionToken('SCHEDULER_TOKEN', {
      providedIn: 'root',
      factory: function () { return defaultScheduler; },
  });
  function createChainedInjector(rootViewInjector, moduleInjector) {
      return {
          get: function (token, notFoundValue, flags) {
              var value = rootViewInjector.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 moduleInjector.get(token, notFoundValue, flags);
          }
      };
  }
  /**
   * Render3 implementation of {@link viewEngine_ComponentFactory}.
   */
  var ComponentFactory$1 = /** @class */ (function (_super) {
      __extends(ComponentFactory, _super);
      /**
       * @param componentDef The component definition.
       * @param ngModule The NgModuleRef to which the factory is bound.
       */
      function ComponentFactory(componentDef, ngModule) {
          var _this = _super.call(this) || this;
          _this.componentDef = componentDef;
          _this.ngModule = ngModule;
          _this.componentType = componentDef.type;
          _this.selector = stringifyCSSSelectorList(componentDef.selectors);
          _this.ngContentSelectors =
              componentDef.ngContentSelectors ? componentDef.ngContentSelectors : [];
          _this.isBoundToModule = !!ngModule;
          return _this;
      }
      Object.defineProperty(ComponentFactory.prototype, "inputs", {
          get: function () {
              return toRefArray(this.componentDef.inputs);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(ComponentFactory.prototype, "outputs", {
          get: function () {
              return toRefArray(this.componentDef.outputs);
          },
          enumerable: true,
          configurable: true
      });
      ComponentFactory.prototype.create = function (injector, projectableNodes, rootSelectorOrNode, ngModule) {
          ngModule = ngModule || this.ngModule;
          var rootViewInjector = ngModule ? createChainedInjector(injector, ngModule.injector) : injector;
          var rendererFactory = rootViewInjector.get(RendererFactory2, domRendererFactory3);
          var sanitizer = rootViewInjector.get(Sanitizer, null);
          var 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.
          var elementName = this.componentDef.selectors[0][0] || 'div';
          var hostRNode = rootSelectorOrNode ?
              locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :
              elementCreate(elementName, rendererFactory.createRenderer(null, this.componentDef), getNamespace$1(elementName));
          var rootFlags = this.componentDef.onPush ? 64 /* Dirty */ | 512 /* IsRoot */ :
              16 /* CheckAlways */ | 512 /* IsRoot */;
          // Check whether this Component needs to be isolated from other components, i.e. whether it
          // should be placed into its own (empty) root context or existing root context should be used.
          // Note: this is internal-only convention and might change in the future, so it should not be
          // relied upon externally.
          var isIsolated = typeof rootSelectorOrNode === 'string' &&
              /^#root-ng-internal-isolated-\d+/.test(rootSelectorOrNode);
          var rootContext = createRootContext();
          // Create the root view. Uses empty TView and ContentTemplate.
          var rootTView = createTView(0 /* Root */, -1, null, 1, 0, null, null, null, null, null);
          var rootLView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector);
          // 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, null);
          var component;
          var tElementNode;
          try {
              var 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.
                      var _a = extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]), attrs = _a.attrs, classes = _a.classes;
                      if (attrs) {
                          setUpAttributes(hostRenderer, hostRNode, attrs);
                      }
                      if (classes && classes.length > 0) {
                          writeDirectClass(hostRenderer, hostRNode, classes.join(' '));
                      }
                  }
              }
              tElementNode = getTNode(rootTView, 0);
              if (projectableNodes !== undefined) {
                  var projection = tElementNode.projection = [];
                  for (var i = 0; i < this.ngContentSelectors.length; i++) {
                      var 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, rootContext, [LifecycleHooksFeature]);
              renderView(rootTView, rootLView, null);
          }
          finally {
              leaveView();
          }
          var componentRef = new ComponentRef$1(this.componentType, component, createElementRef(ElementRef, tElementNode, rootLView), rootLView, tElementNode);
          if (!rootSelectorOrNode || isIsolated) {
              // The host element of the internal or isolated root view is attached to the component's host
              // view node.
              componentRef.hostView._tViewNode.child = tElementNode;
          }
          return componentRef;
      };
      return ComponentFactory;
  }(ComponentFactory));
  var componentFactoryResolver = new ComponentFactoryResolver$1();
  /**
   * 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.
   *
   */
  var ComponentRef$1 = /** @class */ (function (_super) {
      __extends(ComponentRef, _super);
      function ComponentRef(componentType, instance, location, _rootLView, _tNode) {
          var _this = _super.call(this) || this;
          _this.location = location;
          _this._rootLView = _rootLView;
          _this._tNode = _tNode;
          _this.destroyCbs = [];
          _this.instance = instance;
          _this.hostView = _this.changeDetectorRef = new RootViewRef(_rootLView);
          _this.hostView._tViewNode = assignTViewNodeToLView(_rootLView[TVIEW], null, -1, _rootLView);
          _this.componentType = componentType;
          return _this;
      }
      Object.defineProperty(ComponentRef.prototype, "injector", {
          get: function () {
              return new NodeInjector(this._tNode, this._rootLView);
          },
          enumerable: true,
          configurable: true
      });
      ComponentRef.prototype.destroy = function () {
          if (this.destroyCbs) {
              this.destroyCbs.forEach(function (fn) { return fn(); });
              this.destroyCbs = null;
              !this.hostView.destroyed && this.hostView.destroy();
          }
      };
      ComponentRef.prototype.onDestroy = function (callback) {
          if (this.destroyCbs) {
              this.destroyCbs.push(callback);
          }
      };
      return ComponentRef;
  }(ComponentRef));

  /**
   * @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
   */
  /**
   * 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 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
   */
  // THIS CODE IS GENERATED - DO NOT MODIFY
  // See angular/tools/gulp-tasks/cldr/extract.js
  var u = undefined;
  function plural(n) {
      var i = Math.floor(Math.abs(n)), v = n.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 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
   */
  /**
   * This const is used to store the locale data registered with `registerLocaleData`
   */
  var LOCALE_DATA = {};
  /**
   * Register locale data to be used internally by Angular. See the
   * ["I18n guide"](guide/i18n#i18n-pipes) to know how to import additional locale data.
   *
   * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1
   */
  function registerLocaleData(data, localeId, extraData) {
      if (typeof localeId !== 'string') {
          extraData = localeId;
          localeId = data[exports.ɵLocaleDataIndex.LocaleId];
      }
      localeId = localeId.toLowerCase().replace(/_/g, '-');
      LOCALE_DATA[localeId] = data;
      if (extraData) {
          LOCALE_DATA[localeId][exports.ɵ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)
   */
  function findLocaleData(locale) {
      var normalizedLocale = normalizeLocale(locale);
      var match = getLocaleData(normalizedLocale);
      if (match) {
          return match;
      }
      // let's try to find a parent locale
      var parentLocale = normalizedLocale.split('-')[0];
      match = getLocaleData(parentLocale);
      if (match) {
          return match;
      }
      if (parentLocale === 'en') {
          return localeEn;
      }
      throw new Error("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) {
      var data = findLocaleData(locale);
      return data[exports.ɵ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)
   */
  function getLocalePluralCase(locale) {
      var data = findLocaleData(locale);
      return data[exports.ɵ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 = {};
  }
  (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";
  })(exports.ɵLocaleDataIndex || (exports.ɵLocaleDataIndex = {}));
  /**
   * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.
   */
  function normalizeLocale(locale) {
      return locale.toLowerCase().replace(/_/g, '-');
  }

  /**
   * @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
   */
  var pluralMapping = ['zero', 'one', 'two', 'few', 'many'];
  /**
   * Returns the plural case based on the locale
   */
  function getPluralCase(value, locale) {
      var plural = getLocalePluralCase(locale)(parseInt(value, 10));
      var result = pluralMapping[plural];
      return (result !== undefined) ? result : 'other';
  }
  /**
   * The locale id that the application is using by default (for translations and ICU expressions).
   */
  var DEFAULT_LOCALE_ID = 'en-US';
  /**
   * USD currency code that the application uses by default for CurrencyPipe when no
   * DEFAULT_CURRENCY_CODE is provided.
   */
  var USD_CURRENCY_CODE = 'USD';

  var MARKER = "\uFFFD";
  var ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/;
  var SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi;
  var PH_REGEXP = /�(\/?[#*!]\d+):?\d*�/gi;
  var BINDING_REGEXP = /�(\d+):?\d*�/gi;
  var ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi;
  // i18nPostprocess consts
  var ROOT_TEMPLATE_ID = 0;
  var PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]/;
  var PP_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]|(�\/?\*\d+:\d+�)/g;
  var PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g;
  var PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g;
  var PP_ICUS_REGEXP = /�I18N_EXP_(ICU(_\d+)?)�/g;
  var PP_CLOSE_TEMPLATE_REGEXP = /\/\*/;
  var PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
  /**
   * 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.
   *
   */
  function extractParts(pattern) {
      if (!pattern) {
          return [];
      }
      var prevPos = 0;
      var braceStack = [];
      var results = [];
      var braces = /[{}]/g;
      // lastIndex doesn't get set to 0 so we have to.
      braces.lastIndex = 0;
      var match;
      while (match = braces.exec(pattern)) {
          var pos = match.index;
          if (match[0] == '}') {
              braceStack.pop();
              if (braceStack.length == 0) {
                  // End of the block.
                  var 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) {
                  var substring_1 = pattern.substring(prevPos, pos);
                  results.push(substring_1);
                  prevPos = pos + 1;
              }
              braceStack.push('{');
          }
      }
      var substring = pattern.substring(prevPos);
      results.push(substring);
      return results;
  }
  /**
   * 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) {
      var cases = [];
      var values = [];
      var icuType = 1 /* plural */;
      var mainBinding = 0;
      pattern = pattern.replace(ICU_BLOCK_REGEXP, function (str, binding, type) {
          if (type === 'select') {
              icuType = 0 /* select */;
          }
          else {
              icuType = 1 /* plural */;
          }
          mainBinding = parseInt(binding.substr(1), 10);
          return '';
      });
      var parts = extractParts(pattern);
      // Looking for (key block)+ sequence. One of the keys has to be "other".
      for (var pos = 0; pos < parts.length;) {
          var key = parts[pos++].trim();
          if (icuType === 1 /* plural */) {
              // Key can be "=x", we just want "x"
              key = key.replace(/\s*(?:=)?(\w+)\s*/, '$1');
          }
          if (key.length) {
              cases.push(key);
          }
          var blocks = extractParts(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: cases, values: values };
  }
  /**
   * Removes everything inside the sub-templates of a message.
   */
  function removeInnerTemplateTranslation(message) {
      var match;
      var res = '';
      var index = 0;
      var inTemplate = false;
      var 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.substr(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
          var start = message.indexOf(":" + subTemplateIndex + MARKER) + 2 + subTemplateIndex.toString().length;
          var end = message.search(new RegExp(MARKER + "\\/\\*\\d+:" + subTemplateIndex + MARKER));
          return removeInnerTemplateTranslation(message.substring(start, end));
      }
  }
  /**
   * Generate the OpCodes to update the bindings of a string.
   *
   * @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.
   */
  function generateBindingUpdateOpCodes(str, destinationNode, attrName, sanitizeFn) {
      if (sanitizeFn === void 0) { sanitizeFn = null; }
      var updateOpCodes = [null, null]; // Alloc space for mask and size
      var textParts = str.split(BINDING_REGEXP);
      var mask = 0;
      for (var j = 0; j < textParts.length; j++) {
          var textValue = textParts[j];
          if (j & 1) {
              // Odd indexes are bindings
              var bindingIndex = 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 /* SHIFT_REF */ |
          (attrName ? 1 /* Attr */ : 0 /* Text */));
      if (attrName) {
          updateOpCodes.push(attrName, sanitizeFn);
      }
      updateOpCodes[0] = mask;
      updateOpCodes[1] = updateOpCodes.length - 2;
      return updateOpCodes;
  }
  function getBindingMask(icuExpression, mask) {
      if (mask === void 0) { mask = 0; }
      mask = mask | toMaskBit(icuExpression.mainBinding);
      var match;
      for (var i = 0; i < icuExpression.values.length; i++) {
          var valueArr = icuExpression.values[i];
          for (var j = 0; j < valueArr.length; j++) {
              var value = valueArr[j];
              if (typeof value === 'string') {
                  while (match = BINDING_REGEXP.exec(value)) {
                      mask = mask | toMaskBit(parseInt(match[1], 10));
                  }
              }
              else {
                  mask = getBindingMask(value, mask);
              }
          }
      }
      return mask;
  }
  var i18nIndexStack = [];
  var i18nIndexStackPointer = -1;
  /**
   * 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);
  }
  var parentIndexStack = [];
  /**
   * 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})�`: *Projection Placeholder*:  Marks the
   *   beginning and end of <ng-content> that was 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 message The translation message.
   * @param subTemplateIndex Optional sub-template index in the `message`.
   *
   * @codeGenApi
   */
  function ɵɵi18nStart(index, message, subTemplateIndex) {
      var tView = getTView();
      ngDevMode && assertDefined(tView, "tView should be defined");
      i18nIndexStack[++i18nIndexStackPointer] = index;
      // We need to delay projections until `i18nEnd`
      setDelayProjection(true);
      if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
          i18nStartFirstPass(getLView(), tView, index, message, subTemplateIndex);
      }
  }
  // Count for the number of vars that will be allocated for each i18n block.
  // It is global because this is used in multiple functions that include loops and recursive calls.
  // This is reset to 0 when `i18nStartFirstPass` is called.
  var i18nVarsCount;
  function allocNodeIndex(startIndex) {
      return startIndex + i18nVarsCount++;
  }
  /**
   * See `i18nStart` above.
   */
  function i18nStartFirstPass(lView, tView, index, message, subTemplateIndex) {
      var startIndex = tView.blueprint.length - HEADER_OFFSET;
      i18nVarsCount = 0;
      var previousOrParentTNode = getPreviousOrParentTNode();
      var parentTNode = getIsParent() ? previousOrParentTNode : previousOrParentTNode && previousOrParentTNode.parent;
      var parentIndex = parentTNode && parentTNode !== lView[T_HOST] ? parentTNode.index - HEADER_OFFSET : index;
      var parentIndexPointer = 0;
      parentIndexStack[parentIndexPointer] = parentIndex;
      var createOpCodes = [];
      // If the previous node wasn't the direct parent then we have a translation without top level
      // element and we need to keep a reference of the previous element if there is one. We should also
      // keep track whether an element was a parent node or not, so that the logic that consumes
      // the generated `I18nMutateOpCode`s can leverage this information to properly set TNode state
      // (whether it's a parent or sibling).
      if (index > 0 && previousOrParentTNode !== parentTNode) {
          var previousTNodeIndex = previousOrParentTNode.index - HEADER_OFFSET;
          // If current TNode is a sibling node, encode it using a negative index. This information is
          // required when the `Select` action is processed (see the `readCreateOpCodes` function).
          if (!getIsParent()) {
              previousTNodeIndex = ~previousTNodeIndex;
          }
          // Create an OpCode to select the previous TNode
          createOpCodes.push(previousTNodeIndex << 3 /* SHIFT_REF */ | 0 /* Select */);
      }
      var updateOpCodes = [];
      var icuExpressions = [];
      if (message === '' && isRootTemplateMessage(subTemplateIndex)) {
          // If top level translation is an empty string, do not invoke additional processing
          // and just create op codes for empty text node instead.
          createOpCodes.push(message, allocNodeIndex(startIndex), parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
      }
      else {
          var templateTranslation = getTranslationForTemplate(message, subTemplateIndex);
          var msgParts = replaceNgsp(templateTranslation).split(PH_REGEXP);
          for (var i = 0; i < msgParts.length; i++) {
              var value = msgParts[i];
              if (i & 1) {
                  // Odd indexes are placeholders (elements and sub-templates)
                  if (value.charAt(0) === '/') {
                      // It is a closing tag
                      if (value.charAt(1) === "#" /* ELEMENT */) {
                          var phIndex = parseInt(value.substr(2), 10);
                          parentIndex = parentIndexStack[--parentIndexPointer];
                          createOpCodes.push(phIndex << 3 /* SHIFT_REF */ | 5 /* ElementEnd */);
                      }
                  }
                  else {
                      var phIndex = parseInt(value.substr(1), 10);
                      var isElement = value.charAt(0) === "#" /* ELEMENT */;
                      // The value represents a placeholder that we move to the designated index.
                      // Note: positive indicies indicate that a TNode with a given index should also be marked
                      // as parent while executing `Select` instruction.
                      createOpCodes.push((isElement ? phIndex : ~phIndex) << 3 /* SHIFT_REF */ |
                          0 /* Select */, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
                      if (isElement) {
                          parentIndexStack[++parentIndexPointer] = parentIndex = phIndex;
                      }
                  }
              }
              else {
                  // Even indexes are text (including bindings & ICU expressions)
                  var parts = extractParts(value);
                  for (var j = 0; j < parts.length; j++) {
                      if (j & 1) {
                          // Odd indexes are ICU expressions
                          var icuExpression = parts[j];
                          // 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).
                          if (typeof icuExpression !== 'object') {
                              throw new Error("Unable to parse ICU expression in \"" + templateTranslation + "\" message.");
                          }
                          // Create the comment node that will anchor the ICU expression
                          var icuNodeIndex = allocNodeIndex(startIndex);
                          createOpCodes.push(COMMENT_MARKER, ngDevMode ? "ICU " + icuNodeIndex : '', icuNodeIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
                          // Update codes for the ICU expression
                          var mask = getBindingMask(icuExpression);
                          icuStart(icuExpressions, icuExpression, icuNodeIndex, icuNodeIndex);
                          // Since this is recursive, the last TIcu that was pushed is the one we want
                          var tIcuIndex = icuExpressions.length - 1;
                          updateOpCodes.push(toMaskBit(icuExpression.mainBinding), // mask of the main binding
                          3, // skip 3 opCodes if not changed
                          -1 - icuExpression.mainBinding, icuNodeIndex << 2 /* SHIFT_REF */ | 2 /* IcuSwitch */, tIcuIndex, mask, // mask of all the bindings of this ICU expression
                          2, // skip 2 opCodes if not changed
                          icuNodeIndex << 2 /* SHIFT_REF */ | 3 /* IcuUpdate */, tIcuIndex);
                      }
                      else if (parts[j] !== '') {
                          var text = parts[j];
                          // Even indexes are text (including bindings)
                          var hasBinding = text.match(BINDING_REGEXP);
                          // Create text nodes
                          var textNodeIndex = allocNodeIndex(startIndex);
                          createOpCodes.push(
                          // If there is a binding, the value will be set during update
                          hasBinding ? '' : text, textNodeIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
                          if (hasBinding) {
                              addAllToArray(generateBindingUpdateOpCodes(text, textNodeIndex), updateOpCodes);
                          }
                      }
                  }
              }
          }
      }
      if (i18nVarsCount > 0) {
          allocExpando(tView, lView, i18nVarsCount);
      }
      ngDevMode &&
          attachI18nOpCodesDebug(createOpCodes, updateOpCodes, icuExpressions.length ? icuExpressions : null, lView);
      // NOTE: local var needed to properly assert the type of `TI18n`.
      var tI18n = {
          vars: i18nVarsCount,
          create: createOpCodes,
          update: updateOpCodes,
          icus: icuExpressions.length ? icuExpressions : null,
      };
      tView.data[index + HEADER_OFFSET] = tI18n;
  }
  function appendI18nNode(tView, tNode, parentTNode, previousTNode, lView) {
      ngDevMode && ngDevMode.rendererMoveNode++;
      var nextNode = tNode.next;
      if (!previousTNode) {
          previousTNode = parentTNode;
      }
      // Re-organize node tree to put this node in the correct position.
      if (previousTNode === parentTNode && tNode !== parentTNode.child) {
          tNode.next = parentTNode.child;
          parentTNode.child = tNode;
      }
      else if (previousTNode !== parentTNode && tNode !== previousTNode.next) {
          tNode.next = previousTNode.next;
          previousTNode.next = tNode;
      }
      else {
          tNode.next = null;
      }
      if (parentTNode !== lView[T_HOST]) {
          tNode.parent = parentTNode;
      }
      // If tNode was moved around, we might need to fix a broken link.
      var cursor = tNode.next;
      while (cursor) {
          if (cursor.next === tNode) {
              cursor.next = nextNode;
          }
          cursor = cursor.next;
      }
      // If the placeholder to append is a projection, we need to move the projected nodes instead
      if (tNode.type === 1 /* Projection */) {
          applyProjection(tView, lView, tNode);
          return tNode;
      }
      appendChild(tView, lView, getNativeByTNode(tNode, lView), tNode);
      var slotValue = lView[tNode.index];
      if (tNode.type !== 0 /* Container */ && isLContainer(slotValue)) {
          // Nodes that inject ViewContainerRef also have a comment node that should be moved
          appendChild(tView, lView, slotValue[NATIVE], tNode);
      }
      return tNode;
  }
  function isRootTemplateMessage(subTemplateIndex) {
      return subTemplateIndex === undefined;
  }
  /**
   * 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) {
      if (replacements === void 0) { 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.
       */
      var result = message;
      if (PP_MULTI_VALUE_PLACEHOLDERS_REGEXP.test(message)) {
          var matches_1 = {};
          var templateIdsStack_1 = [ROOT_TEMPLATE_ID];
          result = result.replace(PP_PLACEHOLDERS_REGEXP, function (m, phs, tmpl) {
              var content = phs || tmpl;
              var placeholders = matches_1[content] || [];
              if (!placeholders.length) {
                  content.split('|').forEach(function (placeholder) {
                      var match = placeholder.match(PP_TEMPLATE_ID_REGEXP);
                      var templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID;
                      var isCloseTemplateTag = PP_CLOSE_TEMPLATE_REGEXP.test(placeholder);
                      placeholders.push([templateId, isCloseTemplateTag, placeholder]);
                  });
                  matches_1[content] = placeholders;
              }
              if (!placeholders.length) {
                  throw new Error("i18n postprocess: unmatched placeholder - " + content);
              }
              var currentTemplateId = templateIdsStack_1[templateIdsStack_1.length - 1];
              var idx = 0;
              // find placeholder index that matches current template id
              for (var i = 0; i < placeholders.length; i++) {
                  if (placeholders[i][0] === currentTemplateId) {
                      idx = i;
                      break;
                  }
              }
              // update template id stack based on the current tag extracted
              var _a = __read(placeholders[idx], 3), templateId = _a[0], isCloseTemplateTag = _a[1], placeholder = _a[2];
              if (isCloseTemplateTag) {
                  templateIdsStack_1.pop();
              }
              else if (currentTemplateId !== templateId) {
                  templateIdsStack_1.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, function (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, function (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, function (match, key) {
          if (replacements.hasOwnProperty(key)) {
              var list = replacements[key];
              if (!list.length) {
                  throw new Error("i18n postprocess: unmatched ICU - " + match + " with key: " + key);
              }
              return list.shift();
          }
          return match;
      });
      return result;
  }
  /**
   * 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() {
      var lView = getLView();
      var tView = getTView();
      ngDevMode && assertDefined(tView, "tView should be defined");
      i18nEndFirstPass(tView, lView);
      // Stop delaying projections
      setDelayProjection(false);
  }
  /**
   * See `i18nEnd` above.
   */
  function i18nEndFirstPass(tView, lView) {
      ngDevMode &&
          assertEqual(getBindingIndex(), tView.bindingStartIndex, 'i18nEnd should be called before any binding');
      var rootIndex = i18nIndexStack[i18nIndexStackPointer--];
      var tI18n = tView.data[rootIndex + HEADER_OFFSET];
      ngDevMode && assertDefined(tI18n, "You should call i18nStart before i18nEnd");
      // Find the last node that was added before `i18nEnd`
      var lastCreatedNode = getPreviousOrParentTNode();
      // Read the instructions to insert/move/remove DOM elements
      var visitedNodes = readCreateOpCodes(rootIndex, tI18n.create, tView, lView);
      // Remove deleted nodes
      var index = rootIndex + 1;
      while (index <= lastCreatedNode.index - HEADER_OFFSET) {
          if (visitedNodes.indexOf(index) === -1) {
              removeNode(tView, lView, index, /* markAsDetached */ true);
          }
          // Check if an element has any local refs and skip them
          var tNode = getTNode(tView, index);
          if (tNode &&
              (tNode.type === 0 /* Container */ || tNode.type === 3 /* Element */ ||
                  tNode.type === 4 /* ElementContainer */) &&
              tNode.localNames !== null) {
              // Divide by 2 to get the number of local refs,
              // since they are stored as an array that also includes directive indexes,
              // i.e. ["localRef", directiveIndex, ...]
              index += tNode.localNames.length >> 1;
          }
          index++;
      }
  }
  /**
   * Creates and stores the dynamic TNode, and unhooks it from the tree for now.
   */
  function createDynamicNodeAtIndex(tView, lView, index, type, native, name) {
      var previousOrParentTNode = getPreviousOrParentTNode();
      ngDevMode && assertDataInRange(lView, index + HEADER_OFFSET);
      lView[index + HEADER_OFFSET] = native;
      var tNode = getOrCreateTNode(tView, lView[T_HOST], index, type, name, null);
      // We are creating a dynamic node, the previous tNode might not be pointing at this node.
      // We will link ourselves into the tree later with `appendI18nNode`.
      if (previousOrParentTNode && previousOrParentTNode.next === tNode) {
          previousOrParentTNode.next = null;
      }
      return tNode;
  }
  function readCreateOpCodes(index, createOpCodes, tView, lView) {
      var renderer = lView[RENDERER];
      var currentTNode = null;
      var previousTNode = null;
      var visitedNodes = [];
      for (var i = 0; i < createOpCodes.length; i++) {
          var opCode = createOpCodes[i];
          if (typeof opCode == 'string') {
              var textRNode = createTextNode(opCode, renderer);
              var textNodeIndex = createOpCodes[++i];
              ngDevMode && ngDevMode.rendererCreateTextNode++;
              previousTNode = currentTNode;
              currentTNode =
                  createDynamicNodeAtIndex(tView, lView, textNodeIndex, 3 /* Element */, textRNode, null);
              visitedNodes.push(textNodeIndex);
              setIsNotParent();
          }
          else if (typeof opCode == 'number') {
              switch (opCode & 7 /* MASK_OPCODE */) {
                  case 1 /* AppendChild */:
                      var destinationNodeIndex = opCode >>> 17 /* SHIFT_PARENT */;
                      var destinationTNode = void 0;
                      if (destinationNodeIndex === index) {
                          // If the destination node is `i18nStart`, we don't have a
                          // top-level node and we should use the host node instead
                          destinationTNode = lView[T_HOST];
                      }
                      else {
                          destinationTNode = getTNode(tView, destinationNodeIndex);
                      }
                      ngDevMode &&
                          assertDefined(currentTNode, "You need to create or select a node before you can insert it into the DOM");
                      previousTNode =
                          appendI18nNode(tView, currentTNode, destinationTNode, previousTNode, lView);
                      break;
                  case 0 /* Select */:
                      // Negative indicies indicate that a given TNode is a sibling node, not a parent node
                      // (see `i18nStartFirstPass` for additional information).
                      var isParent = opCode >= 0;
                      var nodeIndex = (isParent ? opCode : ~opCode) >>> 3 /* SHIFT_REF */;
                      visitedNodes.push(nodeIndex);
                      previousTNode = currentTNode;
                      currentTNode = getTNode(tView, nodeIndex);
                      if (currentTNode) {
                          setPreviousOrParentTNode(currentTNode, isParent);
                      }
                      break;
                  case 5 /* ElementEnd */:
                      var elementIndex = opCode >>> 3 /* SHIFT_REF */;
                      previousTNode = currentTNode = getTNode(tView, elementIndex);
                      setPreviousOrParentTNode(currentTNode, false);
                      break;
                  case 4 /* Attr */:
                      var elementNodeIndex = opCode >>> 3 /* SHIFT_REF */;
                      var attrName = createOpCodes[++i];
                      var attrValue = createOpCodes[++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
                      elementAttributeInternal(getTNode(tView, elementNodeIndex), lView, attrName, attrValue, null, null);
                      break;
                  default:
                      throw new Error("Unable to determine the type of mutate operation for \"" + opCode + "\"");
              }
          }
          else {
              switch (opCode) {
                  case COMMENT_MARKER:
                      var commentValue = createOpCodes[++i];
                      var commentNodeIndex = createOpCodes[++i];
                      ngDevMode &&
                          assertEqual(typeof commentValue, 'string', "Expected \"" + commentValue + "\" to be a comment node value");
                      var commentRNode = renderer.createComment(commentValue);
                      ngDevMode && ngDevMode.rendererCreateComment++;
                      previousTNode = currentTNode;
                      currentTNode = createDynamicNodeAtIndex(tView, lView, commentNodeIndex, 5 /* IcuContainer */, commentRNode, null);
                      visitedNodes.push(commentNodeIndex);
                      attachPatchData(commentRNode, lView);
                      currentTNode.activeCaseIndex = null;
                      // We will add the case nodes later, during the update phase
                      setIsNotParent();
                      break;
                  case ELEMENT_MARKER:
                      var tagNameValue = createOpCodes[++i];
                      var elementNodeIndex = createOpCodes[++i];
                      ngDevMode &&
                          assertEqual(typeof tagNameValue, 'string', "Expected \"" + tagNameValue + "\" to be an element node tag name");
                      var elementRNode = renderer.createElement(tagNameValue);
                      ngDevMode && ngDevMode.rendererCreateElement++;
                      previousTNode = currentTNode;
                      currentTNode = createDynamicNodeAtIndex(tView, lView, elementNodeIndex, 3 /* Element */, elementRNode, tagNameValue);
                      visitedNodes.push(elementNodeIndex);
                      break;
                  default:
                      throw new Error("Unable to determine the type of mutate operation for \"" + opCode + "\"");
              }
          }
      }
      setIsNotParent();
      return visitedNodes;
  }
  function readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, tView, lView, bypassCheckBit) {
      if (bypassCheckBit === void 0) { bypassCheckBit = false; }
      var caseCreated = false;
      for (var i = 0; i < updateOpCodes.length; i++) {
          // bit code to check if we should apply the next update
          var checkBit = updateOpCodes[i];
          // Number of opCodes to skip until next set of update codes
          var skipCodes = updateOpCodes[++i];
          if (bypassCheckBit || (checkBit & changeMask)) {
              // The value has been updated since last checked
              var value = '';
              for (var j = i + 1; j <= (i + skipCodes); j++) {
                  var opCode = updateOpCodes[j];
                  if (typeof opCode == 'string') {
                      value += opCode;
                  }
                  else if (typeof opCode == 'number') {
                      if (opCode < 0) {
                          // It's a binding index whose value is negative
                          value += renderStringify(lView[bindingsStartIndex - opCode]);
                      }
                      else {
                          var nodeIndex = opCode >>> 2 /* SHIFT_REF */;
                          var tIcuIndex = void 0;
                          var tIcu = void 0;
                          var icuTNode = void 0;
                          switch (opCode & 3 /* MASK_OPCODE */) {
                              case 1 /* Attr */:
                                  var propName = updateOpCodes[++j];
                                  var sanitizeFn = updateOpCodes[++j];
                                  elementPropertyInternal(tView, getTNode(tView, nodeIndex), lView, propName, value, lView[RENDERER], sanitizeFn, false);
                                  break;
                              case 0 /* Text */:
                                  textBindingInternal(lView, nodeIndex, value);
                                  break;
                              case 2 /* IcuSwitch */:
                                  tIcuIndex = updateOpCodes[++j];
                                  tIcu = icus[tIcuIndex];
                                  icuTNode = getTNode(tView, nodeIndex);
                                  // If there is an active case, delete the old nodes
                                  if (icuTNode.activeCaseIndex !== null) {
                                      var removeCodes = tIcu.remove[icuTNode.activeCaseIndex];
                                      for (var k = 0; k < removeCodes.length; k++) {
                                          var removeOpCode = removeCodes[k];
                                          switch (removeOpCode & 7 /* MASK_OPCODE */) {
                                              case 3 /* Remove */:
                                                  var nodeIndex_1 = removeOpCode >>> 3 /* SHIFT_REF */;
                                                  // Remove DOM element, but do *not* mark TNode as detached, since we are
                                                  // just switching ICU cases (while keeping the same TNode), so a DOM element
                                                  // representing a new ICU case will be re-created.
                                                  removeNode(tView, lView, nodeIndex_1, /* markAsDetached */ false);
                                                  break;
                                              case 6 /* RemoveNestedIcu */:
                                                  var nestedIcuNodeIndex = removeCodes[k + 1] >>> 3 /* SHIFT_REF */;
                                                  var nestedIcuTNode = getTNode(tView, nestedIcuNodeIndex);
                                                  var activeIndex = nestedIcuTNode.activeCaseIndex;
                                                  if (activeIndex !== null) {
                                                      var nestedIcuTIndex = removeOpCode >>> 3 /* SHIFT_REF */;
                                                      var nestedTIcu = icus[nestedIcuTIndex];
                                                      addAllToArray(nestedTIcu.remove[activeIndex], removeCodes);
                                                  }
                                                  break;
                                          }
                                      }
                                  }
                                  // Update the active caseIndex
                                  var caseIndex = getCaseIndex(tIcu, value);
                                  icuTNode.activeCaseIndex = caseIndex !== -1 ? caseIndex : null;
                                  if (caseIndex > -1) {
                                      // Add the nodes for the new case
                                      readCreateOpCodes(-1, tIcu.create[caseIndex], tView, lView);
                                      caseCreated = true;
                                  }
                                  break;
                              case 3 /* IcuUpdate */:
                                  tIcuIndex = updateOpCodes[++j];
                                  tIcu = icus[tIcuIndex];
                                  icuTNode = getTNode(tView, nodeIndex);
                                  if (icuTNode.activeCaseIndex !== null) {
                                      readUpdateOpCodes(tIcu.update[icuTNode.activeCaseIndex], icus, bindingsStartIndex, changeMask, tView, lView, caseCreated);
                                  }
                                  break;
                          }
                      }
                  }
              }
          }
          i += skipCodes;
      }
  }
  function removeNode(tView, lView, index, markAsDetached) {
      var removedPhTNode = getTNode(tView, index);
      var removedPhRNode = getNativeByIndex(index, lView);
      if (removedPhRNode) {
          nativeRemoveNode(lView[RENDERER], removedPhRNode);
      }
      var slotValue = load(lView, index);
      if (isLContainer(slotValue)) {
          var lContainer = slotValue;
          if (removedPhTNode.type !== 0 /* Container */) {
              nativeRemoveNode(lView[RENDERER], lContainer[NATIVE]);
          }
      }
      if (markAsDetached) {
          // Define this node as detached to avoid projecting it later
          removedPhTNode.flags |= 64 /* isDetached */;
      }
      ngDevMode && ngDevMode.rendererRemoveNode++;
  }
  /**
   *
   * 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 message The translation message.
   * @param subTemplateIndex Optional sub-template index in the `message`.
   *
   * @codeGenApi
   */
  function ɵɵi18n(index, message, subTemplateIndex) {
      ɵɵi18nStart(index, message, subTemplateIndex);
      ɵɵi18nEnd();
  }
  /**
   * Marks a list of attributes as translatable.
   *
   * @param index A unique index in the static block
   * @param values
   *
   * @codeGenApi
   */
  function ɵɵi18nAttributes(index, values) {
      var lView = getLView();
      var tView = getTView();
      ngDevMode && assertDefined(tView, "tView should be defined");
      i18nAttributesFirstPass(lView, tView, index, values);
  }
  /**
   * See `i18nAttributes` above.
   */
  function i18nAttributesFirstPass(lView, tView, index, values) {
      var previousElement = getPreviousOrParentTNode();
      var previousElementIndex = previousElement.index - HEADER_OFFSET;
      var updateOpCodes = [];
      for (var i = 0; i < values.length; i += 2) {
          var attrName = values[i];
          var message = values[i + 1];
          var parts = message.split(ICU_REGEXP);
          for (var j = 0; j < parts.length; j++) {
              var value = parts[j];
              if (j & 1) {
                  // Odd indexes are ICU expressions
                  // TODO(ocombe): support ICU expressions in attributes
                  throw new Error('ICU expressions are not yet supported in attributes');
              }
              else if (value !== '') {
                  // Even indexes are text (including bindings)
                  var hasBinding = !!value.match(BINDING_REGEXP);
                  if (hasBinding) {
                      if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
                          addAllToArray(generateBindingUpdateOpCodes(value, previousElementIndex, attrName), updateOpCodes);
                      }
                  }
                  else {
                      var tNode = getTNode(tView, previousElementIndex);
                      // Set attributes for Elements only, for other types (like ElementContainer),
                      // only set inputs below
                      if (tNode.type === 3 /* Element */) {
                          elementAttributeInternal(tNode, lView, attrName, value, null, null);
                      }
                      // Check if that attribute is a directive input
                      var dataValue = tNode.inputs !== null && tNode.inputs[attrName];
                      if (dataValue) {
                          setInputsForProperty(tView, lView, dataValue, attrName, value);
                          if (ngDevMode) {
                              var element = getNativeByIndex(previousElementIndex, lView);
                              setNgReflectProperties(lView, element, tNode.type, dataValue, value);
                          }
                      }
                  }
              }
          }
      }
      if (tView.firstCreatePass && tView.data[index + HEADER_OFFSET] === null) {
          tView.data[index + HEADER_OFFSET] = updateOpCodes;
      }
  }
  var changeMask = 0;
  var shiftsCounter = 0;
  /**
   * 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) {
      var lView = getLView();
      if (bindingUpdated(lView, nextBindingIndex(), value)) {
          changeMask = changeMask | (1 << shiftsCounter);
      }
      shiftsCounter++;
      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) {
      if (shiftsCounter) {
          var tView = getTView();
          ngDevMode && assertDefined(tView, "tView should be defined");
          var tI18n = tView.data[index + HEADER_OFFSET];
          var updateOpCodes = void 0;
          var icus = null;
          if (Array.isArray(tI18n)) {
              updateOpCodes = tI18n;
          }
          else {
              updateOpCodes = tI18n.update;
              icus = tI18n.icus;
          }
          var bindingsStartIndex = getBindingIndex() - shiftsCounter - 1;
          var lView = getLView();
          readUpdateOpCodes(updateOpCodes, icus, bindingsStartIndex, changeMask, tView, lView);
          // Reset changeMask & maskBit to default for the next update cycle
          changeMask = 0;
          shiftsCounter = 0;
      }
  }
  /**
   * 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) {
      var index = icuExpression.cases.indexOf(bindingValue);
      if (index === -1) {
          switch (icuExpression.type) {
              case 1 /* plural */: {
                  var resolvedCase = getPluralCase(bindingValue, getLocaleId());
                  index = icuExpression.cases.indexOf(resolvedCase);
                  if (index === -1 && resolvedCase !== 'other') {
                      index = icuExpression.cases.indexOf('other');
                  }
                  break;
              }
              case 0 /* select */: {
                  index = icuExpression.cases.indexOf('other');
                  break;
              }
          }
      }
      return index;
  }
  /**
   * Generate the OpCodes for ICU expressions.
   *
   * @param tIcus
   * @param icuExpression
   * @param startIndex
   * @param expandoStartIndex
   */
  function icuStart(tIcus, icuExpression, startIndex, expandoStartIndex) {
      var createCodes = [];
      var removeCodes = [];
      var updateCodes = [];
      var vars = [];
      var childIcus = [];
      for (var i = 0; i < icuExpression.values.length; i++) {
          // Each value is an array of strings & other ICU expressions
          var valueArr = icuExpression.values[i];
          var nestedIcus = [];
          for (var j = 0; j < valueArr.length; j++) {
              var value = valueArr[j];
              if (typeof value !== 'string') {
                  // It is an nested ICU expression
                  var icuIndex = nestedIcus.push(value) - 1;
                  // Replace nested ICU expression by a comment node
                  valueArr[j] = "<!--\uFFFD" + icuIndex + "\uFFFD-->";
              }
          }
          var icuCase = parseIcuCase(valueArr.join(''), startIndex, nestedIcus, tIcus, expandoStartIndex);
          createCodes.push(icuCase.create);
          removeCodes.push(icuCase.remove);
          updateCodes.push(icuCase.update);
          vars.push(icuCase.vars);
          childIcus.push(icuCase.childIcus);
      }
      var tIcu = {
          type: icuExpression.type,
          vars: vars,
          childIcus: childIcus,
          cases: icuExpression.cases,
          create: createCodes,
          remove: removeCodes,
          update: updateCodes
      };
      tIcus.push(tIcu);
      // Adding the maximum possible of vars needed (based on the cases with the most vars)
      i18nVarsCount += Math.max.apply(Math, __spread(vars));
  }
  /**
   * Transforms a string template into an HTML template and a list of instructions used to update
   * attributes or nodes that contain bindings.
   *
   * @param unsafeHtml The string to parse
   * @param parentIndex
   * @param nestedIcus
   * @param tIcus
   * @param expandoStartIndex
   */
  function parseIcuCase(unsafeHtml, parentIndex, nestedIcus, tIcus, expandoStartIndex) {
      var inertBodyHelper = new InertBodyHelper(getDocument());
      var inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
      if (!inertBodyElement) {
          throw new Error('Unable to generate inert body element');
      }
      var wrapper = getTemplateContent(inertBodyElement) || inertBodyElement;
      var opCodes = { vars: 0, childIcus: [], create: [], remove: [], update: [] };
      parseNodes(wrapper.firstChild, opCodes, parentIndex, nestedIcus, tIcus, expandoStartIndex);
      return opCodes;
  }
  var NESTED_ICU = /�(\d+)�/;
  /**
   * Parses a node, its children and its siblings, and generates the mutate & update OpCodes.
   *
   * @param currentNode The first node to parse
   * @param icuCase The data for the ICU expression case that contains those nodes
   * @param parentIndex Index of the current node's parent
   * @param nestedIcus Data for the nested ICU expressions that this case contains
   * @param tIcus Data for all ICU expressions of the current message
   * @param expandoStartIndex Expando start index for the current ICU expression
   */
  function parseNodes(currentNode, icuCase, parentIndex, nestedIcus, tIcus, expandoStartIndex) {
      if (currentNode) {
          var nestedIcusToCreate = [];
          while (currentNode) {
              var nextNode = currentNode.nextSibling;
              var newIndex = expandoStartIndex + ++icuCase.vars;
              switch (currentNode.nodeType) {
                  case Node.ELEMENT_NODE:
                      var element = currentNode;
                      var tagName = element.tagName.toLowerCase();
                      if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {
                          // This isn't a valid element, we won't create an element for it
                          icuCase.vars--;
                      }
                      else {
                          icuCase.create.push(ELEMENT_MARKER, tagName, newIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
                          var elAttrs = element.attributes;
                          for (var i = 0; i < elAttrs.length; i++) {
                              var attr = elAttrs.item(i);
                              var lowerAttrName = attr.name.toLowerCase();
                              var hasBinding_1 = !!attr.value.match(BINDING_REGEXP);
                              // we assume the input string is safe, unless it's using a binding
                              if (hasBinding_1) {
                                  if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
                                      if (URI_ATTRS[lowerAttrName]) {
                                          addAllToArray(generateBindingUpdateOpCodes(attr.value, newIndex, attr.name, _sanitizeUrl), icuCase.update);
                                      }
                                      else if (SRCSET_ATTRS[lowerAttrName]) {
                                          addAllToArray(generateBindingUpdateOpCodes(attr.value, newIndex, attr.name, sanitizeSrcset), icuCase.update);
                                      }
                                      else {
                                          addAllToArray(generateBindingUpdateOpCodes(attr.value, newIndex, attr.name), icuCase.update);
                                      }
                                  }
                                  else {
                                      ngDevMode &&
                                          console.warn("WARNING: ignoring unsafe attribute value " + lowerAttrName + " on element " + tagName + " (see http://g.co/ng/security#xss)");
                                  }
                              }
                              else {
                                  icuCase.create.push(newIndex << 3 /* SHIFT_REF */ | 4 /* Attr */, attr.name, attr.value);
                              }
                          }
                          // Parse the children of this node (if any)
                          parseNodes(currentNode.firstChild, icuCase, newIndex, nestedIcus, tIcus, expandoStartIndex);
                          // Remove the parent node after the children
                          icuCase.remove.push(newIndex << 3 /* SHIFT_REF */ | 3 /* Remove */);
                      }
                      break;
                  case Node.TEXT_NODE:
                      var value = currentNode.textContent || '';
                      var hasBinding = value.match(BINDING_REGEXP);
                      icuCase.create.push(hasBinding ? '' : value, newIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
                      icuCase.remove.push(newIndex << 3 /* SHIFT_REF */ | 3 /* Remove */);
                      if (hasBinding) {
                          addAllToArray(generateBindingUpdateOpCodes(value, newIndex), icuCase.update);
                      }
                      break;
                  case Node.COMMENT_NODE:
                      // Check if the comment node is a placeholder for a nested ICU
                      var match = NESTED_ICU.exec(currentNode.textContent || '');
                      if (match) {
                          var nestedIcuIndex = parseInt(match[1], 10);
                          var newLocal = ngDevMode ? "nested ICU " + nestedIcuIndex : '';
                          // Create the comment node that will anchor the ICU expression
                          icuCase.create.push(COMMENT_MARKER, newLocal, newIndex, parentIndex << 17 /* SHIFT_PARENT */ | 1 /* AppendChild */);
                          var nestedIcu = nestedIcus[nestedIcuIndex];
                          nestedIcusToCreate.push([nestedIcu, newIndex]);
                      }
                      else {
                          // We do not handle any other type of comment
                          icuCase.vars--;
                      }
                      break;
                  default:
                      // We do not handle any other type of element
                      icuCase.vars--;
              }
              currentNode = nextNode;
          }
          for (var i = 0; i < nestedIcusToCreate.length; i++) {
              var nestedIcu = nestedIcusToCreate[i][0];
              var nestedIcuNodeIndex = nestedIcusToCreate[i][1];
              icuStart(tIcus, nestedIcu, nestedIcuNodeIndex, expandoStartIndex + icuCase.vars);
              // Since this is recursive, the last TIcu that was pushed is the one we want
              var nestTIcuIndex = tIcus.length - 1;
              icuCase.vars += Math.max.apply(Math, __spread(tIcus[nestTIcuIndex].vars));
              icuCase.childIcus.push(nestTIcuIndex);
              var mask = getBindingMask(nestedIcu);
              icuCase.update.push(toMaskBit(nestedIcu.mainBinding), // mask of the main binding
              3, // skip 3 opCodes if not changed
              -1 - nestedIcu.mainBinding, nestedIcuNodeIndex << 2 /* SHIFT_REF */ | 2 /* IcuSwitch */, nestTIcuIndex, mask, // mask of all the bindings of this ICU expression
              2, // skip 2 opCodes if not changed
              nestedIcuNodeIndex << 2 /* SHIFT_REF */ | 3 /* IcuUpdate */, nestTIcuIndex);
              icuCase.remove.push(nestTIcuIndex << 3 /* SHIFT_REF */ | 6 /* RemoveNestedIcu */, nestedIcuNodeIndex << 3 /* SHIFT_REF */ | 3 /* Remove */);
          }
      }
  }
  /**
   * 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.
   */
  var NGSP_UNICODE_REGEXP = /\uE500/g;
  function replaceNgsp(value) {
      return value.replace(NGSP_UNICODE_REGEXP, ' ');
  }
  /**
   * 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.
   */
  var LOCALE_ID = 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 = 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;
  }

  /**
   * @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
   */
  /**
   * 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 marked as pure, resulting in the metadata assignments being
   * tree-shaken away during production builds.
   */
  function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
      return noSideEffects(function () {
          var _a;
          var clazz = type;
          // We determine whether a class has its own metadata by taking the metadata from the
          // parent constructor and checking whether it's the same as the subclass metadata below.
          // We can't use `hasOwnProperty` here because it doesn't work correctly in IE10 for
          // static fields that are defined by TS. See
          // https://github.com/angular/angular/pull/28439#issuecomment-459349218.
          var parentPrototype = clazz.prototype ? Object.getPrototypeOf(clazz.prototype) : null;
          var parentConstructor = parentPrototype && parentPrototype.constructor;
          if (decorators !== null) {
              if (clazz.decorators !== undefined &&
                  (!parentConstructor || parentConstructor.decorators !== clazz.decorators)) {
                  (_a = clazz.decorators).push.apply(_a, __spread(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.propDecorators !== undefined &&
                  (!parentConstructor ||
                      parentConstructor.propDecorators !== clazz.propDecorators)) {
                  clazz.propDecorators = __assign(__assign({}, clazz.propDecorators), propDecorators);
              }
              else {
                  clazz.propDecorators = propDecorators;
              }
          }
      });
  }

  /**
   * @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
   */
  /**
   * Map of module-id to the corresponding NgModule.
   * - In pre Ivy we track NgModuleFactory,
   * - In post Ivy we track the NgModuleType
   */
  var modules = new Map();
  /**
   * Registers a loaded module. Should only be called from generated NgModuleFactory code.
   * @publicApi
   */
  function registerModuleFactory(id, factory) {
      var existing = modules.get(id);
      assertSameOrNotExisting(id, existing && existing.moduleType, factory.moduleType);
      modules.set(id, factory);
  }
  function assertSameOrNotExisting(id, type, incoming) {
      if (type && type !== incoming) {
          throw new Error("Duplicate module registered for " + id + " - " + stringify(type) + " vs " + stringify(type.name));
      }
  }
  function registerNgModuleType(ngModuleType) {
      if (ngModuleType.ɵmod.id !== null) {
          var id = ngModuleType.ɵmod.id;
          var existing = modules.get(id);
          assertSameOrNotExisting(id, existing, ngModuleType);
          modules.set(id, ngModuleType);
      }
      var imports = ngModuleType.ɵmod.imports;
      if (imports instanceof Function) {
          imports = imports();
      }
      if (imports) {
          imports.forEach(function (i) { return registerNgModuleType(i); });
      }
  }
  function clearModulesForTest() {
      modules.clear();
  }
  function getRegisteredNgModuleType(id) {
      return modules.get(id) || autoRegisterModuleById[id];
  }

  /**
   * @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
   */
  var NgModuleRef$1 = /** @class */ (function (_super) {
      __extends(NgModuleRef$1, _super);
      function NgModuleRef$1(ngModuleType, _parent) {
          var _this = _super.call(this) || this;
          _this._parent = _parent;
          // tslint:disable-next-line:require-internal-with-underscore
          _this._bootstrapComponents = [];
          _this.injector = _this;
          _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$1(_this);
          var ngModuleDef = getNgModuleDef(ngModuleType);
          ngDevMode &&
              assertDefined(ngModuleDef, "NgModule '" + stringify(ngModuleType) + "' is not a subtype of 'NgModuleType'.");
          var ngLocaleIdDef = getNgLocaleIdDef(ngModuleType);
          ngLocaleIdDef && setLocaleId(ngLocaleIdDef);
          _this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap);
          _this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [
              { provide: NgModuleRef, useValue: _this }, {
                  provide: ComponentFactoryResolver,
                  useValue: _this.componentFactoryResolver
              }
          ], stringify(ngModuleType));
          // We need to resolve the injector types separately from the injector creation, because
          // the module might be trying to use this ref in its contructor for DI which will cause a
          // circular error that will eventually error out, because the injector isn't created yet.
          _this._r3Injector._resolveInjectorDefTypes();
          _this.instance = _this.get(ngModuleType);
          return _this;
      }
      NgModuleRef$1.prototype.get = function (token, notFoundValue, injectFlags) {
          if (notFoundValue === void 0) { notFoundValue = Injector.THROW_IF_NOT_FOUND; }
          if (injectFlags === void 0) { injectFlags = exports.InjectFlags.Default; }
          if (token === Injector || token === NgModuleRef || token === INJECTOR) {
              return this;
          }
          return this._r3Injector.get(token, notFoundValue, injectFlags);
      };
      NgModuleRef$1.prototype.destroy = function () {
          ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
          var injector = this._r3Injector;
          !injector.destroyed && injector.destroy();
          this.destroyCbs.forEach(function (fn) { return fn(); });
          this.destroyCbs = null;
      };
      NgModuleRef$1.prototype.onDestroy = function (callback) {
          ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
          this.destroyCbs.push(callback);
      };
      return NgModuleRef$1;
  }(NgModuleRef));
  var NgModuleFactory$1 = /** @class */ (function (_super) {
      __extends(NgModuleFactory, _super);
      function NgModuleFactory(moduleType) {
          var _this = _super.call(this) || this;
          _this.moduleType = moduleType;
          var ngModuleDef = getNgModuleDef(moduleType);
          if (ngModuleDef !== null) {
              // Register the NgModule with Angular's module registry. The location (and hence timing) of
              // this call is critical to ensure this works correctly (modules get registered when expected)
              // without bloating bundles (modules are registered when otherwise not referenced).
              //
              // In View Engine, registration occurs in the .ngfactory.js file as a side effect. This has
              // several practical consequences:
              //
              // - If an .ngfactory file is not imported from, the module won't be registered (and can be
              //   tree shaken).
              // - If an .ngfactory file is imported from, the module will be registered even if an instance
              //   is not actually created (via `create` below).
              // - Since an .ngfactory file in View Engine references the .ngfactory files of the NgModule's
              //   imports,
              //
              // In Ivy, things are a bit different. .ngfactory files still exist for compatibility, but are
              // not a required API to use - there are other ways to obtain an NgModuleFactory for a given
              // NgModule. Thus, relying on a side effect in the .ngfactory file is not sufficient. Instead,
              // the side effect of registration is added here, in the constructor of NgModuleFactory,
              // ensuring no matter how a factory is created, the module is registered correctly.
              //
              // An alternative would be to include the registration side effect inline following the actual
              // NgModule definition. This also has the correct timing, but breaks tree-shaking - modules
              // will be registered and retained even if they're otherwise never referenced.
              registerNgModuleType(moduleType);
          }
          return _this;
      }
      NgModuleFactory.prototype.create = function (parentInjector) {
          return new NgModuleRef$1(this.moduleType, parentInjector);
      };
      return NgModuleFactory;
  }(NgModuleFactory));

  /**
   * @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
   */
  /**
   * 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) {
      var bindingIndex = getBindingRoot() + slotOffset;
      var 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) {
      var bindingIndex = getBindingRoot() + slotOffset;
      var lView = getLView();
      var 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) {
      var bindingIndex = getBindingRoot() + slotOffset;
      var lView = getLView();
      var 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) {
      var bindingIndex = getBindingRoot() + slotOffset;
      var lView = getLView();
      var 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) {
      var bindingIndex = getBindingRoot() + slotOffset;
      var lView = getLView();
      var 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 && assertDataInRange(lView, returnValueIndex);
      var 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) {
      var 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) {
      var 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) {
      var 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) {
      var 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) {
      var bindingIndex = bindingRoot + slotOffset;
      var different = false;
      for (var 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 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
   */
  /**
   * 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) {
      var tView = getTView();
      var pipeDef;
      var adjustedIndex = index + HEADER_OFFSET;
      if (tView.firstCreatePass) {
          pipeDef = getPipeDef$1(pipeName, tView.pipeRegistry);
          tView.data[adjustedIndex] = pipeDef;
          if (pipeDef.onDestroy) {
              (tView.destroyHooks || (tView.destroyHooks = [])).push(adjustedIndex, pipeDef.onDestroy);
          }
      }
      else {
          pipeDef = tView.data[adjustedIndex];
      }
      var pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));
      var previousInjectImplementation = setInjectImplementation(ɵɵdirectiveInject);
      // 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`.
      var previousIncludeViewProviders = setIncludeViewProviders(false);
      var pipeInstance = pipeFactory();
      setIncludeViewProviders(previousIncludeViewProviders);
      setInjectImplementation(previousInjectImplementation);
      store(tView, getLView(), index, pipeInstance);
      return pipeInstance;
  }
  /**
   * 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$1(name, registry) {
      if (registry) {
          for (var i = registry.length - 1; i >= 0; i--) {
              var pipeDef = registry[i];
              if (name === pipeDef.name) {
                  return pipeDef;
              }
          }
      }
      throw new Error("The pipe '" + name + "' could not be found!");
  }
  /**
   * 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) {
      var lView = getLView();
      var pipeInstance = load(lView, index);
      return unwrapValue$1(lView, isPure(lView, index) ?
          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) {
      var lView = getLView();
      var pipeInstance = load(lView, index);
      return unwrapValue$1(lView, isPure(lView, index) ?
          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) {
      var lView = getLView();
      var pipeInstance = load(lView, index);
      return unwrapValue$1(lView, isPure(lView, index) ? 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) {
      var lView = getLView();
      var pipeInstance = load(lView, index);
      return unwrapValue$1(lView, isPure(lView, index) ? 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) {
      var lView = getLView();
      var pipeInstance = load(lView, index);
      return unwrapValue$1(lView, isPure(lView, index) ?
          pureFunctionVInternal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) :
          pipeInstance.transform.apply(pipeInstance, values));
  }
  function isPure(lView, index) {
      return lView[TVIEW].data[index + HEADER_OFFSET].pure;
  }
  /**
   * Unwrap the output of a pipe transformation.
   * In order to trick change detection into considering that the new value is always different from
   * the old one, the old value is overwritten by NO_CHANGE.
   *
   * @param newValue the pipe transformation output.
   */
  function unwrapValue$1(lView, newValue) {
      if (WrappedValue.isWrapped(newValue)) {
          newValue = WrappedValue.unwrap(newValue);
          // The NO_CHANGE value needs to be written at the index where the impacted binding value is
          // stored
          var bindingToInvalidateIdx = getBindingIndex();
          lView[bindingToInvalidateIdx] = NO_CHANGE;
      }
      return newValue;
  }

  /**
   * @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
   */
  /**
   * Use in components with the `@Output` directive to emit custom events
   * synchronously or asynchronously, and register handlers for those events
   * by subscribing to an instance.
   *
   * @usageNotes
   *
   * Extends
   * [RxJS `Subject`](https://rxjs.dev/api/index/class/Subject)
   * for Angular by adding the `emit()` method.
   *
   * In the following example, a component defines two output properties
   * that create event emitters. When the title is clicked, the emitter
   * emits an open or close event to toggle the current visibility state.
   *
   * ```html
   * @Component({
   *   selector: 'zippy',
   *   template: `
   *   <div class="zippy">
   *     <div (click)="toggle()">Toggle</div>
   *     <div [hidden]="!visible">
   *       <ng-content></ng-content>
   *     </div>
   *  </div>`})
   * export class Zippy {
   *   visible: boolean = true;
   *   @Output() open: EventEmitter<any> = new EventEmitter();
   *   @Output() close: EventEmitter<any> = new EventEmitter();
   *
   *   toggle() {
   *     this.visible = !this.visible;
   *     if (this.visible) {
   *       this.open.emit(null);
   *     } else {
   *       this.close.emit(null);
   *     }
   *   }
   * }
   * ```
   *
   * Access the event object with the `$event` argument passed to the output event
   * handler:
   *
   * ```html
   * <zippy (open)="onOpen($event)" (close)="onClose($event)"></zippy>
   * ```
   *
   * @see [Observables in Angular](guide/observables-in-angular)
   * @publicApi
   */
  var EventEmitter = /** @class */ (function (_super) {
      __extends(EventEmitter, _super);
      /**
       * Creates an instance of this class that can
       * deliver events synchronously or asynchronously.
       *
       * @param isAsync When true, deliver events asynchronously.
       *
       */
      function EventEmitter(isAsync) {
          if (isAsync === void 0) { isAsync = false; }
          var _this = _super.call(this) || this;
          _this.__isAsync = isAsync;
          return _this;
      }
      /**
       * Emits an event containing a given value.
       * @param value The value to emit.
       */
      EventEmitter.prototype.emit = function (value) {
          _super.prototype.next.call(this, value);
      };
      /**
       * Registers handlers for events emitted by this instance.
       * @param generatorOrNext When supplied, a custom handler for emitted events.
       * @param error When supplied, a custom handler for an error notification
       * from this emitter.
       * @param complete When supplied, a custom handler for a completion
       * notification from this emitter.
       */
      EventEmitter.prototype.subscribe = function (generatorOrNext, error, complete) {
          var schedulerFn;
          var errorFn = function (err) { return null; };
          var completeFn = function () { return null; };
          if (generatorOrNext && typeof generatorOrNext === 'object') {
              schedulerFn = this.__isAsync ? function (value) {
                  setTimeout(function () { return generatorOrNext.next(value); });
              } : function (value) {
                  generatorOrNext.next(value);
              };
              if (generatorOrNext.error) {
                  errorFn = this.__isAsync ? function (err) {
                      setTimeout(function () { return generatorOrNext.error(err); });
                  } : function (err) {
                      generatorOrNext.error(err);
                  };
              }
              if (generatorOrNext.complete) {
                  completeFn = this.__isAsync ? function () {
                      setTimeout(function () { return generatorOrNext.complete(); });
                  } : function () {
                      generatorOrNext.complete();
                  };
              }
          }
          else {
              schedulerFn = this.__isAsync ? function (value) {
                  setTimeout(function () { return generatorOrNext(value); });
              } : function (value) {
                  generatorOrNext(value);
              };
              if (error) {
                  errorFn = this.__isAsync ? function (err) {
                      setTimeout(function () { return error(err); });
                  } : function (err) {
                      error(err);
                  };
              }
              if (complete) {
                  completeFn = this.__isAsync ? function () {
                      setTimeout(function () { return complete(); });
                  } : function () {
                      complete();
                  };
              }
          }
          var sink = _super.prototype.subscribe.call(this, schedulerFn, errorFn, completeFn);
          if (generatorOrNext instanceof rxjs.Subscription) {
              generatorOrNext.add(sink);
          }
          return sink;
      };
      return EventEmitter;
  }(rxjs.Subject));

  /**
   * @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
   */
  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
   */
  var QueryList = /** @class */ (function () {
      function QueryList() {
          this.dirty = true;
          this._results = [];
          this.changes = new EventEmitter();
          this.length = 0;
          // 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> { ... }
          var symbol = getSymbolIterator();
          var proto = QueryList.prototype;
          if (!proto[symbol])
              proto[symbol] = symbolIterator;
      }
      /**
       * See
       * [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
       */
      QueryList.prototype.map = function (fn) {
          return this._results.map(fn);
      };
      /**
       * See
       * [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
       */
      QueryList.prototype.filter = function (fn) {
          return this._results.filter(fn);
      };
      /**
       * See
       * [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
       */
      QueryList.prototype.find = function (fn) {
          return this._results.find(fn);
      };
      /**
       * See
       * [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
       */
      QueryList.prototype.reduce = function (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)
       */
      QueryList.prototype.forEach = function (fn) {
          this._results.forEach(fn);
      };
      /**
       * See
       * [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
       */
      QueryList.prototype.some = function (fn) {
          return this._results.some(fn);
      };
      /**
       * Returns a copy of the internal results list as an Array.
       */
      QueryList.prototype.toArray = function () {
          return this._results.slice();
      };
      QueryList.prototype.toString = function () {
          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
       */
      QueryList.prototype.reset = function (resultsTree) {
          this._results = flatten(resultsTree);
          this.dirty = false;
          this.length = this._results.length;
          this.last = this._results[this.length - 1];
          this.first = this._results[0];
      };
      /**
       * Triggers a change event by emitting on the `changes` {@link EventEmitter}.
       */
      QueryList.prototype.notifyOnChanges = function () {
          this.changes.emit(this);
      };
      /** internal */
      QueryList.prototype.setDirty = function () {
          this.dirty = true;
      };
      /** internal */
      QueryList.prototype.destroy = function () {
          this.changes.complete();
          this.changes.unsubscribe();
      };
      return QueryList;
  }());

  /**
   * @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
   */
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$7 = 1;

  /**
   * @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
   */
  // Note: This hack is necessary so we don't erroneously get a circular dependency
  // failure based on types.
  var unusedValueExportToPlacateAjd$8 = 1;

  /**
   * @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
   */
  var unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$7 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$8;
  var LQuery_ = /** @class */ (function () {
      function LQuery_(queryList) {
          this.queryList = queryList;
          this.matches = null;
      }
      LQuery_.prototype.clone = function () {
          return new LQuery_(this.queryList);
      };
      LQuery_.prototype.setDirty = function () {
          this.queryList.setDirty();
      };
      return LQuery_;
  }());
  var LQueries_ = /** @class */ (function () {
      function LQueries_(queries) {
          if (queries === void 0) { queries = []; }
          this.queries = queries;
      }
      LQueries_.prototype.createEmbeddedView = function (tView) {
          var tQueries = tView.queries;
          if (tQueries !== null) {
              var noOfInheritedQueries = tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length;
              var 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 (var i = 0; i < noOfInheritedQueries; i++) {
                  var tQuery = tQueries.getByIndex(i);
                  var parentLQuery = this.queries[tQuery.indexInDeclarationView];
                  viewLQueries.push(parentLQuery.clone());
              }
              return new LQueries_(viewLQueries);
          }
          return null;
      };
      LQueries_.prototype.insertView = function (tView) {
          this.dirtyQueriesWithMatches(tView);
      };
      LQueries_.prototype.detachView = function (tView) {
          this.dirtyQueriesWithMatches(tView);
      };
      LQueries_.prototype.dirtyQueriesWithMatches = function (tView) {
          for (var i = 0; i < this.queries.length; i++) {
              if (getTQuery(tView, i).matches !== null) {
                  this.queries[i].setDirty();
              }
          }
      };
      return LQueries_;
  }());
  var TQueryMetadata_ = /** @class */ (function () {
      function TQueryMetadata_(predicate, descendants, isStatic, read) {
          if (read === void 0) { read = null; }
          this.predicate = predicate;
          this.descendants = descendants;
          this.isStatic = isStatic;
          this.read = read;
      }
      return TQueryMetadata_;
  }());
  var TQueries_ = /** @class */ (function () {
      function TQueries_(queries) {
          if (queries === void 0) { queries = []; }
          this.queries = queries;
      }
      TQueries_.prototype.elementStart = function (tView, tNode) {
          ngDevMode &&
              assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');
          for (var i = 0; i < this.queries.length; i++) {
              this.queries[i].elementStart(tView, tNode);
          }
      };
      TQueries_.prototype.elementEnd = function (tNode) {
          for (var i = 0; i < this.queries.length; i++) {
              this.queries[i].elementEnd(tNode);
          }
      };
      TQueries_.prototype.embeddedTView = function (tNode) {
          var queriesForTemplateRef = null;
          for (var i = 0; i < this.length; i++) {
              var childQueryIndex = queriesForTemplateRef !== null ? queriesForTemplateRef.length : 0;
              var 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;
      };
      TQueries_.prototype.template = function (tView, tNode) {
          ngDevMode &&
              assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');
          for (var i = 0; i < this.queries.length; i++) {
              this.queries[i].template(tView, tNode);
          }
      };
      TQueries_.prototype.getByIndex = function (index) {
          ngDevMode && assertDataInRange(this.queries, index);
          return this.queries[index];
      };
      Object.defineProperty(TQueries_.prototype, "length", {
          get: function () {
              return this.queries.length;
          },
          enumerable: true,
          configurable: true
      });
      TQueries_.prototype.track = function (tquery) {
          this.queries.push(tquery);
      };
      return TQueries_;
  }());
  var TQuery_ = /** @class */ (function () {
      function TQuery_(metadata, nodeIndex) {
          if (nodeIndex === void 0) { 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;
      }
      TQuery_.prototype.elementStart = function (tView, tNode) {
          if (this.isApplyingToNode(tNode)) {
              this.matchTNode(tView, tNode);
          }
      };
      TQuery_.prototype.elementEnd = function (tNode) {
          if (this._declarationNodeIndex === tNode.index) {
              this._appliesToNextNode = false;
          }
      };
      TQuery_.prototype.template = function (tView, tNode) {
          this.elementStart(tView, tNode);
      };
      TQuery_.prototype.embeddedTView = function (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;
      };
      TQuery_.prototype.isApplyingToNode = function (tNode) {
          if (this._appliesToNextNode && this.metadata.descendants === false) {
              var declarationNodeIdx = this._declarationNodeIndex;
              var parent_1 = 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_1 !== null && parent_1.type === 4 /* ElementContainer */ &&
                  parent_1.index !== declarationNodeIdx) {
                  parent_1 = parent_1.parent;
              }
              return declarationNodeIdx === (parent_1 !== null ? parent_1.index : -1);
          }
          return this._appliesToNextNode;
      };
      TQuery_.prototype.matchTNode = function (tView, tNode) {
          if (Array.isArray(this.metadata.predicate)) {
              var localNames = this.metadata.predicate;
              for (var i = 0; i < localNames.length; i++) {
                  this.matchTNodeWithReadOption(tView, tNode, getIdxOfMatchingSelector(tNode, localNames[i]));
              }
          }
          else {
              var typePredicate = this.metadata.predicate;
              if (typePredicate === TemplateRef) {
                  if (tNode.type === 0 /* Container */) {
                      this.matchTNodeWithReadOption(tView, tNode, -1);
                  }
              }
              else {
                  this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, typePredicate, false, false));
              }
          }
      };
      TQuery_.prototype.matchTNodeWithReadOption = function (tView, tNode, nodeMatchIdx) {
          if (nodeMatchIdx !== null) {
              var read = this.metadata.read;
              if (read !== null) {
                  if (read === ElementRef || read === ViewContainerRef ||
                      read === TemplateRef && tNode.type === 0 /* Container */) {
                      this.addMatch(tNode.index, -2);
                  }
                  else {
                      var directiveOrProviderIdx = locateDirectiveOrProvider(tNode, tView, read, false, false);
                      if (directiveOrProviderIdx !== null) {
                          this.addMatch(tNode.index, directiveOrProviderIdx);
                      }
                  }
              }
              else {
                  this.addMatch(tNode.index, nodeMatchIdx);
              }
          }
      };
      TQuery_.prototype.addMatch = function (tNodeIdx, matchIdx) {
          if (this.matches === null) {
              this.matches = [tNodeIdx, matchIdx];
          }
          else {
              this.matches.push(tNodeIdx, matchIdx);
          }
      };
      return TQuery_;
  }());
  /**
   * 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) {
      var localNames = tNode.localNames;
      if (localNames !== null) {
          for (var 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 /* Element */ || tNode.type === 4 /* ElementContainer */) {
          return createElementRef(ElementRef, tNode, currentView);
      }
      else if (tNode.type === 0 /* Container */) {
          return createTemplateRef(TemplateRef, ElementRef, 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(ElementRef, tNode, lView);
      }
      else if (read === TemplateRef) {
          return createTemplateRef(TemplateRef, ElementRef, tNode, lView);
      }
      else if (read === ViewContainerRef) {
          ngDevMode &&
              assertNodeOfPossibleTypes(tNode, 3 /* Element */, 0 /* Container */, 4 /* ElementContainer */);
          return createContainerRef(ViewContainerRef, ElementRef, 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) {
      var lQuery = lView[QUERIES].queries[queryIndex];
      if (lQuery.matches === null) {
          var tViewData = tView.data;
          var tQueryMatches = tQuery.matches;
          var result = [];
          for (var i = 0; i < tQueryMatches.length; i += 2) {
              var 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 && assertDataInRange(tViewData, matchedNodeIdx);
                  var 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) {
      var tQuery = tView.queries.getByIndex(queryIndex);
      var tQueryMatches = tQuery.matches;
      if (tQueryMatches !== null) {
          var lViewResults = materializeViewResults(tView, lView, tQuery, queryIndex);
          for (var i = 0; i < tQueryMatches.length; i += 2) {
              var tNodeIdx = tQueryMatches[i];
              if (tNodeIdx > 0) {
                  result.push(lViewResults[i / 2]);
              }
              else {
                  var childQueryIndex = tQueryMatches[i + 1];
                  var declarationLContainer = lView[-tNodeIdx];
                  ngDevMode && assertLContainer(declarationLContainer);
                  // collect matches for views inserted in this container
                  for (var i_1 = CONTAINER_HEADER_OFFSET; i_1 < declarationLContainer.length; i_1++) {
                      var embeddedLView = declarationLContainer[i_1];
                      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) {
                      var embeddedLViews = declarationLContainer[MOVED_VIEWS];
                      for (var i_2 = 0; i_2 < embeddedLViews.length; i_2++) {
                          var embeddedLView = embeddedLViews[i_2];
                          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) {
      var lView = getLView();
      var tView = getTView();
      var queryIndex = getCurrentQueryIndex();
      setCurrentQueryIndex(queryIndex + 1);
      var tQuery = getTQuery(tView, queryIndex);
      if (queryList.dirty && (isCreationMode(lView) === tQuery.metadata.isStatic)) {
          if (tQuery.matches === null) {
              queryList.reset([]);
          }
          else {
              var result = tQuery.crossesNgTemplate ?
                  collectQueryResults(tView, lView, queryIndex, []) :
                  materializeViewResults(tView, lView, tQuery, queryIndex);
              queryList.reset(result);
              queryList.notifyOnChanges();
          }
          return true;
      }
      return false;
  }
  /**
   * Creates new QueryList for a static view query.
   *
   * @param predicate The type for which the query will search
   * @param descend Whether or not to descend into children
   * @param read What to save in the query
   *
   * @codeGenApi
   */
  function ɵɵstaticViewQuery(predicate, descend, read) {
      viewQueryInternal(getTView(), getLView(), predicate, descend, read, true);
  }
  /**
   * Creates new QueryList, stores the reference in LView and returns QueryList.
   *
   * @param predicate The type for which the query will search
   * @param descend Whether or not to descend into children
   * @param read What to save in the query
   *
   * @codeGenApi
   */
  function ɵɵviewQuery(predicate, descend, read) {
      viewQueryInternal(getTView(), getLView(), predicate, descend, read, false);
  }
  function viewQueryInternal(tView, lView, predicate, descend, read, isStatic) {
      if (tView.firstCreatePass) {
          createTQuery(tView, new TQueryMetadata_(predicate, descend, isStatic, read), -1);
          if (isStatic) {
              tView.staticViewQueries = true;
          }
      }
      createLQuery(tView, lView);
  }
  /**
   * 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 descend Whether or not to descend into children
   * @param read What to save in the query
   * @returns QueryList<T>
   *
   * @codeGenApi
   */
  function ɵɵcontentQuery(directiveIndex, predicate, descend, read) {
      contentQueryInternal(getTView(), getLView(), predicate, descend, read, false, getPreviousOrParentTNode(), directiveIndex);
  }
  /**
   * Registers a QueryList, associated with a static 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 descend Whether or not to descend into children
   * @param read What to save in the query
   * @returns QueryList<T>
   *
   * @codeGenApi
   */
  function ɵɵstaticContentQuery(directiveIndex, predicate, descend, read) {
      contentQueryInternal(getTView(), getLView(), predicate, descend, read, true, getPreviousOrParentTNode(), directiveIndex);
  }
  function contentQueryInternal(tView, lView, predicate, descend, read, isStatic, tNode, directiveIndex) {
      if (tView.firstCreatePass) {
          createTQuery(tView, new TQueryMetadata_(predicate, descend, isStatic, read), tNode.index);
          saveContentQueryAndDirectiveIndex(tView, directiveIndex);
          if (isStatic) {
              tView.staticContentQueries = true;
          }
      }
      createLQuery(tView, lView);
  }
  /**
   * 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 && assertDataInRange(lView[QUERIES].queries, queryIndex);
      return lView[QUERIES].queries[queryIndex].queryList;
  }
  function createLQuery(tView, lView) {
      var queryList = new QueryList();
      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) {
      var tViewContentQueries = tView.contentQueries || (tView.contentQueries = []);
      var lastSavedDirectiveIndex = tView.contentQueries.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 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
   */
  /**
   * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
   * `<ng-template>` element.
   *
   * @codeGenApi
   */
  function ɵɵtemplateRefExtractor(tNode, currentView) {
      return createTemplateRef(TemplateRef, ElementRef, tNode, currentView);
  }
  /**
   * Returns the appropriate `ChangeDetectorRef` for a pipe.
   *
   * @codeGenApi
   */
  function ɵɵinjectPipeChangeDetectorRef(flags) {
      if (flags === void 0) { flags = exports.InjectFlags.Default; }
      var value = injectChangeDetectorRef(true);
      if (value == null && !(flags & exports.InjectFlags.Optional)) {
          throw new Error("No provider for ChangeDetectorRef!");
      }
      else {
          return value;
      }
  }

  /**
   * @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
   */

  /**
   * @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
   */
  var ɵ0$d = function () { return ({
      'ɵɵ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,
      'ɵɵgetFactoryOf': ɵɵgetFactoryOf,
      'ɵɵgetInheritedFactory': ɵɵgetInheritedFactory,
      'ɵɵinject': ɵɵinject,
      'ɵɵinjectAttribute': ɵɵinjectAttribute,
      'ɵɵinvalidFactory': ɵɵinvalidFactory,
      'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
      'ɵɵinjectPipeChangeDetectorRef': ɵɵinjectPipeChangeDetectorRef,
      'ɵɵtemplateRefExtractor': ɵɵtemplateRefExtractor,
      'ɵɵNgOnChangesFeature': ɵɵNgOnChangesFeature,
      'ɵɵProvidersFeature': ɵɵProvidersFeature,
      'ɵɵCopyDefinitionFeature': ɵɵCopyDefinitionFeature,
      'ɵɵInheritDefinitionFeature': ɵɵInheritDefinitionFeature,
      'ɵɵ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,
      'ɵɵupdateSyntheticHostBinding': ɵɵupdateSyntheticHostBinding,
      'ɵɵcomponentHostSyntheticListener': ɵɵcomponentHostSyntheticListener,
      'ɵɵ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,
      'ɵɵstaticViewQuery': ɵɵstaticViewQuery,
      'ɵɵstaticContentQuery': ɵɵstaticContentQuery,
      'ɵɵ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,
      'ɵɵstyleSanitizer': ɵɵstyleSanitizer,
      'ɵɵclassProp': ɵɵclassProp,
      'ɵɵselect': ɵɵselect,
      'ɵɵ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,
      'ɵɵsanitizeHtml': ɵɵsanitizeHtml,
      'ɵɵsanitizeStyle': ɵɵsanitizeStyle,
      'ɵɵdefaultStyleSanitizer': ɵɵdefaultStyleSanitizer,
      'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl,
      'ɵɵsanitizeScript': ɵɵsanitizeScript,
      'ɵɵsanitizeUrl': ɵɵsanitizeUrl,
      'ɵɵsanitizeUrlOrResourceUrl': ɵɵsanitizeUrlOrResourceUrl,
  }); };
  /**
   * 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.
   */
  var angularCoreEnv = (ɵ0$d)();

  var 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 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
   */
  var EMPTY_ARRAY$5 = [];
  var 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: moduleType, ngModule: ngModule });
  }
  var 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 (var i = moduleQueue.length - 1; i >= 0; i--) {
                  var _a = moduleQueue[i], moduleType = _a.moduleType, ngModule = _a.ngModule;
                  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) {
      if (ngModule === void 0) { ngModule = {}; }
      compileNgModuleDefs(moduleType, ngModule);
      // 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` 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) {
      if (allowDuplicateDeclarationsInRoot === void 0) { allowDuplicateDeclarationsInRoot = false; }
      ngDevMode && assertDefined(moduleType, 'Required value moduleType');
      ngDevMode && assertDefined(ngModule, 'Required value ngModule');
      var declarations = flatten(ngModule.declarations || EMPTY_ARRAY$5);
      var ngModuleDef = null;
      Object.defineProperty(moduleType, NG_MOD_DEF, {
          configurable: true,
          get: function () {
              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");
                  }
                  ngModuleDef = getCompilerFacade().compileNgModule(angularCoreEnv, "ng:///" + moduleType.name + "/\u0275mod.js", {
                      type: moduleType,
                      bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY$5).map(resolveForwardRef),
                      declarations: declarations.map(resolveForwardRef),
                      imports: flatten(ngModule.imports || EMPTY_ARRAY$5)
                          .map(resolveForwardRef)
                          .map(expandModuleWithProviders),
                      exports: flatten(ngModule.exports || EMPTY_ARRAY$5)
                          .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;
          }
      });
      var ngInjectorDef = null;
      Object.defineProperty(moduleType, NG_INJ_DEF, {
          get: function () {
              if (ngInjectorDef === null) {
                  ngDevMode &&
                      verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot);
                  var meta = {
                      name: moduleType.name,
                      type: moduleType,
                      deps: reflectDependencies(moduleType),
                      providers: ngModule.providers || EMPTY_ARRAY$5,
                      imports: [
                          (ngModule.imports || EMPTY_ARRAY$5).map(resolveForwardRef),
                          (ngModule.exports || EMPTY_ARRAY$5).map(resolveForwardRef),
                      ],
                  };
                  ngInjectorDef = getCompilerFacade().compileInjector(angularCoreEnv, "ng:///" + moduleType.name + "/\u0275inj.js", meta);
              }
              return ngInjectorDef;
          },
          // Make the property configurable in dev mode to allow overriding in tests
          configurable: !!ngDevMode,
      });
  }
  function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot, importingModule) {
      if (verifiedNgModule.get(moduleType))
          return;
      verifiedNgModule.set(moduleType, true);
      moduleType = resolveForwardRef(moduleType);
      var 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);
      }
      var errors = [];
      var declarations = maybeUnwrapFn(ngModuleDef.declarations);
      var imports = maybeUnwrapFn(ngModuleDef.imports);
      flatten(imports).map(unwrapModuleWithProvidersImports).forEach(function (mod) {
          verifySemanticsOfNgModuleImport(mod, moduleType);
          verifySemanticsOfNgModuleDef(mod, false, moduleType);
      });
      var exports = maybeUnwrapFn(ngModuleDef.exports);
      declarations.forEach(verifyDeclarationsHaveDefinitions);
      declarations.forEach(verifyDirectivesHaveSelector);
      var combinedDeclarations = __spread(declarations.map(resolveForwardRef), flatten(imports.map(computeCombinedExports)).map(resolveForwardRef));
      exports.forEach(verifyExportsAreDeclaredOrReExported);
      declarations.forEach(function (decl) { return verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot); });
      declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule);
      var ngModule = getAnnotation(moduleType, 'NgModule');
      if (ngModule) {
          ngModule.imports &&
              flatten(ngModule.imports).map(unwrapModuleWithProvidersImports).forEach(function (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);
          var def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef(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);
          var def = getDirectiveDef(type);
          if (!getComponentDef(type) && def && def.selectors.length == 0) {
              errors.push("Directive " + stringifyForError(type) + " has no selector, please add it!");
          }
      }
      function verifyExportsAreDeclaredOrReExported(type) {
          type = resolveForwardRef(type);
          var kind = getComponentDef(type) && 'component' || getDirectiveDef(type) && 'directive' ||
              getPipeDef(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);
          var existingModule = ownerNgModule.get(type);
          if (existingModule && existingModule !== moduleType) {
              if (!suppressErrors) {
                  var 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);
          var existingModule = ownerNgModule.get(type);
          if (!existingModule) {
              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.");
          }
      }
      function verifyComponentEntryComponentsIsPartOfNgModule(type) {
          type = resolveForwardRef(type);
          if (getComponentDef(type)) {
              // We know we are component
              var component = getAnnotation(type, 'Component');
              if (component && component.entryComponents) {
                  deepForEach(component.entryComponents, verifyComponentIsPartOfNgModule);
              }
          }
      }
      function verifySemanticsOfNgModuleImport(type, importingModule) {
          type = resolveForwardRef(type);
          if (getComponentDef(type) || getDirectiveDef(type)) {
              throw new Error("Unexpected directive '" + type.name + "' imported by the module '" + importingModule.name + "'. Please add an @NgModule annotation.");
          }
          if (getPipeDef(type)) {
              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) {
      var annotation = null;
      collect(type.__annotations__);
      collect(type.decorators);
      return annotation;
      function collect(annotations) {
          if (annotations) {
              annotations.forEach(readAnnotation);
          }
      }
      function readAnnotation(decorator) {
          if (!annotation) {
              var proto = Object.getPrototypeOf(decorator);
              if (proto.ngMetadataName == name) {
                  annotation = decorator;
              }
              else if (decorator.type) {
                  var proto_1 = Object.getPrototypeOf(decorator.type);
                  if (proto_1.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.
   */
  var ownerNgModule = new Map();
  var verifiedNgModule = new Map();
  function resetCompiledComponents() {
      ownerNgModule = new Map();
      verifiedNgModule = new Map();
      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);
      var ngModuleDef = getNgModuleDef(type, true);
      return __spread(flatten(maybeUnwrapFn(ngModuleDef.exports).map(function (type) {
          var 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) {
      var declarations = flatten(ngModule.declarations || EMPTY_ARRAY$5);
      var transitiveScopes = transitiveScopesFor(moduleType);
      declarations.forEach(function (declaration) {
          if (declaration.hasOwnProperty(NG_COMP_DEF)) {
              // A `ɵcmp` field exists - go ahead and patch the component directly.
              var component = declaration;
              var 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 = function () {
          return Array.from(transitiveScopes.compilation.directives)
              .map(function (dir) { return dir.hasOwnProperty(NG_COMP_DEF) ? getComponentDef(dir) : getDirectiveDef(dir); })
              .filter(function (def) { return !!def; });
      };
      componentDef.pipeDefs = function () {
          return Array.from(transitiveScopes.compilation.pipes).map(function (pipe) { return getPipeDef(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 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 transitiveScopesFor(moduleType) {
      if (!isNgModule(moduleType)) {
          throw new Error(moduleType.name + " does not have a module def (\u0275mod property)");
      }
      var def = getNgModuleDef(moduleType);
      if (def.transitiveCompileScopes !== null) {
          return def.transitiveCompileScopes;
      }
      var scopes = {
          schemas: def.schemas || null,
          compilation: {
              directives: new Set(),
              pipes: new Set(),
          },
          exported: {
              directives: new Set(),
              pipes: new Set(),
          },
      };
      maybeUnwrapFn(def.imports).forEach(function (imported) {
          var importedType = imported;
          if (!isNgModule(importedType)) {
              throw new Error("Importing " + importedType.name + " which does not have a \u0275mod property");
          }
          // When this module imports another, the imported module's exported directives and pipes are
          // added to the compilation scope of this module.
          var importedScope = transitiveScopesFor(importedType);
          importedScope.exported.directives.forEach(function (entry) { return scopes.compilation.directives.add(entry); });
          importedScope.exported.pipes.forEach(function (entry) { return scopes.compilation.pipes.add(entry); });
      });
      maybeUnwrapFn(def.declarations).forEach(function (declared) {
          var declaredWithDefs = declared;
          if (getPipeDef(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(function (exported) {
          var 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.
              var exportedScope = transitiveScopesFor(exportedType);
              exportedScope.exported.directives.forEach(function (entry) {
                  scopes.compilation.directives.add(entry);
                  scopes.exported.directives.add(entry);
              });
              exportedScope.exported.pipes.forEach(function (entry) {
                  scopes.compilation.pipes.add(entry);
                  scopes.exported.pipes.add(entry);
              });
          }
          else if (getPipeDef(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;
  }
  function isModuleWithProviders(value) {
      return value.ngModule !== undefined;
  }
  function isNgModule(value) {
      return !!getNgModuleDef(value);
  }

  /**
   * @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
   */
  /**
   * 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();
      var 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: function () {
              if (ngComponentDef === null) {
                  var compiler = getCompilerFacade();
                  if (componentNeedsResolution(metadata)) {
                      var 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.
                  var options = getJitOptions();
                  var preserveWhitespaces = metadata.preserveWhitespaces;
                  if (preserveWhitespaces === undefined) {
                      if (options !== null && options.preserveWhitespaces !== undefined) {
                          preserveWhitespaces = options.preserveWhitespaces;
                      }
                      else {
                          preserveWhitespaces = false;
                      }
                  }
                  var encapsulation = metadata.encapsulation;
                  if (encapsulation === undefined) {
                      if (options !== null && options.defaultEncapsulation !== undefined) {
                          encapsulation = options.defaultEncapsulation;
                      }
                      else {
                          encapsulation = exports.ViewEncapsulation.Emulated;
                      }
                  }
                  var templateUrl = metadata.templateUrl || "ng:///" + type.name + "/template.html";
                  var meta = __assign(__assign({}, directiveMetadata(type, metadata)), { typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl), template: metadata.template || '', preserveWhitespaces: preserveWhitespaces, styles: metadata.styles || EMPTY_ARRAY, animations: metadata.animations, directives: [], changeDetection: metadata.changeDetection, pipes: new Map(), encapsulation: encapsulation, interpolation: metadata.interpolation, viewProviders: metadata.viewProviders || null });
                  if (meta.usesInheritance) {
                      addDirectiveDefToUndecoratedParents(type);
                  }
                  ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
                  // 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)) {
                      var scopes = transitiveScopesFor(type.ngSelectorScope);
                      patchComponentDefWithScope(ngComponentDef, scopes);
                  }
              }
              return ngComponentDef;
          },
          // Make the property configurable in dev mode to allow overriding in tests
          configurable: !!ngDevMode,
      });
  }
  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) {
      var ngDirectiveDef = null;
      addDirectiveFactoryDef(type, directive || {});
      Object.defineProperty(type, NG_DIR_DEF, {
          get: function () {
              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.
                  var meta = getDirectiveMetadata(type, directive || {});
                  ngDirectiveDef =
                      getCompilerFacade().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) {
      var name = type && type.name;
      var sourceMapUrl = "ng:///" + name + "/\u0275dir.js";
      var compiler = getCompilerFacade();
      var facade = directiveMetadata(type, metadata);
      facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl);
      if (facade.usesInheritance) {
          addDirectiveDefToUndecoratedParents(type);
      }
      return { metadata: facade, sourceMapUrl: sourceMapUrl };
  }
  function addDirectiveFactoryDef(type, metadata) {
      var ngFactoryDef = null;
      Object.defineProperty(type, NG_FACTORY_DEF, {
          get: function () {
              if (ngFactoryDef === null) {
                  var meta = getDirectiveMetadata(type, metadata);
                  var compiler = getCompilerFacade();
                  ngFactoryDef = compiler.compileFactory(angularCoreEnv, "ng:///" + type.name + "/\u0275fac.js", __assign(__assign({}, meta.metadata), { injectFn: 'directiveInject', target: compiler.R3FactoryTarget.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.
      var reflect = getReflect();
      var propMetadata = reflect.ownPropMetadata(type);
      return {
          name: type.name,
          type: type,
          typeArgumentCount: 0,
          selector: metadata.selector !== undefined ? metadata.selector : null,
          deps: reflectDependencies(type),
          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)
      };
  }
  /**
   * Adds a directive definition to all parent classes of a type that don't have an Angular decorator.
   */
  function addDirectiveDefToUndecoratedParents(type) {
      var objPrototype = Object.prototype;
      var 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
      };
  }
  function extractQueriesMetadata(type, propMetadata, isQueryAnn) {
      var queriesMeta = [];
      var _loop_1 = function (field) {
          if (propMetadata.hasOwnProperty(field)) {
              var annotations_1 = propMetadata[field];
              annotations_1.forEach(function (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_1.some(isInputAnnotation)) {
                          throw new Error("Cannot combine @Input decorators with query decorators");
                      }
                      queriesMeta.push(convertToR3QueryMetadata(field, ann));
                  }
              });
          }
      };
      for (var field in propMetadata) {
          _loop_1(field);
      }
      return queriesMeta;
  }
  function extractExportAs(exportAs) {
      return exportAs === undefined ? null : splitByComma(exportAs);
  }
  function isContentQuery(value) {
      var name = value.ngMetadataName;
      return name === 'ContentChild' || name === 'ContentChildren';
  }
  function isViewQuery(value) {
      var name = value.ngMetadataName;
      return name === 'ViewChild' || name === 'ViewChildren';
  }
  function isInputAnnotation(value) {
      return value.ngMetadataName === 'Input';
  }
  function splitByComma(value) {
      return value.split(',').map(function (piece) { return piece.trim(); });
  }
  var LIFECYCLE_HOOKS = [
      'ngOnChanges', 'ngOnInit', 'ngOnDestroy', 'ngDoCheck', 'ngAfterViewInit', 'ngAfterViewChecked',
      'ngAfterContentInit', 'ngAfterContentChecked'
  ];
  function shouldAddAbstractDirective(type) {
      var reflect = getReflect();
      if (LIFECYCLE_HOOKS.some(function (hookName) { return reflect.hasLifecycleHook(type, hookName); })) {
          return true;
      }
      var propMetadata = reflect.propMetadata(type);
      for (var field in propMetadata) {
          var annotations = propMetadata[field];
          for (var i = 0; i < annotations.length; i++) {
              var current = annotations[i];
              var metadataName = current.ngMetadataName;
              if (isInputAnnotation(current) || isContentQuery(current) || isViewQuery(current) ||
                  metadataName === 'Output' || metadataName === 'HostBinding' ||
                  metadataName === 'HostListener') {
                  return true;
              }
          }
      }
      return false;
  }

  /**
   * @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
   */
  function compilePipe(type, meta) {
      var ngPipeDef = null;
      var ngFactoryDef = null;
      Object.defineProperty(type, NG_FACTORY_DEF, {
          get: function () {
              if (ngFactoryDef === null) {
                  var metadata = getPipeMetadata(type, meta);
                  var compiler = getCompilerFacade();
                  ngFactoryDef = compiler.compileFactory(angularCoreEnv, "ng:///" + metadata.name + "/\u0275fac.js", __assign(__assign({}, metadata), { injectFn: 'directiveInject', target: compiler.R3FactoryTarget.Pipe }));
              }
              return ngFactoryDef;
          },
          // Make the property configurable in dev mode to allow overriding in tests
          configurable: !!ngDevMode,
      });
      Object.defineProperty(type, NG_PIPE_DEF, {
          get: function () {
              if (ngPipeDef === null) {
                  var metadata = getPipeMetadata(type, meta);
                  ngPipeDef = getCompilerFacade().compilePipe(angularCoreEnv, "ng:///" + metadata.name + "/\u0275pipe.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,
          typeArgumentCount: 0,
          name: type.name,
          deps: reflectDependencies(type),
          pipeName: meta.name,
          pure: meta.pure !== undefined ? meta.pure : true
      };
  }

  /**
   * @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
   */
  var ɵ0$e = function (dir) {
      if (dir === void 0) { dir = {}; }
      return dir;
  }, ɵ1$3 = function (type, meta) { return SWITCH_COMPILE_DIRECTIVE(type, meta); };
  /**
   * Type of the Directive metadata.
   *
   * @publicApi
   */
  var Directive = makeDecorator('Directive', ɵ0$e, undefined, undefined, ɵ1$3);
  var ɵ2$1 = function (c) {
      if (c === void 0) { c = {}; }
      return (__assign({ changeDetection: exports.ChangeDetectionStrategy.Default }, c));
  }, ɵ3$1 = function (type, meta) { return SWITCH_COMPILE_COMPONENT(type, meta); };
  /**
   * Component decorator and metadata.
   *
   * @Annotation
   * @publicApi
   */
  var Component = makeDecorator('Component', ɵ2$1, Directive, undefined, ɵ3$1);
  var ɵ4 = function (p) { return (__assign({ pure: true }, p)); }, ɵ5 = function (type, meta) { return SWITCH_COMPILE_PIPE(type, meta); };
  /**
   * @Annotation
   * @publicApi
   */
  var Pipe = makeDecorator('Pipe', ɵ4, undefined, undefined, ɵ5);
  var ɵ6 = function (bindingPropertyName) { return ({ bindingPropertyName: bindingPropertyName }); };
  /**
   * @Annotation
   * @publicApi
   */
  var Input = makePropDecorator('Input', ɵ6);
  var ɵ7 = function (bindingPropertyName) { return ({ bindingPropertyName: bindingPropertyName }); };
  /**
   * @Annotation
   * @publicApi
   */
  var Output = makePropDecorator('Output', ɵ7);
  var ɵ8 = function (hostPropertyName) { return ({ hostPropertyName: hostPropertyName }); };
  /**
   * @Annotation
   * @publicApi
   */
  var HostBinding = makePropDecorator('HostBinding', ɵ8);
  var ɵ9 = function (eventName, args) { return ({ eventName: eventName, args: args }); };
  /**
   * 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 key-press events.
   * ``` ts
   * import { HostListener, Component } from "@angular/core";
   *
   * @Component({
   *   selector: 'app',
   *   template: `<h1>Hello, you have pressed keys {{counter}} number of times!</h1> Press any key to
   * increment the counter.
   *   <button (click)="resetCounter()">Reset Counter</button>`
   * })
   * class AppComponent {
   *   counter = 0;
   *   @HostListener('window:keydown', ['$event'])
   *   handleKeyDown(event: KeyboardEvent) {
   *     this.counter++;
   *   }
   *   resetCounter() {
   *     this.counter = 0;
   *   }
   * }
   * ```
   *
   * @Annotation
   * @publicApi
   */
  var HostListener = makePropDecorator('HostListener', ɵ9);
  var SWITCH_COMPILE_COMPONENT__POST_R3__ = compileComponent;
  var SWITCH_COMPILE_DIRECTIVE__POST_R3__ = compileDirective;
  var SWITCH_COMPILE_PIPE__POST_R3__ = compilePipe;
  var SWITCH_COMPILE_COMPONENT__PRE_R3__ = noop;
  var SWITCH_COMPILE_DIRECTIVE__PRE_R3__ = noop;
  var SWITCH_COMPILE_PIPE__PRE_R3__ = noop;
  var SWITCH_COMPILE_COMPONENT = SWITCH_COMPILE_COMPONENT__PRE_R3__;
  var SWITCH_COMPILE_DIRECTIVE = SWITCH_COMPILE_DIRECTIVE__PRE_R3__;
  var SWITCH_COMPILE_PIPE = SWITCH_COMPILE_PIPE__PRE_R3__;

  /**
   * @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
   */
  var ɵ0$f = function (ngModule) { return ngModule; }, ɵ1$4 = 
  /**
   * 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.
   */
  function (type, meta) { return SWITCH_COMPILE_NGMODULE(type, meta); };
  /**
   * @Annotation
   * @publicApi
   */
  var NgModule = makeDecorator('NgModule', ɵ0$f, undefined, undefined, ɵ1$4);
  function preR3NgModuleCompile(moduleType, metadata) {
      var imports = (metadata && metadata.imports) || [];
      if (metadata && metadata.exports) {
          imports = __spread(imports, [metadata.exports]);
      }
      moduleType.ɵinj = ɵɵdefineInjector({
          factory: convertInjectableProviderToFactory(moduleType, { useClass: moduleType }),
          providers: metadata && metadata.providers,
          imports: imports,
      });
  }
  var SWITCH_COMPILE_NGMODULE__POST_R3__ = compileNgModule;
  var SWITCH_COMPILE_NGMODULE__PRE_R3__ = preR3NgModuleCompile;
  var SWITCH_COMPILE_NGMODULE = SWITCH_COMPILE_NGMODULE__PRE_R3__;

  /**
   * @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
   */

  /**
   * @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
   */

  /**
   * @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
   */
  /**
   * An injection token that allows you to provide one or more initialization functions.
   * These function are injected at application startup and executed during
   * app initialization. If any of these functions returns a Promise, initialization
   * does not complete until the Promise is resolved.
   *
   * 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.
   * That way, the function is executed during the application bootstrap process,
   * and the needed data is available on startup.
   *
   * @publicApi
   */
  var APP_INITIALIZER = new InjectionToken('Application Initializer');
  /**
   * A class that reflects the state of running {@link APP_INITIALIZER}s.
   *
   * @publicApi
   */
  var ApplicationInitStatus = /** @class */ (function () {
      function ApplicationInitStatus(appInits) {
          var _this = this;
          this.appInits = appInits;
          this.initialized = false;
          this.done = false;
          this.donePromise = new Promise(function (res, rej) {
              _this.resolve = res;
              _this.reject = rej;
          });
      }
      /** @internal */
      ApplicationInitStatus.prototype.runInitializers = function () {
          var _this = this;
          if (this.initialized) {
              return;
          }
          var asyncInitPromises = [];
          var complete = function () {
              _this.done = true;
              _this.resolve();
          };
          if (this.appInits) {
              for (var i = 0; i < this.appInits.length; i++) {
                  var initResult = this.appInits[i]();
                  if (isPromise(initResult)) {
                      asyncInitPromises.push(initResult);
                  }
              }
          }
          Promise.all(asyncInitPromises)
              .then(function () {
              complete();
          })
              .catch(function (e) {
              _this.reject(e);
          });
          if (asyncInitPromises.length === 0) {
              complete();
          }
          this.initialized = true;
      };
      ApplicationInitStatus = __decorate([
          Injectable(),
          __param(0, Inject(APP_INITIALIZER)), __param(0, Optional()),
          __metadata("design:paramtypes", [Array])
      ], ApplicationInitStatus);
      return ApplicationInitStatus;
  }());

  /**
   * @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
   */
  /**
   * A DI Token representing a unique string id assigned to the application by Angular and used
   * primarily for prefixing application attributes and CSS styles when
   * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
   *
   * If you need to avoid randomly generated value to be used as an application id, you can provide
   * a custom value via a DI provider <!-- TODO: provider --> configuring the root {@link Injector}
   * using this token.
   * @publicApi
   */
  var APP_ID = new InjectionToken('AppId');
  function _appIdRandomProviderFactory() {
      return "" + _randomChar() + _randomChar() + _randomChar();
  }
  /**
   * Providers that will generate a random APP_ID_TOKEN.
   * @publicApi
   */
  var APP_ID_RANDOM_PROVIDER = {
      provide: APP_ID,
      useFactory: _appIdRandomProviderFactory,
      deps: [],
  };
  function _randomChar() {
      return String.fromCharCode(97 + Math.floor(Math.random() * 25));
  }
  /**
   * A function that will be executed when a platform is initialized.
   * @publicApi
   */
  var PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer');
  /**
   * A token that indicates an opaque platform id.
   * @publicApi
   */
  var PLATFORM_ID = new InjectionToken('Platform ID');
  /**
   * All callbacks provided via this token will be called for every component that is bootstrapped.
   * Signature of the callback:
   *
   * `(componentRef: ComponentRef) => void`.
   *
   * @publicApi
   */
  var APP_BOOTSTRAP_LISTENER = new InjectionToken('appBootstrapListener');
  /**
   * A token which indicates the root directory of the application
   * @publicApi
   */
  var PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');

  /**
   * @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
   */
  var Console = /** @class */ (function () {
      function Console() {
      }
      Console.prototype.log = function (message) {
          // tslint:disable-next-line:no-console
          console.log(message);
      };
      // Note: for reporting errors use `DOM.logError()` as it is platform specific
      Console.prototype.warn = function (message) {
          // tslint:disable-next-line:no-console
          console.warn(message);
      };
      Console = __decorate([
          Injectable()
      ], Console);
      return Console;
  }());

  /**
   * @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
   */
  /**
   * 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#setting-up-locale) 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
   */
  var LOCALE_ID$1 = new InjectionToken('LocaleId');
  /**
   * 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#setting-up-locale) 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
   */
  var DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode');
  /**
   * 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#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
   */
  var 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#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
   */
  var TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat');
  (function (MissingTranslationStrategy) {
      MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
      MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
      MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
  })(exports.MissingTranslationStrategy || (exports.MissingTranslationStrategy = {}));

  /**
   * @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
   */
  var SWITCH_IVY_ENABLED__POST_R3__ = true;
  var SWITCH_IVY_ENABLED__PRE_R3__ = false;
  var ivyEnabled = SWITCH_IVY_ENABLED__PRE_R3__;

  /**
   * @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
   */
  /**
   * Combination of NgModuleFactory and ComponentFactorys.
   *
   * @publicApi
   */
  var ModuleWithComponentFactories = /** @class */ (function () {
      function ModuleWithComponentFactories(ngModuleFactory, componentFactories) {
          this.ngModuleFactory = ngModuleFactory;
          this.componentFactories = componentFactories;
      }
      return ModuleWithComponentFactories;
  }());
  function _throwError() {
      throw new Error("Runtime compiler is not loaded");
  }
  var Compiler_compileModuleSync__PRE_R3__ = _throwError;
  var Compiler_compileModuleSync__POST_R3__ = function (moduleType) {
      return new NgModuleFactory$1(moduleType);
  };
  var Compiler_compileModuleSync = Compiler_compileModuleSync__PRE_R3__;
  var Compiler_compileModuleAsync__PRE_R3__ = _throwError;
  var Compiler_compileModuleAsync__POST_R3__ = function (moduleType) {
      return Promise.resolve(Compiler_compileModuleSync__POST_R3__(moduleType));
  };
  var Compiler_compileModuleAsync = Compiler_compileModuleAsync__PRE_R3__;
  var Compiler_compileModuleAndAllComponentsSync__PRE_R3__ = _throwError;
  var Compiler_compileModuleAndAllComponentsSync__POST_R3__ = function (moduleType) {
      var ngModuleFactory = Compiler_compileModuleSync__POST_R3__(moduleType);
      var moduleDef = getNgModuleDef(moduleType);
      var componentFactories = maybeUnwrapFn(moduleDef.declarations)
          .reduce(function (factories, declaration) {
          var componentDef = getComponentDef(declaration);
          componentDef && factories.push(new ComponentFactory$1(componentDef));
          return factories;
      }, []);
      return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
  };
  var Compiler_compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync__PRE_R3__;
  var Compiler_compileModuleAndAllComponentsAsync__PRE_R3__ = _throwError;
  var Compiler_compileModuleAndAllComponentsAsync__POST_R3__ = function (moduleType) {
      return Promise.resolve(Compiler_compileModuleAndAllComponentsSync__POST_R3__(moduleType));
  };
  var Compiler_compileModuleAndAllComponentsAsync = Compiler_compileModuleAndAllComponentsAsync__PRE_R3__;
  /**
   * 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
   */
  var Compiler = /** @class */ (function () {
      function Compiler() {
          /**
           * Compiles the given NgModule and all of its components. All templates of the components listed
           * in `entryComponents` have to be inlined.
           */
          this.compileModuleSync = Compiler_compileModuleSync;
          /**
           * Compiles the given NgModule and all of its components
           */
          this.compileModuleAsync = Compiler_compileModuleAsync;
          /**
           * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
           */
          this.compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync;
          /**
           * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
           */
          this.compileModuleAndAllComponentsAsync = Compiler_compileModuleAndAllComponentsAsync;
      }
      /**
       * Clears all caches.
       */
      Compiler.prototype.clearCache = function () { };
      /**
       * Clears the cache for the given component/ngModule.
       */
      Compiler.prototype.clearCacheFor = function (type) { };
      /**
       * Returns the id for a given NgModule, if one is defined and known to the compiler.
       */
      Compiler.prototype.getModuleId = function (moduleType) {
          return undefined;
      };
      Compiler = __decorate([
          Injectable()
      ], Compiler);
      return Compiler;
  }());
  /**
   * Token to provide CompilerOptions in the platform injector.
   *
   * @publicApi
   */
  var COMPILER_OPTIONS = new InjectionToken('compilerOptions');
  /**
   * A factory for creating a Compiler
   *
   * @publicApi
   */
  var CompilerFactory = /** @class */ (function () {
      function CompilerFactory() {
      }
      return CompilerFactory;
  }());

  /**
   * @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
   */
  var promise = (function () { return Promise.resolve(0); })();
  function scheduleMicroTask(fn) {
      if (typeof Zone === 'undefined') {
          // use promise to schedule microTask instead of use Zone
          promise.then(function () {
              fn && fn.apply(null, null);
          });
      }
      else {
          Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
      }
  }

  /**
   * @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
   */
  function getNativeRequestAnimationFrame() {
      var nativeRequestAnimationFrame = _global['requestAnimationFrame'];
      var nativeCancelAnimationFrame = _global['cancelAnimationFrame'];
      if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
          // use unpatched version of requestAnimationFrame(native delegate) if possible
          // to avoid another Change detection
          var unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')];
          if (unpatchedRequestAnimationFrame) {
              nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
          }
          var unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')];
          if (unpatchedCancelAnimationFrame) {
              nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
          }
      }
      return { nativeRequestAnimationFrame: nativeRequestAnimationFrame, nativeCancelAnimationFrame: nativeCancelAnimationFrame };
  }

  /**
   * @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
   */
  /**
   * 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
   */
  var NgZone = /** @class */ (function () {
      function NgZone(_a) {
          var _b = _a.enableLongStackTrace, enableLongStackTrace = _b === void 0 ? false : _b, _c = _a.shouldCoalesceEventChangeDetection, shouldCoalesceEventChangeDetection = _c === void 0 ? false : _c;
          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 Error("In this configuration Angular requires Zone.js");
          }
          Zone.assertZonePatched();
          var self = this;
          self._nesting = 0;
          self._outer = self._inner = Zone.current;
          if (Zone['wtfZoneSpec']) {
              self._inner = self._inner.fork(Zone['wtfZoneSpec']);
          }
          if (Zone['TaskTrackingZoneSpec']) {
              self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']);
          }
          if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
              self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
          }
          self.shouldCoalesceEventChangeDetection = shouldCoalesceEventChangeDetection;
          self.lastRequestAnimationFrameId = -1;
          self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
          forkInnerZoneWithAngularBehavior(self);
      }
      NgZone.isInAngularZone = function () {
          return Zone.current.get('isAngularZone') === true;
      };
      NgZone.assertInAngularZone = function () {
          if (!NgZone.isInAngularZone()) {
              throw new Error('Expected to be in Angular Zone, but it is not!');
          }
      };
      NgZone.assertNotInAngularZone = function () {
          if (NgZone.isInAngularZone()) {
              throw new Error('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`.
       */
      NgZone.prototype.run = function (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`.
       */
      NgZone.prototype.runTask = function (fn, applyThis, applyArgs, name) {
          var zone = this._inner;
          var task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop$1, noop$1);
          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.
       */
      NgZone.prototype.runGuarded = function (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.
       */
      NgZone.prototype.runOutsideAngular = function (fn) {
          return this._outer.run(fn);
      };
      return NgZone;
  }());
  function noop$1() { }
  var EMPTY_PAYLOAD = {};
  function checkStable(zone) {
      if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
          try {
              zone._nesting++;
              zone.onMicrotaskEmpty.emit(null);
          }
          finally {
              zone._nesting--;
              if (!zone.hasPendingMicrotasks) {
                  try {
                      zone.runOutsideAngular(function () { return zone.onStable.emit(null); });
                  }
                  finally {
                      zone.isStable = true;
                  }
              }
          }
      }
  }
  function delayChangeDetectionForEvents(zone) {
      if (zone.lastRequestAnimationFrameId !== -1) {
          return;
      }
      zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, function () {
          zone.lastRequestAnimationFrameId = -1;
          updateMicroTaskStatus(zone);
          checkStable(zone);
      });
      updateMicroTaskStatus(zone);
  }
  function forkInnerZoneWithAngularBehavior(zone) {
      var delayChangeDetectionForEventsDelegate = function () {
          delayChangeDetectionForEvents(zone);
      };
      var maybeDelayChangeDetection = !!zone.shouldCoalesceEventChangeDetection &&
          zone.nativeRequestAnimationFrame && delayChangeDetectionForEventsDelegate;
      zone._inner = zone._inner.fork({
          name: 'angular',
          properties: { 'isAngularZone': true, 'maybeDelayChangeDetection': maybeDelayChangeDetection },
          onInvokeTask: function (delegate, current, target, task, applyThis, applyArgs) {
              try {
                  onEnter(zone);
                  return delegate.invokeTask(target, task, applyThis, applyArgs);
              }
              finally {
                  if (maybeDelayChangeDetection && task.type === 'eventTask') {
                      maybeDelayChangeDetection();
                  }
                  onLeave(zone);
              }
          },
          onInvoke: function (delegate, current, target, callback, applyThis, applyArgs, source) {
              try {
                  onEnter(zone);
                  return delegate.invoke(target, callback, applyThis, applyArgs, source);
              }
              finally {
                  onLeave(zone);
              }
          },
          onHasTask: function (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: function (delegate, current, target, error) {
              delegate.handleError(target, error);
              zone.runOutsideAngular(function () { return zone.onError.emit(error); });
              return false;
          }
      });
  }
  function updateMicroTaskStatus(zone) {
      if (zone._hasPendingMicrotasks ||
          (zone.shouldCoalesceEventChangeDetection && 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.
   */
  var NoopNgZone = /** @class */ (function () {
      function NoopNgZone() {
          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();
      }
      NoopNgZone.prototype.run = function (fn, applyThis, applyArgs) {
          return fn.apply(applyThis, applyArgs);
      };
      NoopNgZone.prototype.runGuarded = function (fn, applyThis, applyArgs) {
          return fn.apply(applyThis, applyArgs);
      };
      NoopNgZone.prototype.runOutsideAngular = function (fn) {
          return fn();
      };
      NoopNgZone.prototype.runTask = function (fn, applyThis, applyArgs, name) {
          return fn.apply(applyThis, applyArgs);
      };
      return NoopNgZone;
  }());

  /**
   * @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
   */
  /**
   * The Testability service provides testing hooks that can be accessed from
   * the browser and by services such as Protractor. Each bootstrapped Angular
   * application on the page will have an instance of Testability.
   * @publicApi
   */
  var Testability = /** @class */ (function () {
      function Testability(_ngZone) {
          var _this = this;
          this._ngZone = _ngZone;
          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;
          this._watchAngularEvents();
          _ngZone.run(function () {
              _this.taskTrackingZone =
                  typeof Zone == 'undefined' ? null : Zone.current.get('TaskTrackingZone');
          });
      }
      Testability.prototype._watchAngularEvents = function () {
          var _this = this;
          this._ngZone.onUnstable.subscribe({
              next: function () {
                  _this._didWork = true;
                  _this._isZoneStable = false;
              }
          });
          this._ngZone.runOutsideAngular(function () {
              _this._ngZone.onStable.subscribe({
                  next: function () {
                      NgZone.assertNotInAngularZone();
                      scheduleMicroTask(function () {
                          _this._isZoneStable = true;
                          _this._runCallbacksIfReady();
                      });
                  }
              });
          });
      };
      /**
       * Increases the number of pending request
       * @deprecated pending requests are now tracked with zones.
       */
      Testability.prototype.increasePendingRequestCount = function () {
          this._pendingCount += 1;
          this._didWork = true;
          return this._pendingCount;
      };
      /**
       * Decreases the number of pending request
       * @deprecated pending requests are now tracked with zones
       */
      Testability.prototype.decreasePendingRequestCount = function () {
          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
       */
      Testability.prototype.isStable = function () {
          return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks;
      };
      Testability.prototype._runCallbacksIfReady = function () {
          var _this = this;
          if (this.isStable()) {
              // Schedules the call backs in a new frame so that it is always async.
              scheduleMicroTask(function () {
                  while (_this._callbacks.length !== 0) {
                      var cb = _this._callbacks.pop();
                      clearTimeout(cb.timeoutId);
                      cb.doneCb(_this._didWork);
                  }
                  _this._didWork = false;
              });
          }
          else {
              // Still not stable, send updates.
              var pending_1 = this.getPendingTasks();
              this._callbacks = this._callbacks.filter(function (cb) {
                  if (cb.updateCb && cb.updateCb(pending_1)) {
                      clearTimeout(cb.timeoutId);
                      return false;
                  }
                  return true;
              });
              this._didWork = true;
          }
      };
      Testability.prototype.getPendingTasks = function () {
          if (!this.taskTrackingZone) {
              return [];
          }
          // Copy the tasks data so that we don't leak tasks.
          return this.taskTrackingZone.macroTasks.map(function (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
              };
          });
      };
      Testability.prototype.addCallback = function (cb, timeout, updateCb) {
          var _this = this;
          var timeoutId = -1;
          if (timeout && timeout > 0) {
              timeoutId = setTimeout(function () {
                  _this._callbacks = _this._callbacks.filter(function (cb) { return 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.
       */
      Testability.prototype.whenStable = function (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/dist/task-tracking.js" 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
       */
      Testability.prototype.getPendingRequestCount = function () {
          return this._pendingCount;
      };
      /**
       * Find providers by name
       * @param using The root element to search from
       * @param provider The name of binding variable
       * @param exactMatch Whether using exactMatch
       */
      Testability.prototype.findProviders = function (using, provider, exactMatch) {
          // TODO(juliemr): implement.
          return [];
      };
      Testability = __decorate([
          Injectable(),
          __metadata("design:paramtypes", [NgZone])
      ], Testability);
      return Testability;
  }());
  /**
   * A global registry of {@link Testability} instances for specific elements.
   * @publicApi
   */
  var TestabilityRegistry = /** @class */ (function () {
      function TestabilityRegistry() {
          /** @internal */
          this._applications = new Map();
          _testabilityGetter.addToWindow(this);
      }
      /**
       * Registers an application with a testability hook so that it can be tracked
       * @param token token of application, root element
       * @param testability Testability hook
       */
      TestabilityRegistry.prototype.registerApplication = function (token, testability) {
          this._applications.set(token, testability);
      };
      /**
       * Unregisters an application.
       * @param token token of application, root element
       */
      TestabilityRegistry.prototype.unregisterApplication = function (token) {
          this._applications.delete(token);
      };
      /**
       * Unregisters all applications
       */
      TestabilityRegistry.prototype.unregisterAllApplications = function () {
          this._applications.clear();
      };
      /**
       * Get a testability hook associated with the application
       * @param elem root element
       */
      TestabilityRegistry.prototype.getTestability = function (elem) {
          return this._applications.get(elem) || null;
      };
      /**
       * Get all registered testabilities
       */
      TestabilityRegistry.prototype.getAllTestabilities = function () {
          return Array.from(this._applications.values());
      };
      /**
       * Get all registered applications(root elements)
       */
      TestabilityRegistry.prototype.getAllRootElements = function () {
          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
       */
      TestabilityRegistry.prototype.findTestabilityInTree = function (elem, findInAncestors) {
          if (findInAncestors === void 0) { findInAncestors = true; }
          return _testabilityGetter.findTestabilityInTree(this, elem, findInAncestors);
      };
      TestabilityRegistry = __decorate([
          Injectable(),
          __metadata("design:paramtypes", [])
      ], TestabilityRegistry);
      return TestabilityRegistry;
  }());
  var _NoopGetTestability = /** @class */ (function () {
      function _NoopGetTestability() {
      }
      _NoopGetTestability.prototype.addToWindow = function (registry) { };
      _NoopGetTestability.prototype.findTestabilityInTree = function (registry, elem, findInAncestors) {
          return null;
      };
      return _NoopGetTestability;
  }());
  /**
   * Set the {@link GetTestability} implementation used by the Angular testing framework.
   * @publicApi
   */
  function setTestabilityGetter(getter) {
      _testabilityGetter = getter;
  }
  var _testabilityGetter = new _NoopGetTestability();

  /**
   * @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
   */
  var _platform;
  var compileNgModuleFactory = compileNgModuleFactory__PRE_R3__;
  function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
      var compilerFactory = injector.get(CompilerFactory);
      var compiler = compilerFactory.createCompiler([options]);
      return compiler.compileModuleAsync(moduleType);
  }
  function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
      ngDevMode && assertNgModuleType(moduleType);
      var compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options);
      if (typeof ngJitMode === 'undefined' || ngJitMode) {
          // 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(function (options) { return options.defaultEncapsulation; })),
              preserveWhitespaces: _lastDefined(compilerOptions.map(function (options) { return options.preserveWhitespaces; })),
          });
      }
      var moduleFactory = new NgModuleFactory$1(moduleType);
      if (isComponentResourceResolutionQueueEmpty()) {
          return Promise.resolve(moduleFactory);
      }
      var compilerProviders = _mergeArrays(compilerOptions.map(function (o) { return 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);
      }
      var compiler = getCompilerFacade();
      var compilerInjector = Injector.create({ providers: compilerProviders });
      var 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(function (url) { return Promise.resolve(resourceLoader.get(url)); })
          .then(function () { return moduleFactory; });
  }
  // the `window.ng` global utilities are only available in non-VE versions of
  // Angular. The function switch below will make sure that the code is not
  // included into Angular when PRE mode is active.
  function publishDefaultGlobalUtils__PRE_R3__() { }
  function publishDefaultGlobalUtils__POST_R3__() {
      ngDevMode && publishDefaultGlobalUtils();
  }
  var publishDefaultGlobalUtils$1 = publishDefaultGlobalUtils__PRE_R3__;
  var isBoundToModule = isBoundToModule__PRE_R3__;
  function isBoundToModule__PRE_R3__(cf) {
      return cf instanceof ComponentFactoryBoundToModule;
  }
  function isBoundToModule__POST_R3__(cf) {
      return cf.isBoundToModule;
  }
  var ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken');
  /**
   * A token for third-party components that can register themselves with NgProbe.
   *
   * @publicApi
   */
  var NgProbeToken = /** @class */ (function () {
      function NgProbeToken(name, token) {
          this.name = name;
          this.token = token;
      }
      return NgProbeToken;
  }());
  /**
   * Creates a platform.
   * Platforms have to be eagerly created via this function.
   *
   * @publicApi
   */
  function createPlatform(injector) {
      if (_platform && !_platform.destroyed &&
          !_platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
          throw new Error('There can be only one platform. Destroy the previous one to create a new one.');
      }
      publishDefaultGlobalUtils$1();
      _platform = injector.get(PlatformRef);
      var inits = injector.get(PLATFORM_INITIALIZER, null);
      if (inits)
          inits.forEach(function (init) { return init(); });
      return _platform;
  }
  /**
   * Creates a factory for a platform
   *
   * @publicApi
   */
  function createPlatformFactory(parentPlatformFactory, name, providers) {
      if (providers === void 0) { providers = []; }
      var desc = "Platform: " + name;
      var marker = new InjectionToken(desc);
      return function (extraProviders) {
          if (extraProviders === void 0) { extraProviders = []; }
          var platform = getPlatform();
          if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
              if (parentPlatformFactory) {
                  parentPlatformFactory(providers.concat(extraProviders).concat({ provide: marker, useValue: true }));
              }
              else {
                  var injectedProviders = providers.concat(extraProviders).concat({ provide: marker, useValue: true }, {
                      provide: INJECTOR_SCOPE,
                      useValue: 'platform'
                  });
                  createPlatform(Injector.create({ providers: injectedProviders, name: desc }));
              }
          }
          return assertPlatform(marker);
      };
  }
  /**
   * Checks that there currently is a platform which contains the given token as a provider.
   *
   * @publicApi
   */
  function assertPlatform(requiredToken) {
      var platform = getPlatform();
      if (!platform) {
          throw new Error('No platform exists!');
      }
      if (!platform.injector.get(requiredToken, null)) {
          throw new Error('A platform with a different configuration has been created. Please destroy it first.');
      }
      return platform;
  }
  /**
   * Destroy the existing platform.
   *
   * @publicApi
   */
  function destroyPlatform() {
      if (_platform && !_platform.destroyed) {
          _platform.destroy();
      }
  }
  /**
   * Returns the current platform.
   *
   * @publicApi
   */
  function getPlatform() {
      return _platform && !_platform.destroyed ? _platform : null;
  }
  /**
   * The Angular platform is the entry point for Angular on a web page. Each page
   * has exactly one platform, and 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 via a platform factory
   * (e.g. {@link platformBrowser}), or explicitly by calling the {@link createPlatform} function.
   *
   * @publicApi
   */
  var PlatformRef = /** @class */ (function () {
      /** @internal */
      function PlatformRef(_injector) {
          this._injector = _injector;
          this._modules = [];
          this._destroyListeners = [];
          this._destroyed = false;
      }
      /**
       * Creates an instance of an `@NgModule` for the given platform
       * for offline compilation.
       *
       * @usageNotes
       * ### Simple Example
       *
       * ```typescript
       * my_module.ts:
       *
       * @NgModule({
       *   imports: [BrowserModule]
       * })
       * class MyModule {}
       *
       * main.ts:
       * import {MyModuleNgFactory} from './my_module.ngfactory';
       * import {platformBrowser} from '@angular/platform-browser';
       *
       * let moduleRef = platformBrowser().bootstrapModuleFactory(MyModuleNgFactory);
       * ```
       */
      PlatformRef.prototype.bootstrapModuleFactory = function (moduleFactory, options) {
          var _this = this;
          // 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.
          var ngZoneOption = options ? options.ngZone : undefined;
          var ngZoneEventCoalescing = (options && options.ngZoneEventCoalescing) || false;
          var ngZone = getNgZone(ngZoneOption, ngZoneEventCoalescing);
          var providers = [{ provide: NgZone, useValue: ngZone }];
          // Attention: Don't use ApplicationRef.run here,
          // as we want to be sure that all possible constructor calls are inside `ngZone.run`!
          return ngZone.run(function () {
              var ngZoneInjector = Injector.create({ providers: providers, parent: _this.injector, name: moduleFactory.moduleType.name });
              var moduleRef = moduleFactory.create(ngZoneInjector);
              var exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
              if (!exceptionHandler) {
                  throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?');
              }
              moduleRef.onDestroy(function () { return remove(_this._modules, moduleRef); });
              ngZone.runOutsideAngular(function () { return ngZone.onError.subscribe({
                  next: function (error) {
                      exceptionHandler.handleError(error);
                  }
              }); });
              return _callAndReportToErrorHandler(exceptionHandler, ngZone, function () {
                  var initStatus = moduleRef.injector.get(ApplicationInitStatus);
                  initStatus.runInitializers();
                  return initStatus.donePromise.then(function () {
                      if (ivyEnabled) {
                          // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
                          var localeId = moduleRef.injector.get(LOCALE_ID$1, DEFAULT_LOCALE_ID);
                          setLocaleId(localeId || DEFAULT_LOCALE_ID);
                      }
                      _this._moduleDoBootstrap(moduleRef);
                      return moduleRef;
                  });
              });
          });
      };
      /**
       * Creates an instance of an `@NgModule` for a given platform using the given runtime compiler.
       *
       * @usageNotes
       * ### Simple Example
       *
       * ```typescript
       * @NgModule({
       *   imports: [BrowserModule]
       * })
       * class MyModule {}
       *
       * let moduleRef = platformBrowser().bootstrapModule(MyModule);
       * ```
       *
       */
      PlatformRef.prototype.bootstrapModule = function (moduleType, compilerOptions) {
          var _this = this;
          if (compilerOptions === void 0) { compilerOptions = []; }
          var options = optionsReducer({}, compilerOptions);
          return compileNgModuleFactory(this.injector, options, moduleType)
              .then(function (moduleFactory) { return _this.bootstrapModuleFactory(moduleFactory, options); });
      };
      PlatformRef.prototype._moduleDoBootstrap = function (moduleRef) {
          var appRef = moduleRef.injector.get(ApplicationRef);
          if (moduleRef._bootstrapComponents.length > 0) {
              moduleRef._bootstrapComponents.forEach(function (f) { return appRef.bootstrap(f); });
          }
          else if (moduleRef.instance.ngDoBootstrap) {
              moduleRef.instance.ngDoBootstrap(appRef);
          }
          else {
              throw new Error("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);
      };
      /**
       * Register a listener to be called when the platform is disposed.
       */
      PlatformRef.prototype.onDestroy = function (callback) {
          this._destroyListeners.push(callback);
      };
      Object.defineProperty(PlatformRef.prototype, "injector", {
          /**
           * Retrieve the platform {@link Injector}, which is the parent injector for
           * every Angular application on the page and provides singleton providers.
           */
          get: function () {
              return this._injector;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * Destroy the Angular platform and all Angular applications on the page.
       */
      PlatformRef.prototype.destroy = function () {
          if (this._destroyed) {
              throw new Error('The platform has already been destroyed!');
          }
          this._modules.slice().forEach(function (module) { return module.destroy(); });
          this._destroyListeners.forEach(function (listener) { return listener(); });
          this._destroyed = true;
      };
      Object.defineProperty(PlatformRef.prototype, "destroyed", {
          get: function () {
              return this._destroyed;
          },
          enumerable: true,
          configurable: true
      });
      PlatformRef = __decorate([
          Injectable(),
          __metadata("design:paramtypes", [Injector])
      ], PlatformRef);
      return PlatformRef;
  }());
  function getNgZone(ngZoneOption, ngZoneEventCoalescing) {
      var ngZone;
      if (ngZoneOption === 'noop') {
          ngZone = new NoopNgZone();
      }
      else {
          ngZone = (ngZoneOption === 'zone.js' ? undefined : ngZoneOption) || new NgZone({
              enableLongStackTrace: isDevMode(),
              shouldCoalesceEventChangeDetection: ngZoneEventCoalescing
          });
      }
      return ngZone;
  }
  function _callAndReportToErrorHandler(errorHandler, ngZone, callback) {
      try {
          var result = callback();
          if (isPromise(result)) {
              return result.catch(function (e) {
                  ngZone.runOutsideAngular(function () { return errorHandler.handleError(e); });
                  // rethrow as the exception handler might not do it
                  throw e;
              });
          }
          return result;
      }
      catch (e) {
          ngZone.runOutsideAngular(function () { return 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 = __assign(__assign({}, 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
   */
  var ApplicationRef = /** @class */ (function () {
      /** @internal */
      function ApplicationRef(_zone, _console, _injector, _exceptionHandler, _componentFactoryResolver, _initStatus) {
          var _this = this;
          this._zone = _zone;
          this._console = _console;
          this._injector = _injector;
          this._exceptionHandler = _exceptionHandler;
          this._componentFactoryResolver = _componentFactoryResolver;
          this._initStatus = _initStatus;
          /** @internal */
          this._bootstrapListeners = [];
          this._views = [];
          this._runningTick = false;
          this._enforceNoNewChanges = false;
          this._stable = true;
          /**
           * 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._enforceNoNewChanges = isDevMode();
          this._zone.onMicrotaskEmpty.subscribe({
              next: function () {
                  _this._zone.run(function () {
                      _this.tick();
                  });
              }
          });
          var isCurrentlyStable = new rxjs.Observable(function (observer) {
              _this._stable = _this._zone.isStable && !_this._zone.hasPendingMacrotasks &&
                  !_this._zone.hasPendingMicrotasks;
              _this._zone.runOutsideAngular(function () {
                  observer.next(_this._stable);
                  observer.complete();
              });
          });
          var isStable = new rxjs.Observable(function (observer) {
              // Create the subscription to onStable outside the Angular Zone so that
              // the callback is run outside the Angular Zone.
              var stableSub;
              _this._zone.runOutsideAngular(function () {
                  stableSub = _this._zone.onStable.subscribe(function () {
                      NgZone.assertNotInAngularZone();
                      // Check whether there are no pending macro/micro tasks in the next tick
                      // to allow for NgZone to update the state.
                      scheduleMicroTask(function () {
                          if (!_this._stable && !_this._zone.hasPendingMacrotasks &&
                              !_this._zone.hasPendingMicrotasks) {
                              _this._stable = true;
                              observer.next(true);
                          }
                      });
                  });
              });
              var unstableSub = _this._zone.onUnstable.subscribe(function () {
                  NgZone.assertInAngularZone();
                  if (_this._stable) {
                      _this._stable = false;
                      _this._zone.runOutsideAngular(function () {
                          observer.next(false);
                      });
                  }
              });
              return function () {
                  stableSub.unsubscribe();
                  unstableSub.unsubscribe();
              };
          });
          this.isStable =
              rxjs.merge(isCurrentlyStable, isStable.pipe(operators.share()));
      }
      /**
       * Bootstrap a new component at the root level of the application.
       *
       * @usageNotes
       * ### Bootstrap process
       *
       * When bootstrapping a new root component into an application, Angular mounts the
       * specified application component onto DOM elements identified by the componentType's
       * selector and kicks off automatic change detection to finish initializing the component.
       *
       * Optionally, a component can be mounted onto a DOM element that does not match the
       * componentType's selector.
       *
       * ### Example
       * {@example core/ts/platform/platform.ts region='longform'}
       */
      ApplicationRef.prototype.bootstrap = function (componentOrFactory, rootSelectorOrNode) {
          var _this = this;
          if (!this._initStatus.done) {
              throw new Error('Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.');
          }
          var componentFactory;
          if (componentOrFactory instanceof ComponentFactory) {
              componentFactory = componentOrFactory;
          }
          else {
              componentFactory =
                  this._componentFactoryResolver.resolveComponentFactory(componentOrFactory);
          }
          this.componentTypes.push(componentFactory.componentType);
          // Create a factory associated with the current module if it's not bound to some other
          var ngModule = isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef);
          var selectorOrNode = rootSelectorOrNode || componentFactory.selector;
          var compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
          compRef.onDestroy(function () {
              _this._unloadComponent(compRef);
          });
          var testability = compRef.injector.get(Testability, null);
          if (testability) {
              compRef.injector.get(TestabilityRegistry)
                  .registerApplication(compRef.location.nativeElement, testability);
          }
          this._loadComponent(compRef);
          if (isDevMode()) {
              this._console.log("Angular is running in the development mode. Call enableProdMode() to enable the 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.
       */
      ApplicationRef.prototype.tick = function () {
          var e_1, _a, e_2, _b;
          var _this = this;
          if (this._runningTick) {
              throw new Error('ApplicationRef.tick is called recursively');
          }
          try {
              this._runningTick = true;
              try {
                  for (var _c = __values(this._views), _d = _c.next(); !_d.done; _d = _c.next()) {
                      var view = _d.value;
                      view.detectChanges();
                  }
              }
              catch (e_1_1) { e_1 = { error: e_1_1 }; }
              finally {
                  try {
                      if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
                  }
                  finally { if (e_1) throw e_1.error; }
              }
              if (this._enforceNoNewChanges) {
                  try {
                      for (var _e = __values(this._views), _f = _e.next(); !_f.done; _f = _e.next()) {
                          var view = _f.value;
                          view.checkNoChanges();
                      }
                  }
                  catch (e_2_1) { e_2 = { error: e_2_1 }; }
                  finally {
                      try {
                          if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
                      }
                      finally { if (e_2) throw e_2.error; }
                  }
              }
          }
          catch (e) {
              // Attention: Don't rethrow as it could cancel subscriptions to Observables!
              this._zone.runOutsideAngular(function () { return _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.
       */
      ApplicationRef.prototype.attachView = function (viewRef) {
          var view = viewRef;
          this._views.push(view);
          view.attachToAppRef(this);
      };
      /**
       * Detaches a view from dirty checking again.
       */
      ApplicationRef.prototype.detachView = function (viewRef) {
          var view = viewRef;
          remove(this._views, view);
          view.detachFromAppRef();
      };
      ApplicationRef.prototype._loadComponent = function (componentRef) {
          this.attachView(componentRef.hostView);
          this.tick();
          this.components.push(componentRef);
          // Get the listeners lazily to prevent DI cycles.
          var listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners);
          listeners.forEach(function (listener) { return listener(componentRef); });
      };
      ApplicationRef.prototype._unloadComponent = function (componentRef) {
          this.detachView(componentRef.hostView);
          remove(this.components, componentRef);
      };
      /** @internal */
      ApplicationRef.prototype.ngOnDestroy = function () {
          // TODO(alxhub): Dispose of the NgZone.
          this._views.slice().forEach(function (view) { return view.destroy(); });
      };
      Object.defineProperty(ApplicationRef.prototype, "viewCount", {
          /**
           * Returns the number of attached views.
           */
          get: function () {
              return this._views.length;
          },
          enumerable: true,
          configurable: true
      });
      ApplicationRef = __decorate([
          Injectable(),
          __metadata("design:paramtypes", [NgZone, Console, Injector,
              ErrorHandler,
              ComponentFactoryResolver,
              ApplicationInitStatus])
      ], ApplicationRef);
      return ApplicationRef;
  }());
  function remove(list, el) {
      var index = list.indexOf(el);
      if (index > -1) {
          list.splice(index, 1);
      }
  }
  function _lastDefined(args) {
      for (var i = args.length - 1; i >= 0; i--) {
          if (args[i] !== undefined) {
              return args[i];
          }
      }
      return undefined;
  }
  function _mergeArrays(parts) {
      var result = [];
      parts.forEach(function (part) { return part && result.push.apply(result, __spread(part)); });
      return result;
  }

  /**
   * @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
   */

  /**
   * @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
   */

  /**
   * @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
   */
  /**
   * Used to load ng module factories.
   *
   * @publicApi
   * @deprecated the `string` form of `loadChildren` is deprecated, and `NgModuleFactoryLoader` is
   * part of its implementation. See `LoadChildren` for more details.
   */
  var NgModuleFactoryLoader = /** @class */ (function () {
      function NgModuleFactoryLoader() {
      }
      return NgModuleFactoryLoader;
  }());
  function getModuleFactory__PRE_R3__(id) {
      var factory = getRegisteredNgModuleType(id);
      if (!factory)
          throw noModuleError(id);
      return factory;
  }
  function getModuleFactory__POST_R3__(id) {
      var type = getRegisteredNgModuleType(id);
      if (!type)
          throw noModuleError(id);
      return new NgModuleFactory$1(type);
  }
  /**
   * Returns the NgModuleFactory with the given id, if it exists and has been loaded.
   * Factories for modules that do not specify an `id` cannot be retrieved. Throws if the module
   * cannot be found.
   * @publicApi
   */
  var getModuleFactory = getModuleFactory__PRE_R3__;
  function noModuleError(id) {
      return new Error("No module with ID " + id + " loaded");
  }

  /**
   * @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
   */
  var _SEPARATOR = '#';
  var FACTORY_CLASS_SUFFIX = 'NgFactory';
  /**
   * Configuration for SystemJsNgModuleLoader.
   * token.
   *
   * @publicApi
   * @deprecated the `string` form of `loadChildren` is deprecated, and `SystemJsNgModuleLoaderConfig`
   * is part of its implementation. See `LoadChildren` for more details.
   */
  var SystemJsNgModuleLoaderConfig = /** @class */ (function () {
      function SystemJsNgModuleLoaderConfig() {
      }
      return SystemJsNgModuleLoaderConfig;
  }());
  var DEFAULT_CONFIG = {
      factoryPathPrefix: '',
      factoryPathSuffix: '.ngfactory',
  };
  /**
   * NgModuleFactoryLoader that uses SystemJS to load NgModuleFactory
   * @publicApi
   * @deprecated the `string` form of `loadChildren` is deprecated, and `SystemJsNgModuleLoader` is
   * part of its implementation. See `LoadChildren` for more details.
   */
  var SystemJsNgModuleLoader = /** @class */ (function () {
      function SystemJsNgModuleLoader(_compiler, config) {
          this._compiler = _compiler;
          this._config = config || DEFAULT_CONFIG;
      }
      SystemJsNgModuleLoader.prototype.load = function (path) {
          var legacyOfflineMode = !ivyEnabled && this._compiler instanceof Compiler;
          return legacyOfflineMode ? this.loadFactory(path) : this.loadAndCompile(path);
      };
      SystemJsNgModuleLoader.prototype.loadAndCompile = function (path) {
          var _this = this;
          var _a = __read(path.split(_SEPARATOR), 2), module = _a[0], exportName = _a[1];
          if (exportName === undefined) {
              exportName = 'default';
          }
          return System.import(module)
              .then(function (module) { return module[exportName]; })
              .then(function (type) { return checkNotEmpty(type, module, exportName); })
              .then(function (type) { return _this._compiler.compileModuleAsync(type); });
      };
      SystemJsNgModuleLoader.prototype.loadFactory = function (path) {
          var _a = __read(path.split(_SEPARATOR), 2), module = _a[0], exportName = _a[1];
          var factoryClassSuffix = FACTORY_CLASS_SUFFIX;
          if (exportName === undefined) {
              exportName = 'default';
              factoryClassSuffix = '';
          }
          return System.import(this._config.factoryPathPrefix + module + this._config.factoryPathSuffix)
              .then(function (module) { return module[exportName + factoryClassSuffix]; })
              .then(function (factory) { return checkNotEmpty(factory, module, exportName); });
      };
      SystemJsNgModuleLoader = __decorate([
          Injectable(),
          __param(1, Optional()),
          __metadata("design:paramtypes", [Compiler, SystemJsNgModuleLoaderConfig])
      ], SystemJsNgModuleLoader);
      return SystemJsNgModuleLoader;
  }());
  function checkNotEmpty(value, modulePath, exportName) {
      if (!value) {
          throw new Error("Cannot find '" + exportName + "' in '" + modulePath + "'");
      }
      return value;
  }

  /**
   * @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
   */
  /**
   * Represents an Angular [view](guide/glossary#view),
   * specifically the [host view](guide/glossary#view-tree) that is defined by a component.
   * Also serves as the base class
   * that adds destroy methods for [embedded views](guide/glossary#view-tree).
   *
   * @see `EmbeddedViewRef`
   *
   * @publicApi
   */
  var ViewRef$1 = /** @class */ (function (_super) {
      __extends(ViewRef, _super);
      function ViewRef() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      return ViewRef;
  }(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
   */
  var EmbeddedViewRef = /** @class */ (function (_super) {
      __extends(EmbeddedViewRef, _super);
      function EmbeddedViewRef() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      return EmbeddedViewRef;
  }(ViewRef$1));

  /**
   * @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
   */

  /**
   * @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
   */
  /**
   * @publicApi
   */
  var DebugEventListener = /** @class */ (function () {
      function DebugEventListener(name, callback) {
          this.name = name;
          this.callback = callback;
      }
      return DebugEventListener;
  }());
  var DebugNode__PRE_R3__ = /** @class */ (function () {
      function DebugNode__PRE_R3__(nativeNode, parent, _debugContext) {
          this.listeners = [];
          this.parent = null;
          this._debugContext = _debugContext;
          this.nativeNode = nativeNode;
          if (parent && parent instanceof DebugElement__PRE_R3__) {
              parent.addChild(this);
          }
      }
      Object.defineProperty(DebugNode__PRE_R3__.prototype, "injector", {
          get: function () {
              return this._debugContext.injector;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__PRE_R3__.prototype, "componentInstance", {
          get: function () {
              return this._debugContext.component;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__PRE_R3__.prototype, "context", {
          get: function () {
              return this._debugContext.context;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__PRE_R3__.prototype, "references", {
          get: function () {
              return this._debugContext.references;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__PRE_R3__.prototype, "providerTokens", {
          get: function () {
              return this._debugContext.providerTokens;
          },
          enumerable: true,
          configurable: true
      });
      return DebugNode__PRE_R3__;
  }());
  var DebugElement__PRE_R3__ = /** @class */ (function (_super) {
      __extends(DebugElement__PRE_R3__, _super);
      function DebugElement__PRE_R3__(nativeNode, parent, _debugContext) {
          var _this = _super.call(this, nativeNode, parent, _debugContext) || this;
          _this.properties = {};
          _this.attributes = {};
          _this.classes = {};
          _this.styles = {};
          _this.childNodes = [];
          _this.nativeElement = nativeNode;
          return _this;
      }
      DebugElement__PRE_R3__.prototype.addChild = function (child) {
          if (child) {
              this.childNodes.push(child);
              child.parent = this;
          }
      };
      DebugElement__PRE_R3__.prototype.removeChild = function (child) {
          var childIndex = this.childNodes.indexOf(child);
          if (childIndex !== -1) {
              child.parent = null;
              this.childNodes.splice(childIndex, 1);
          }
      };
      DebugElement__PRE_R3__.prototype.insertChildrenAfter = function (child, newChildren) {
          var _a;
          var _this = this;
          var siblingIndex = this.childNodes.indexOf(child);
          if (siblingIndex !== -1) {
              (_a = this.childNodes).splice.apply(_a, __spread([siblingIndex + 1, 0], newChildren));
              newChildren.forEach(function (c) {
                  if (c.parent) {
                      c.parent.removeChild(c);
                  }
                  child.parent = _this;
              });
          }
      };
      DebugElement__PRE_R3__.prototype.insertBefore = function (refChild, newChild) {
          var refIndex = this.childNodes.indexOf(refChild);
          if (refIndex === -1) {
              this.addChild(newChild);
          }
          else {
              if (newChild.parent) {
                  newChild.parent.removeChild(newChild);
              }
              newChild.parent = this;
              this.childNodes.splice(refIndex, 0, newChild);
          }
      };
      DebugElement__PRE_R3__.prototype.query = function (predicate) {
          var results = this.queryAll(predicate);
          return results[0] || null;
      };
      DebugElement__PRE_R3__.prototype.queryAll = function (predicate) {
          var matches = [];
          _queryElementChildren(this, predicate, matches);
          return matches;
      };
      DebugElement__PRE_R3__.prototype.queryAllNodes = function (predicate) {
          var matches = [];
          _queryNodeChildren(this, predicate, matches);
          return matches;
      };
      Object.defineProperty(DebugElement__PRE_R3__.prototype, "children", {
          get: function () {
              return this.childNodes //
                  .filter(function (node) { return node instanceof DebugElement__PRE_R3__; });
          },
          enumerable: true,
          configurable: true
      });
      DebugElement__PRE_R3__.prototype.triggerEventHandler = function (eventName, eventObj) {
          this.listeners.forEach(function (listener) {
              if (listener.name == eventName) {
                  listener.callback(eventObj);
              }
          });
      };
      return DebugElement__PRE_R3__;
  }(DebugNode__PRE_R3__));
  /**
   * @publicApi
   */
  function asNativeElements(debugEls) {
      return debugEls.map(function (el) { return el.nativeElement; });
  }
  function _queryElementChildren(element, predicate, matches) {
      element.childNodes.forEach(function (node) {
          if (node instanceof DebugElement__PRE_R3__) {
              if (predicate(node)) {
                  matches.push(node);
              }
              _queryElementChildren(node, predicate, matches);
          }
      });
  }
  function _queryNodeChildren(parentNode, predicate, matches) {
      if (parentNode instanceof DebugElement__PRE_R3__) {
          parentNode.childNodes.forEach(function (node) {
              if (predicate(node)) {
                  matches.push(node);
              }
              if (node instanceof DebugElement__PRE_R3__) {
                  _queryNodeChildren(node, predicate, matches);
              }
          });
      }
  }
  var DebugNode__POST_R3__ = /** @class */ (function () {
      function DebugNode__POST_R3__(nativeNode) {
          this.nativeNode = nativeNode;
      }
      Object.defineProperty(DebugNode__POST_R3__.prototype, "parent", {
          get: function () {
              var parent = this.nativeNode.parentNode;
              return parent ? new DebugElement__POST_R3__(parent) : null;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__POST_R3__.prototype, "injector", {
          get: function () {
              return getInjector(this.nativeNode);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__POST_R3__.prototype, "componentInstance", {
          get: function () {
              var nativeElement = this.nativeNode;
              return nativeElement &&
                  (getComponent(nativeElement) || getOwningComponent(nativeElement));
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__POST_R3__.prototype, "context", {
          get: function () {
              return getComponent(this.nativeNode) || getContext(this.nativeNode);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__POST_R3__.prototype, "listeners", {
          get: function () {
              return getListeners(this.nativeNode).filter(function (listener) { return listener.type === 'dom'; });
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__POST_R3__.prototype, "references", {
          get: function () {
              return getLocalRefs(this.nativeNode);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugNode__POST_R3__.prototype, "providerTokens", {
          get: function () {
              return getInjectionTokens(this.nativeNode);
          },
          enumerable: true,
          configurable: true
      });
      return DebugNode__POST_R3__;
  }());
  var DebugElement__POST_R3__ = /** @class */ (function (_super) {
      __extends(DebugElement__POST_R3__, _super);
      function DebugElement__POST_R3__(nativeNode) {
          var _this = this;
          ngDevMode && assertDomNode(nativeNode);
          _this = _super.call(this, nativeNode) || this;
          return _this;
      }
      Object.defineProperty(DebugElement__POST_R3__.prototype, "nativeElement", {
          get: function () {
              return this.nativeNode.nodeType == Node.ELEMENT_NODE ? this.nativeNode : null;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "name", {
          get: function () {
              try {
                  var context = loadLContext(this.nativeNode);
                  var lView = context.lView;
                  var tData = lView[TVIEW].data;
                  var tNode = tData[context.nodeIndex];
                  return tNode.tagName;
              }
              catch (e) {
                  return this.nativeNode.nodeName;
              }
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "properties", {
          /**
           *  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: function () {
              var context = loadLContext(this.nativeNode, false);
              if (context == null) {
                  return {};
              }
              var lView = context.lView;
              var tData = lView[TVIEW].data;
              var tNode = tData[context.nodeIndex];
              var 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;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "attributes", {
          get: function () {
              var attributes = {};
              var element = this.nativeElement;
              if (!element) {
                  return attributes;
              }
              var context = loadLContext(element, false);
              if (context == null) {
                  return {};
              }
              var lView = context.lView;
              var tNodeAttrs = lView[TVIEW].data[context.nodeIndex].attrs;
              var 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) {
                  var i = 0;
                  while (i < tNodeAttrs.length) {
                      var 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;
                      var attrValue = tNodeAttrs[i + 1];
                      attributes[attrName] = attrValue;
                      lowercaseTNodeAttrs.push(attrName.toLowerCase());
                      i += 2;
                  }
              }
              var eAttrs = element.attributes;
              for (var i = 0; i < eAttrs.length; i++) {
                  var attr = eAttrs[i];
                  var 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;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "styles", {
          get: function () {
              if (this.nativeElement && this.nativeElement.style) {
                  return this.nativeElement.style;
              }
              return {};
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "classes", {
          get: function () {
              var result = {};
              var element = this.nativeElement;
              // SVG elements return an `SVGAnimatedString` instead of a plain string for the `className`.
              var className = element.className;
              var classes = className && typeof className !== 'string' ? className.baseVal.split(' ') :
                  className.split(' ');
              classes.forEach(function (value) { return result[value] = true; });
              return result;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "childNodes", {
          get: function () {
              var childNodes = this.nativeNode.childNodes;
              var children = [];
              for (var i = 0; i < childNodes.length; i++) {
                  var element = childNodes[i];
                  children.push(getDebugNode__POST_R3__(element));
              }
              return children;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugElement__POST_R3__.prototype, "children", {
          get: function () {
              var nativeElement = this.nativeElement;
              if (!nativeElement)
                  return [];
              var childNodes = nativeElement.children;
              var children = [];
              for (var i = 0; i < childNodes.length; i++) {
                  var element = childNodes[i];
                  children.push(getDebugNode__POST_R3__(element));
              }
              return children;
          },
          enumerable: true,
          configurable: true
      });
      DebugElement__POST_R3__.prototype.query = function (predicate) {
          var results = this.queryAll(predicate);
          return results[0] || null;
      };
      DebugElement__POST_R3__.prototype.queryAll = function (predicate) {
          var matches = [];
          _queryAllR3(this, predicate, matches, true);
          return matches;
      };
      DebugElement__POST_R3__.prototype.queryAllNodes = function (predicate) {
          var matches = [];
          _queryAllR3(this, predicate, matches, false);
          return matches;
      };
      DebugElement__POST_R3__.prototype.triggerEventHandler = function (eventName, eventObj) {
          var node = this.nativeNode;
          var invokedListeners = [];
          this.listeners.forEach(function (listener) {
              if (listener.name === eventName) {
                  var 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(function (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) {
                      var unwrappedListener = listener('__ngUnwrap__');
                      return invokedListeners.indexOf(unwrappedListener) === -1 &&
                          unwrappedListener.call(node, eventObj);
                  }
              });
          }
      };
      return DebugElement__POST_R3__;
  }(DebugNode__POST_R3__));
  function copyDomProperties(element, properties) {
      if (element) {
          // Skip own properties (as those are patched)
          var obj = Object.getPrototypeOf(element);
          var NodePrototype = Node.prototype;
          while (obj !== null && obj !== NodePrototype) {
              var descriptors = Object.getOwnPropertyDescriptors(obj);
              for (var 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.
                      var 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 _queryAllR3(parentElement, predicate, matches, elementsOnly) {
      var context = loadLContext(parentElement.nativeNode, false);
      if (context !== null) {
          var parentTNode = context.lView[TVIEW].data[context.nodeIndex];
          _queryNodeChildrenR3(parentTNode, context.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 _queryNodeChildrenR3(tNode, lView, predicate, matches, elementsOnly, rootNativeNode) {
      var e_1, _a;
      var nativeNode = getNativeByTNodeOrNull(tNode, lView);
      // For each type of TNode, specific logic is executed.
      if (tNode.type === 3 /* Element */ || tNode.type === 4 /* ElementContainer */) {
          // Case 1: the TNode is an element
          // The native node has to be checked.
          _addQueryMatchR3(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.
              var componentView = getComponentLViewByIndex(tNode.index, lView);
              if (componentView && componentView[TVIEW].firstChild) {
                  _queryNodeChildrenR3(componentView[TVIEW].firstChild, componentView, predicate, matches, elementsOnly, rootNativeNode);
              }
          }
          else {
              if (tNode.child) {
                  // Otherwise, its children have to be processed.
                  _queryNodeChildrenR3(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 depedency
              //    from `Renderer2` to Ivy which could bring Ivy code into ViewEngine.
              // 2. We would have to make `Renderer3` "know" about debug nodes.
              // 3. 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.
          var nodeOrContainer = lView[tNode.index];
          if (isLContainer(nodeOrContainer)) {
              _queryNodeChildrenInContainerR3(nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
          }
      }
      else if (tNode.type === 0 /* Container */) {
          // Case 2: the TNode is a container
          // The native node has to be checked.
          var lContainer = lView[tNode.index];
          _addQueryMatchR3(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode);
          // Each view inside the container has to be processed.
          _queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode);
      }
      else if (tNode.type === 1 /* 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.
          var componentView = lView[DECLARATION_COMPONENT_VIEW];
          var componentHost = componentView[T_HOST];
          var head = componentHost.projection[tNode.projection];
          if (Array.isArray(head)) {
              try {
                  for (var head_1 = __values(head), head_1_1 = head_1.next(); !head_1_1.done; head_1_1 = head_1.next()) {
                      var nativeNode_1 = head_1_1.value;
                      _addQueryMatchR3(nativeNode_1, predicate, matches, elementsOnly, rootNativeNode);
                  }
              }
              catch (e_1_1) { e_1 = { error: e_1_1 }; }
              finally {
                  try {
                      if (head_1_1 && !head_1_1.done && (_a = head_1.return)) _a.call(head_1);
                  }
                  finally { if (e_1) throw e_1.error; }
              }
          }
          else if (head) {
              var nextLView = componentView[PARENT];
              var nextTNode = nextLView[TVIEW].data[head.index];
              _queryNodeChildrenR3(nextTNode, nextLView, predicate, matches, elementsOnly, rootNativeNode);
          }
      }
      else if (tNode.child) {
          // Case 4: the TNode is a view.
          _queryNodeChildrenR3(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.
          var nextTNode = (tNode.flags & 4 /* isProjected */) ? tNode.projectionNext : tNode.next;
          if (nextTNode) {
              _queryNodeChildrenR3(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 _queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode) {
      for (var i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
          var childView = lContainer[i];
          _queryNodeChildrenR3(childView[TVIEW].node, 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 _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode) {
      if (rootNativeNode !== nativeNode) {
          var debugNode = getDebugNode$1(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__POST_R3__ && 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 of positive matches
   * @param elementsOnly whether only elements should be searched
   */
  function _queryNativeNodeDescendants(parentNode, predicate, matches, elementsOnly) {
      var nodes = parentNode.childNodes;
      var length = nodes.length;
      for (var i = 0; i < length; i++) {
          var node = nodes[i];
          var debugNode = getDebugNode$1(node);
          if (debugNode) {
              if (elementsOnly && debugNode instanceof DebugElement__POST_R3__ && 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) {
      var bindingIndexes = tNode.propertyBindings;
      if (bindingIndexes !== null) {
          for (var i = 0; i < bindingIndexes.length; i++) {
              var bindingIndex = bindingIndexes[i];
              var propMetadata = tData[bindingIndex];
              var metadataParts = propMetadata.split(INTERPOLATION_DELIMITER);
              var propertyName = metadataParts[0];
              if (metadataParts.length > 1) {
                  var value = metadataParts[1];
                  for (var 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.
  var _nativeNodeToDebugNode = new Map();
  function getDebugNode__PRE_R3__(nativeNode) {
      return _nativeNodeToDebugNode.get(nativeNode) || null;
  }
  var NG_DEBUG_PROPERTY = '__ng_debug__';
  function getDebugNode__POST_R3__(nativeNode) {
      if (nativeNode instanceof Node) {
          if (!(nativeNode.hasOwnProperty(NG_DEBUG_PROPERTY))) {
              nativeNode[NG_DEBUG_PROPERTY] = nativeNode.nodeType == Node.ELEMENT_NODE ?
                  new DebugElement__POST_R3__(nativeNode) :
                  new DebugNode__POST_R3__(nativeNode);
          }
          return nativeNode[NG_DEBUG_PROPERTY];
      }
      return null;
  }
  /**
   * @publicApi
   */
  var getDebugNode$1 = getDebugNode__PRE_R3__;
  function getDebugNodeR2__PRE_R3__(nativeNode) {
      return getDebugNode__PRE_R3__(nativeNode);
  }
  function getDebugNodeR2__POST_R3__(_nativeNode) {
      return null;
  }
  var getDebugNodeR2 = getDebugNodeR2__PRE_R3__;
  function getAllDebugNodes() {
      return Array.from(_nativeNodeToDebugNode.values());
  }
  function indexDebugNode(node) {
      _nativeNodeToDebugNode.set(node.nativeNode, node);
  }
  function removeDebugNodeFromIndex(node) {
      _nativeNodeToDebugNode.delete(node.nativeNode);
  }
  /**
   * @publicApi
   */
  var DebugNode = DebugNode__PRE_R3__;
  /**
   * @publicApi
   */
  var DebugElement = DebugElement__PRE_R3__;

  /**
   * @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
   */

  /**
   * @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
   */
  var _CORE_PLATFORM_PROVIDERS = [
      // Set a default platform name for platforms that don't set it explicitly.
      { provide: PLATFORM_ID, useValue: 'unknown' },
      { provide: PlatformRef, deps: [Injector] },
      { provide: TestabilityRegistry, deps: [] },
      { provide: Console, deps: [] },
  ];
  /**
   * This platform has to be included in any other platform
   *
   * @publicApi
   */
  var platformCore = createPlatformFactory(null, 'core', _CORE_PLATFORM_PROVIDERS);

  /**
   * @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
   */
  function _iterableDiffersFactory() {
      return defaultIterableDiffers;
  }
  function _keyValueDiffersFactory() {
      return defaultKeyValueDiffers;
  }
  function _localeFactory(locale) {
      locale = locale || getGlobalLocale();
      if (ivyEnabled) {
          setLocaleId(locale);
      }
      return locale;
  }
  /**
   * 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 (ivyEnabled && typeof $localize !== 'undefined' && $localize.locale) ||
              DEFAULT_LOCALE_ID;
      }
  }
  var ɵ0$g = USD_CURRENCY_CODE;
  /**
   * A built-in [dependency injection token](guide/glossary#di-token)
   * that is used to configure the root injector for bootstrapping.
   */
  var APPLICATION_MODULE_PROVIDERS = [
      {
          provide: ApplicationRef,
          useClass: ApplicationRef,
          deps: [NgZone, Console, Injector, ErrorHandler, ComponentFactoryResolver, ApplicationInitStatus]
      },
      { provide: SCHEDULER, deps: [NgZone], useFactory: zoneSchedulerFactory },
      {
          provide: ApplicationInitStatus,
          useClass: ApplicationInitStatus,
          deps: [[new Optional(), APP_INITIALIZER]]
      },
      { provide: Compiler, useClass: Compiler, deps: [] },
      APP_ID_RANDOM_PROVIDER,
      { provide: IterableDiffers, useFactory: _iterableDiffersFactory, deps: [] },
      { provide: KeyValueDiffers, useFactory: _keyValueDiffersFactory, deps: [] },
      {
          provide: LOCALE_ID$1,
          useFactory: _localeFactory,
          deps: [[new Inject(LOCALE_ID$1), new Optional(), new SkipSelf()]]
      },
      { provide: DEFAULT_CURRENCY_CODE, useValue: ɵ0$g },
  ];
  /**
   * Schedule work at next available slot.
   *
   * In Ivy this is just `requestAnimationFrame`. For compatibility reasons when bootstrapped
   * using `platformRef.bootstrap` we need to use `NgZone.onStable` as the scheduling mechanism.
   * This overrides the scheduling mechanism in Ivy to `NgZone.onStable`.
   *
   * @param ngZone NgZone to use for scheduling.
   */
  function zoneSchedulerFactory(ngZone) {
      var queue = [];
      ngZone.onStable.subscribe(function () {
          while (queue.length) {
              queue.pop()();
          }
      });
      return function (fn) {
          queue.push(fn);
      };
  }
  /**
   * Configures the root injector for an app with
   * providers of `@angular/core` dependencies that `ApplicationRef` needs
   * to bootstrap components.
   *
   * Re-exported by `BrowserModule`, which is included automatically in the root
   * `AppModule` when you create a new app with the CLI `new` command.
   *
   * @publicApi
   */
  var ApplicationModule = /** @class */ (function () {
      // Inject ApplicationRef to make it eager...
      function ApplicationModule(appRef) {
      }
      ApplicationModule = __decorate([
          NgModule({ providers: APPLICATION_MODULE_PROVIDERS }),
          __metadata("design:paramtypes", [ApplicationRef])
      ], ApplicationModule);
      return ApplicationModule;
  }());

  /**
   * @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
   */
  function anchorDef(flags, matchedQueriesDsl, ngContentIndex, childCount, handleEvent, templateFactory) {
      flags |= 1 /* TypeElement */;
      var _a = splitMatchedQueriesDsl(matchedQueriesDsl), matchedQueries = _a.matchedQueries, references = _a.references, matchedQueryIds = _a.matchedQueryIds;
      var template = templateFactory ? resolveDefinition(templateFactory) : null;
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          flags: flags,
          checkIndex: -1,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          matchedQueries: matchedQueries,
          matchedQueryIds: matchedQueryIds,
          references: references,
          ngContentIndex: ngContentIndex,
          childCount: childCount,
          bindings: [],
          bindingFlags: 0,
          outputs: [],
          element: {
              ns: null,
              name: null,
              attrs: null,
              template: template,
              componentProvider: null,
              componentView: null,
              componentRendererType: null,
              publicProviders: null,
              allProviders: null,
              handleEvent: handleEvent || NOOP
          },
          provider: null,
          text: null,
          query: null,
          ngContent: null
      };
  }
  function elementDef(checkIndex, flags, matchedQueriesDsl, ngContentIndex, childCount, namespaceAndName, fixedAttrs, bindings, outputs, handleEvent, componentView, componentRendererType) {
      var _a;
      if (fixedAttrs === void 0) { fixedAttrs = []; }
      if (!handleEvent) {
          handleEvent = NOOP;
      }
      var _b = splitMatchedQueriesDsl(matchedQueriesDsl), matchedQueries = _b.matchedQueries, references = _b.references, matchedQueryIds = _b.matchedQueryIds;
      var ns = null;
      var name = null;
      if (namespaceAndName) {
          _a = __read(splitNamespace(namespaceAndName), 2), ns = _a[0], name = _a[1];
      }
      bindings = bindings || [];
      var bindingDefs = [];
      for (var i = 0; i < bindings.length; i++) {
          var _c = __read(bindings[i], 3), bindingFlags = _c[0], namespaceAndName_1 = _c[1], suffixOrSecurityContext = _c[2];
          var _d = __read(splitNamespace(namespaceAndName_1), 2), ns_1 = _d[0], name_1 = _d[1];
          var securityContext = undefined;
          var suffix = undefined;
          switch (bindingFlags & 15 /* Types */) {
              case 4 /* TypeElementStyle */:
                  suffix = suffixOrSecurityContext;
                  break;
              case 1 /* TypeElementAttribute */:
              case 8 /* TypeProperty */:
                  securityContext = suffixOrSecurityContext;
                  break;
          }
          bindingDefs[i] =
              { flags: bindingFlags, ns: ns_1, name: name_1, nonMinifiedName: name_1, securityContext: securityContext, suffix: suffix };
      }
      outputs = outputs || [];
      var outputDefs = [];
      for (var i = 0; i < outputs.length; i++) {
          var _e = __read(outputs[i], 2), target = _e[0], eventName = _e[1];
          outputDefs[i] =
              { type: 0 /* ElementOutput */, target: target, eventName: eventName, propName: null };
      }
      fixedAttrs = fixedAttrs || [];
      var attrs = fixedAttrs.map(function (_a) {
          var _b = __read(_a, 2), namespaceAndName = _b[0], value = _b[1];
          var _c = __read(splitNamespace(namespaceAndName), 2), ns = _c[0], name = _c[1];
          return [ns, name, value];
      });
      componentRendererType = resolveRendererType2(componentRendererType);
      if (componentView) {
          flags |= 33554432 /* ComponentView */;
      }
      flags |= 1 /* TypeElement */;
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          checkIndex: checkIndex,
          flags: flags,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          matchedQueries: matchedQueries,
          matchedQueryIds: matchedQueryIds,
          references: references,
          ngContentIndex: ngContentIndex,
          childCount: childCount,
          bindings: bindingDefs,
          bindingFlags: calcBindingFlags(bindingDefs),
          outputs: outputDefs,
          element: {
              ns: ns,
              name: name,
              attrs: attrs,
              template: null,
              // will bet set by the view definition
              componentProvider: null,
              componentView: componentView || null,
              componentRendererType: componentRendererType,
              publicProviders: null,
              allProviders: null,
              handleEvent: handleEvent || NOOP,
          },
          provider: null,
          text: null,
          query: null,
          ngContent: null
      };
  }
  function createElement(view, renderHost, def) {
      var elDef = def.element;
      var rootSelectorOrNode = view.root.selectorOrNode;
      var renderer = view.renderer;
      var el;
      if (view.parent || !rootSelectorOrNode) {
          if (elDef.name) {
              el = renderer.createElement(elDef.name, elDef.ns);
          }
          else {
              el = renderer.createComment('');
          }
          var parentEl = getParentRenderElement(view, renderHost, def);
          if (parentEl) {
              renderer.appendChild(parentEl, el);
          }
      }
      else {
          // when using native Shadow DOM, do not clear the root element contents to allow slot projection
          var preserveContent = (!!elDef.componentRendererType &&
              elDef.componentRendererType.encapsulation === exports.ViewEncapsulation.ShadowDom);
          el = renderer.selectRootElement(rootSelectorOrNode, preserveContent);
      }
      if (elDef.attrs) {
          for (var i = 0; i < elDef.attrs.length; i++) {
              var _a = __read(elDef.attrs[i], 3), ns = _a[0], name_2 = _a[1], value = _a[2];
              renderer.setAttribute(el, name_2, value, ns);
          }
      }
      return el;
  }
  function listenToElementOutputs(view, compView, def, el) {
      for (var i = 0; i < def.outputs.length; i++) {
          var output = def.outputs[i];
          var handleEventClosure = renderEventHandlerClosure(view, def.nodeIndex, elementEventFullName(output.target, output.eventName));
          var listenTarget = output.target;
          var listenerView = view;
          if (output.target === 'component') {
              listenTarget = null;
              listenerView = compView;
          }
          var disposable = listenerView.renderer.listen(listenTarget || el, output.eventName, handleEventClosure);
          view.disposables[def.outputIndex + i] = disposable;
      }
  }
  function renderEventHandlerClosure(view, index, eventName) {
      return function (event) { return dispatchEvent(view, index, eventName, event); };
  }
  function checkAndUpdateElementInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var bindLen = def.bindings.length;
      var changed = false;
      if (bindLen > 0 && checkAndUpdateElementValue(view, def, 0, v0))
          changed = true;
      if (bindLen > 1 && checkAndUpdateElementValue(view, def, 1, v1))
          changed = true;
      if (bindLen > 2 && checkAndUpdateElementValue(view, def, 2, v2))
          changed = true;
      if (bindLen > 3 && checkAndUpdateElementValue(view, def, 3, v3))
          changed = true;
      if (bindLen > 4 && checkAndUpdateElementValue(view, def, 4, v4))
          changed = true;
      if (bindLen > 5 && checkAndUpdateElementValue(view, def, 5, v5))
          changed = true;
      if (bindLen > 6 && checkAndUpdateElementValue(view, def, 6, v6))
          changed = true;
      if (bindLen > 7 && checkAndUpdateElementValue(view, def, 7, v7))
          changed = true;
      if (bindLen > 8 && checkAndUpdateElementValue(view, def, 8, v8))
          changed = true;
      if (bindLen > 9 && checkAndUpdateElementValue(view, def, 9, v9))
          changed = true;
      return changed;
  }
  function checkAndUpdateElementDynamic(view, def, values) {
      var changed = false;
      for (var i = 0; i < values.length; i++) {
          if (checkAndUpdateElementValue(view, def, i, values[i]))
              changed = true;
      }
      return changed;
  }
  function checkAndUpdateElementValue(view, def, bindingIdx, value) {
      if (!checkAndUpdateBinding(view, def, bindingIdx, value)) {
          return false;
      }
      var binding = def.bindings[bindingIdx];
      var elData = asElementData(view, def.nodeIndex);
      var renderNode = elData.renderElement;
      var name = binding.name;
      switch (binding.flags & 15 /* Types */) {
          case 1 /* TypeElementAttribute */:
              setElementAttribute(view, binding, renderNode, binding.ns, name, value);
              break;
          case 2 /* TypeElementClass */:
              setElementClass(view, renderNode, name, value);
              break;
          case 4 /* TypeElementStyle */:
              setElementStyle(view, binding, renderNode, name, value);
              break;
          case 8 /* TypeProperty */:
              var bindView = (def.flags & 33554432 /* ComponentView */ &&
                  binding.flags & 32 /* SyntheticHostProperty */) ?
                  elData.componentView :
                  view;
              setElementProperty(bindView, binding, renderNode, name, value);
              break;
      }
      return true;
  }
  function setElementAttribute(view, binding, renderNode, ns, name, value) {
      var securityContext = binding.securityContext;
      var renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
      renderValue = renderValue != null ? renderValue.toString() : null;
      var renderer = view.renderer;
      if (value != null) {
          renderer.setAttribute(renderNode, name, renderValue, ns);
      }
      else {
          renderer.removeAttribute(renderNode, name, ns);
      }
  }
  function setElementClass(view, renderNode, name, value) {
      var renderer = view.renderer;
      if (value) {
          renderer.addClass(renderNode, name);
      }
      else {
          renderer.removeClass(renderNode, name);
      }
  }
  function setElementStyle(view, binding, renderNode, name, value) {
      var renderValue = view.root.sanitizer.sanitize(exports.SecurityContext.STYLE, value);
      if (renderValue != null) {
          renderValue = renderValue.toString();
          var unit = binding.suffix;
          if (unit != null) {
              renderValue = renderValue + unit;
          }
      }
      else {
          renderValue = null;
      }
      var renderer = view.renderer;
      if (renderValue != null) {
          renderer.setStyle(renderNode, name, renderValue);
      }
      else {
          renderer.removeStyle(renderNode, name);
      }
  }
  function setElementProperty(view, binding, renderNode, name, value) {
      var securityContext = binding.securityContext;
      var renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
      view.renderer.setProperty(renderNode, name, renderValue);
  }

  /**
   * @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
   */
  function queryDef(flags, id, bindings) {
      var bindingDefs = [];
      for (var propName in bindings) {
          var bindingType = bindings[propName];
          bindingDefs.push({ propName: propName, bindingType: bindingType });
      }
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          // TODO(vicb): check
          checkIndex: -1,
          flags: flags,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          ngContentIndex: -1,
          matchedQueries: {},
          matchedQueryIds: 0,
          references: {},
          childCount: 0,
          bindings: [],
          bindingFlags: 0,
          outputs: [],
          element: null,
          provider: null,
          text: null,
          query: { id: id, filterId: filterQueryId(id), bindings: bindingDefs },
          ngContent: null
      };
  }
  function createQuery() {
      return new QueryList();
  }
  function dirtyParentQueries(view) {
      var queryIds = view.def.nodeMatchedQueries;
      while (view.parent && isEmbeddedView(view)) {
          var tplDef = view.parentNodeDef;
          view = view.parent;
          // content queries
          var end = tplDef.nodeIndex + tplDef.childCount;
          for (var i = 0; i <= end; i++) {
              var nodeDef = view.def.nodes[i];
              if ((nodeDef.flags & 67108864 /* TypeContentQuery */) &&
                  (nodeDef.flags & 536870912 /* DynamicQuery */) &&
                  (nodeDef.query.filterId & queryIds) === nodeDef.query.filterId) {
                  asQueryList(view, i).setDirty();
              }
              if ((nodeDef.flags & 1 /* TypeElement */ && i + nodeDef.childCount < tplDef.nodeIndex) ||
                  !(nodeDef.childFlags & 67108864 /* TypeContentQuery */) ||
                  !(nodeDef.childFlags & 536870912 /* DynamicQuery */)) {
                  // skip elements that don't contain the template element or no query.
                  i += nodeDef.childCount;
              }
          }
      }
      // view queries
      if (view.def.nodeFlags & 134217728 /* TypeViewQuery */) {
          for (var i = 0; i < view.def.nodes.length; i++) {
              var nodeDef = view.def.nodes[i];
              if ((nodeDef.flags & 134217728 /* TypeViewQuery */) && (nodeDef.flags & 536870912 /* DynamicQuery */)) {
                  asQueryList(view, i).setDirty();
              }
              // only visit the root nodes
              i += nodeDef.childCount;
          }
      }
  }
  function checkAndUpdateQuery(view, nodeDef) {
      var queryList = asQueryList(view, nodeDef.nodeIndex);
      if (!queryList.dirty) {
          return;
      }
      var directiveInstance;
      var newValues = undefined;
      if (nodeDef.flags & 67108864 /* TypeContentQuery */) {
          var elementDef = nodeDef.parent.parent;
          newValues = calcQueryValues(view, elementDef.nodeIndex, elementDef.nodeIndex + elementDef.childCount, nodeDef.query, []);
          directiveInstance = asProviderData(view, nodeDef.parent.nodeIndex).instance;
      }
      else if (nodeDef.flags & 134217728 /* TypeViewQuery */) {
          newValues = calcQueryValues(view, 0, view.def.nodes.length - 1, nodeDef.query, []);
          directiveInstance = view.component;
      }
      queryList.reset(newValues);
      var bindings = nodeDef.query.bindings;
      var notify = false;
      for (var i = 0; i < bindings.length; i++) {
          var binding = bindings[i];
          var boundValue = void 0;
          switch (binding.bindingType) {
              case 0 /* First */:
                  boundValue = queryList.first;
                  break;
              case 1 /* All */:
                  boundValue = queryList;
                  notify = true;
                  break;
          }
          directiveInstance[binding.propName] = boundValue;
      }
      if (notify) {
          queryList.notifyOnChanges();
      }
  }
  function calcQueryValues(view, startIndex, endIndex, queryDef, values) {
      for (var i = startIndex; i <= endIndex; i++) {
          var nodeDef = view.def.nodes[i];
          var valueType = nodeDef.matchedQueries[queryDef.id];
          if (valueType != null) {
              values.push(getQueryValue(view, nodeDef, valueType));
          }
          if (nodeDef.flags & 1 /* TypeElement */ && nodeDef.element.template &&
              (nodeDef.element.template.nodeMatchedQueries & queryDef.filterId) ===
                  queryDef.filterId) {
              var elementData = asElementData(view, i);
              // check embedded views that were attached at the place of their template,
              // but process child nodes first if some match the query (see issue #16568)
              if ((nodeDef.childMatchedQueries & queryDef.filterId) === queryDef.filterId) {
                  calcQueryValues(view, i + 1, i + nodeDef.childCount, queryDef, values);
                  i += nodeDef.childCount;
              }
              if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
                  var embeddedViews = elementData.viewContainer._embeddedViews;
                  for (var k = 0; k < embeddedViews.length; k++) {
                      var embeddedView = embeddedViews[k];
                      var dvc = declaredViewContainer(embeddedView);
                      if (dvc && dvc === elementData) {
                          calcQueryValues(embeddedView, 0, embeddedView.def.nodes.length - 1, queryDef, values);
                      }
                  }
              }
              var projectedViews = elementData.template._projectedViews;
              if (projectedViews) {
                  for (var k = 0; k < projectedViews.length; k++) {
                      var projectedView = projectedViews[k];
                      calcQueryValues(projectedView, 0, projectedView.def.nodes.length - 1, queryDef, values);
                  }
              }
          }
          if ((nodeDef.childMatchedQueries & queryDef.filterId) !== queryDef.filterId) {
              // if no child matches the query, skip the children.
              i += nodeDef.childCount;
          }
      }
      return values;
  }
  function getQueryValue(view, nodeDef, queryValueType) {
      if (queryValueType != null) {
          // a match
          switch (queryValueType) {
              case 1 /* RenderElement */:
                  return asElementData(view, nodeDef.nodeIndex).renderElement;
              case 0 /* ElementRef */:
                  return new ElementRef(asElementData(view, nodeDef.nodeIndex).renderElement);
              case 2 /* TemplateRef */:
                  return asElementData(view, nodeDef.nodeIndex).template;
              case 3 /* ViewContainerRef */:
                  return asElementData(view, nodeDef.nodeIndex).viewContainer;
              case 4 /* Provider */:
                  return asProviderData(view, nodeDef.nodeIndex).instance;
          }
      }
  }

  /**
   * @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
   */
  function ngContentDef(ngContentIndex, index) {
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          checkIndex: -1,
          flags: 8 /* TypeNgContent */,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          matchedQueries: {},
          matchedQueryIds: 0,
          references: {},
          ngContentIndex: ngContentIndex,
          childCount: 0,
          bindings: [],
          bindingFlags: 0,
          outputs: [],
          element: null,
          provider: null,
          text: null,
          query: null,
          ngContent: { index: index }
      };
  }
  function appendNgContent(view, renderHost, def) {
      var parentEl = getParentRenderElement(view, renderHost, def);
      if (!parentEl) {
          // Nothing to do if there is no parent element.
          return;
      }
      var ngContentIndex = def.ngContent.index;
      visitProjectedRenderNodes(view, ngContentIndex, 1 /* AppendChild */, parentEl, null, undefined);
  }

  /**
   * @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
   */
  function purePipeDef(checkIndex, argCount) {
      // argCount + 1 to include the pipe as first arg
      return _pureExpressionDef(128 /* TypePurePipe */, checkIndex, newArray(argCount + 1));
  }
  function pureArrayDef(checkIndex, argCount) {
      return _pureExpressionDef(32 /* TypePureArray */, checkIndex, newArray(argCount));
  }
  function pureObjectDef(checkIndex, propToIndex) {
      var keys = Object.keys(propToIndex);
      var nbKeys = keys.length;
      var propertyNames = [];
      for (var i = 0; i < nbKeys; i++) {
          var key = keys[i];
          var index = propToIndex[key];
          propertyNames.push(key);
      }
      return _pureExpressionDef(64 /* TypePureObject */, checkIndex, propertyNames);
  }
  function _pureExpressionDef(flags, checkIndex, propertyNames) {
      var bindings = [];
      for (var i = 0; i < propertyNames.length; i++) {
          var prop = propertyNames[i];
          bindings.push({
              flags: 8 /* TypeProperty */,
              name: prop,
              ns: null,
              nonMinifiedName: prop,
              securityContext: null,
              suffix: null
          });
      }
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          checkIndex: checkIndex,
          flags: flags,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          matchedQueries: {},
          matchedQueryIds: 0,
          references: {},
          ngContentIndex: -1,
          childCount: 0,
          bindings: bindings,
          bindingFlags: calcBindingFlags(bindings),
          outputs: [],
          element: null,
          provider: null,
          text: null,
          query: null,
          ngContent: null
      };
  }
  function createPureExpression(view, def) {
      return { value: undefined };
  }
  function checkAndUpdatePureExpressionInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var bindings = def.bindings;
      var changed = false;
      var bindLen = bindings.length;
      if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0))
          changed = true;
      if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1))
          changed = true;
      if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2))
          changed = true;
      if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3))
          changed = true;
      if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4))
          changed = true;
      if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5))
          changed = true;
      if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6))
          changed = true;
      if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7))
          changed = true;
      if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8))
          changed = true;
      if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9))
          changed = true;
      if (changed) {
          var data = asPureExpressionData(view, def.nodeIndex);
          var value = void 0;
          switch (def.flags & 201347067 /* Types */) {
              case 32 /* TypePureArray */:
                  value = [];
                  if (bindLen > 0)
                      value.push(v0);
                  if (bindLen > 1)
                      value.push(v1);
                  if (bindLen > 2)
                      value.push(v2);
                  if (bindLen > 3)
                      value.push(v3);
                  if (bindLen > 4)
                      value.push(v4);
                  if (bindLen > 5)
                      value.push(v5);
                  if (bindLen > 6)
                      value.push(v6);
                  if (bindLen > 7)
                      value.push(v7);
                  if (bindLen > 8)
                      value.push(v8);
                  if (bindLen > 9)
                      value.push(v9);
                  break;
              case 64 /* TypePureObject */:
                  value = {};
                  if (bindLen > 0)
                      value[bindings[0].name] = v0;
                  if (bindLen > 1)
                      value[bindings[1].name] = v1;
                  if (bindLen > 2)
                      value[bindings[2].name] = v2;
                  if (bindLen > 3)
                      value[bindings[3].name] = v3;
                  if (bindLen > 4)
                      value[bindings[4].name] = v4;
                  if (bindLen > 5)
                      value[bindings[5].name] = v5;
                  if (bindLen > 6)
                      value[bindings[6].name] = v6;
                  if (bindLen > 7)
                      value[bindings[7].name] = v7;
                  if (bindLen > 8)
                      value[bindings[8].name] = v8;
                  if (bindLen > 9)
                      value[bindings[9].name] = v9;
                  break;
              case 128 /* TypePurePipe */:
                  var pipe = v0;
                  switch (bindLen) {
                      case 1:
                          value = pipe.transform(v0);
                          break;
                      case 2:
                          value = pipe.transform(v1);
                          break;
                      case 3:
                          value = pipe.transform(v1, v2);
                          break;
                      case 4:
                          value = pipe.transform(v1, v2, v3);
                          break;
                      case 5:
                          value = pipe.transform(v1, v2, v3, v4);
                          break;
                      case 6:
                          value = pipe.transform(v1, v2, v3, v4, v5);
                          break;
                      case 7:
                          value = pipe.transform(v1, v2, v3, v4, v5, v6);
                          break;
                      case 8:
                          value = pipe.transform(v1, v2, v3, v4, v5, v6, v7);
                          break;
                      case 9:
                          value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8);
                          break;
                      case 10:
                          value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8, v9);
                          break;
                  }
                  break;
          }
          data.value = value;
      }
      return changed;
  }
  function checkAndUpdatePureExpressionDynamic(view, def, values) {
      var bindings = def.bindings;
      var changed = false;
      for (var i = 0; i < values.length; i++) {
          // Note: We need to loop over all values, so that
          // the old values are updates as well!
          if (checkAndUpdateBinding(view, def, i, values[i])) {
              changed = true;
          }
      }
      if (changed) {
          var data = asPureExpressionData(view, def.nodeIndex);
          var value = void 0;
          switch (def.flags & 201347067 /* Types */) {
              case 32 /* TypePureArray */:
                  value = values;
                  break;
              case 64 /* TypePureObject */:
                  value = {};
                  for (var i = 0; i < values.length; i++) {
                      value[bindings[i].name] = values[i];
                  }
                  break;
              case 128 /* TypePurePipe */:
                  var pipe = values[0];
                  var params = values.slice(1);
                  value = pipe.transform.apply(pipe, __spread(params));
                  break;
          }
          data.value = value;
      }
      return changed;
  }

  /**
   * @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
   */
  function textDef(checkIndex, ngContentIndex, staticText) {
      var bindings = [];
      for (var i = 1; i < staticText.length; i++) {
          bindings[i - 1] = {
              flags: 8 /* TypeProperty */,
              name: null,
              ns: null,
              nonMinifiedName: null,
              securityContext: null,
              suffix: staticText[i],
          };
      }
      return {
          // will bet set by the view definition
          nodeIndex: -1,
          parent: null,
          renderParent: null,
          bindingIndex: -1,
          outputIndex: -1,
          // regular values
          checkIndex: checkIndex,
          flags: 2 /* TypeText */,
          childFlags: 0,
          directChildFlags: 0,
          childMatchedQueries: 0,
          matchedQueries: {},
          matchedQueryIds: 0,
          references: {},
          ngContentIndex: ngContentIndex,
          childCount: 0,
          bindings: bindings,
          bindingFlags: 8 /* TypeProperty */,
          outputs: [],
          element: null,
          provider: null,
          text: { prefix: staticText[0] },
          query: null,
          ngContent: null,
      };
  }
  function createText(view, renderHost, def) {
      var renderNode;
      var renderer = view.renderer;
      renderNode = renderer.createText(def.text.prefix);
      var parentEl = getParentRenderElement(view, renderHost, def);
      if (parentEl) {
          renderer.appendChild(parentEl, renderNode);
      }
      return { renderText: renderNode };
  }
  function checkAndUpdateTextInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var changed = false;
      var bindings = def.bindings;
      var bindLen = bindings.length;
      if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0))
          changed = true;
      if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1))
          changed = true;
      if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2))
          changed = true;
      if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3))
          changed = true;
      if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4))
          changed = true;
      if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5))
          changed = true;
      if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6))
          changed = true;
      if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7))
          changed = true;
      if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8))
          changed = true;
      if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9))
          changed = true;
      if (changed) {
          var value = def.text.prefix;
          if (bindLen > 0)
              value += _addInterpolationPart(v0, bindings[0]);
          if (bindLen > 1)
              value += _addInterpolationPart(v1, bindings[1]);
          if (bindLen > 2)
              value += _addInterpolationPart(v2, bindings[2]);
          if (bindLen > 3)
              value += _addInterpolationPart(v3, bindings[3]);
          if (bindLen > 4)
              value += _addInterpolationPart(v4, bindings[4]);
          if (bindLen > 5)
              value += _addInterpolationPart(v5, bindings[5]);
          if (bindLen > 6)
              value += _addInterpolationPart(v6, bindings[6]);
          if (bindLen > 7)
              value += _addInterpolationPart(v7, bindings[7]);
          if (bindLen > 8)
              value += _addInterpolationPart(v8, bindings[8]);
          if (bindLen > 9)
              value += _addInterpolationPart(v9, bindings[9]);
          var renderNode = asTextData(view, def.nodeIndex).renderText;
          view.renderer.setValue(renderNode, value);
      }
      return changed;
  }
  function checkAndUpdateTextDynamic(view, def, values) {
      var bindings = def.bindings;
      var changed = false;
      for (var i = 0; i < values.length; i++) {
          // Note: We need to loop over all values, so that
          // the old values are updates as well!
          if (checkAndUpdateBinding(view, def, i, values[i])) {
              changed = true;
          }
      }
      if (changed) {
          var value = '';
          for (var i = 0; i < values.length; i++) {
              value = value + _addInterpolationPart(values[i], bindings[i]);
          }
          value = def.text.prefix + value;
          var renderNode = asTextData(view, def.nodeIndex).renderText;
          view.renderer.setValue(renderNode, value);
      }
      return changed;
  }
  function _addInterpolationPart(value, binding) {
      var valueStr = value != null ? value.toString() : '';
      return valueStr + binding.suffix;
  }

  /**
   * @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
   */
  function viewDef(flags, nodes, updateDirectives, updateRenderer) {
      // clone nodes and set auto calculated values
      var viewBindingCount = 0;
      var viewDisposableCount = 0;
      var viewNodeFlags = 0;
      var viewRootNodeFlags = 0;
      var viewMatchedQueries = 0;
      var currentParent = null;
      var currentRenderParent = null;
      var currentElementHasPublicProviders = false;
      var currentElementHasPrivateProviders = false;
      var lastRenderRootNode = null;
      for (var i = 0; i < nodes.length; i++) {
          var node = nodes[i];
          node.nodeIndex = i;
          node.parent = currentParent;
          node.bindingIndex = viewBindingCount;
          node.outputIndex = viewDisposableCount;
          node.renderParent = currentRenderParent;
          viewNodeFlags |= node.flags;
          viewMatchedQueries |= node.matchedQueryIds;
          if (node.element) {
              var elDef = node.element;
              elDef.publicProviders =
                  currentParent ? currentParent.element.publicProviders : Object.create(null);
              elDef.allProviders = elDef.publicProviders;
              // Note: We assume that all providers of an element are before any child element!
              currentElementHasPublicProviders = false;
              currentElementHasPrivateProviders = false;
              if (node.element.template) {
                  viewMatchedQueries |= node.element.template.nodeMatchedQueries;
              }
          }
          validateNode(currentParent, node, nodes.length);
          viewBindingCount += node.bindings.length;
          viewDisposableCount += node.outputs.length;
          if (!currentRenderParent && (node.flags & 3 /* CatRenderNode */)) {
              lastRenderRootNode = node;
          }
          if (node.flags & 20224 /* CatProvider */) {
              if (!currentElementHasPublicProviders) {
                  currentElementHasPublicProviders = true;
                  // Use prototypical inheritance to not get O(n^2) complexity...
                  currentParent.element.publicProviders =
                      Object.create(currentParent.element.publicProviders);
                  currentParent.element.allProviders = currentParent.element.publicProviders;
              }
              var isPrivateService = (node.flags & 8192 /* PrivateProvider */) !== 0;
              var isComponent = (node.flags & 32768 /* Component */) !== 0;
              if (!isPrivateService || isComponent) {
                  currentParent.element.publicProviders[tokenKey(node.provider.token)] = node;
              }
              else {
                  if (!currentElementHasPrivateProviders) {
                      currentElementHasPrivateProviders = true;
                      // Use prototypical inheritance to not get O(n^2) complexity...
                      currentParent.element.allProviders =
                          Object.create(currentParent.element.publicProviders);
                  }
                  currentParent.element.allProviders[tokenKey(node.provider.token)] = node;
              }
              if (isComponent) {
                  currentParent.element.componentProvider = node;
              }
          }
          if (currentParent) {
              currentParent.childFlags |= node.flags;
              currentParent.directChildFlags |= node.flags;
              currentParent.childMatchedQueries |= node.matchedQueryIds;
              if (node.element && node.element.template) {
                  currentParent.childMatchedQueries |= node.element.template.nodeMatchedQueries;
              }
          }
          else {
              viewRootNodeFlags |= node.flags;
          }
          if (node.childCount > 0) {
              currentParent = node;
              if (!isNgContainer(node)) {
                  currentRenderParent = node;
              }
          }
          else {
              // When the current node has no children, check if it is the last children of its parent.
              // When it is, propagate the flags up.
              // The loop is required because an element could be the last transitive children of several
              // elements. We loop to either the root or the highest opened element (= with remaining
              // children)
              while (currentParent && i === currentParent.nodeIndex + currentParent.childCount) {
                  var newParent = currentParent.parent;
                  if (newParent) {
                      newParent.childFlags |= currentParent.childFlags;
                      newParent.childMatchedQueries |= currentParent.childMatchedQueries;
                  }
                  currentParent = newParent;
                  // We also need to update the render parent & account for ng-container
                  if (currentParent && isNgContainer(currentParent)) {
                      currentRenderParent = currentParent.renderParent;
                  }
                  else {
                      currentRenderParent = currentParent;
                  }
              }
          }
      }
      var handleEvent = function (view, nodeIndex, eventName, event) {
          return nodes[nodeIndex].element.handleEvent(view, eventName, event);
      };
      return {
          // Will be filled later...
          factory: null,
          nodeFlags: viewNodeFlags,
          rootNodeFlags: viewRootNodeFlags,
          nodeMatchedQueries: viewMatchedQueries,
          flags: flags,
          nodes: nodes,
          updateDirectives: updateDirectives || NOOP,
          updateRenderer: updateRenderer || NOOP,
          handleEvent: handleEvent,
          bindingCount: viewBindingCount,
          outputCount: viewDisposableCount,
          lastRenderRootNode: lastRenderRootNode
      };
  }
  function isNgContainer(node) {
      return (node.flags & 1 /* TypeElement */) !== 0 && node.element.name === null;
  }
  function validateNode(parent, node, nodeCount) {
      var template = node.element && node.element.template;
      if (template) {
          if (!template.lastRenderRootNode) {
              throw new Error("Illegal State: Embedded templates without nodes are not allowed!");
          }
          if (template.lastRenderRootNode &&
              template.lastRenderRootNode.flags & 16777216 /* EmbeddedViews */) {
              throw new Error("Illegal State: Last root node of a template can't have embedded views, at index " + node.nodeIndex + "!");
          }
      }
      if (node.flags & 20224 /* CatProvider */) {
          var parentFlags = parent ? parent.flags : 0;
          if ((parentFlags & 1 /* TypeElement */) === 0) {
              throw new Error("Illegal State: StaticProvider/Directive nodes need to be children of elements or anchors, at index " + node.nodeIndex + "!");
          }
      }
      if (node.query) {
          if (node.flags & 67108864 /* TypeContentQuery */ &&
              (!parent || (parent.flags & 16384 /* TypeDirective */) === 0)) {
              throw new Error("Illegal State: Content Query nodes need to be children of directives, at index " + node.nodeIndex + "!");
          }
          if (node.flags & 134217728 /* TypeViewQuery */ && parent) {
              throw new Error("Illegal State: View Query nodes have to be top level nodes, at index " + node.nodeIndex + "!");
          }
      }
      if (node.childCount) {
          var parentEnd = parent ? parent.nodeIndex + parent.childCount : nodeCount - 1;
          if (node.nodeIndex <= parentEnd && node.nodeIndex + node.childCount > parentEnd) {
              throw new Error("Illegal State: childCount of node leads outside of parent, at index " + node.nodeIndex + "!");
          }
      }
  }
  function createEmbeddedView(parent, anchorDef, viewDef, context) {
      // embedded views are seen as siblings to the anchor, so we need
      // to get the parent of the anchor and use it as parentIndex.
      var view = createView(parent.root, parent.renderer, parent, anchorDef, viewDef);
      initView(view, parent.component, context);
      createViewNodes(view);
      return view;
  }
  function createRootView(root, def, context) {
      var view = createView(root, root.renderer, null, null, def);
      initView(view, context, context);
      createViewNodes(view);
      return view;
  }
  function createComponentView(parentView, nodeDef, viewDef, hostElement) {
      var rendererType = nodeDef.element.componentRendererType;
      var compRenderer;
      if (!rendererType) {
          compRenderer = parentView.root.renderer;
      }
      else {
          compRenderer = parentView.root.rendererFactory.createRenderer(hostElement, rendererType);
      }
      return createView(parentView.root, compRenderer, parentView, nodeDef.element.componentProvider, viewDef);
  }
  function createView(root, renderer, parent, parentNodeDef, def) {
      var nodes = new Array(def.nodes.length);
      var disposables = def.outputCount ? new Array(def.outputCount) : null;
      var view = {
          def: def,
          parent: parent,
          viewContainerParent: null,
          parentNodeDef: parentNodeDef,
          context: null,
          component: null,
          nodes: nodes,
          state: 13 /* CatInit */,
          root: root,
          renderer: renderer,
          oldValues: new Array(def.bindingCount),
          disposables: disposables,
          initIndex: -1
      };
      return view;
  }
  function initView(view, component, context) {
      view.component = component;
      view.context = context;
  }
  function createViewNodes(view) {
      var renderHost;
      if (isComponentView(view)) {
          var hostDef = view.parentNodeDef;
          renderHost = asElementData(view.parent, hostDef.parent.nodeIndex).renderElement;
      }
      var def = view.def;
      var nodes = view.nodes;
      for (var i = 0; i < def.nodes.length; i++) {
          var nodeDef = def.nodes[i];
          Services.setCurrentNode(view, i);
          var nodeData = void 0;
          switch (nodeDef.flags & 201347067 /* Types */) {
              case 1 /* TypeElement */:
                  var el = createElement(view, renderHost, nodeDef);
                  var componentView = undefined;
                  if (nodeDef.flags & 33554432 /* ComponentView */) {
                      var compViewDef = resolveDefinition(nodeDef.element.componentView);
                      componentView = Services.createComponentView(view, nodeDef, compViewDef, el);
                  }
                  listenToElementOutputs(view, componentView, nodeDef, el);
                  nodeData = {
                      renderElement: el,
                      componentView: componentView,
                      viewContainer: null,
                      template: nodeDef.element.template ? createTemplateData(view, nodeDef) : undefined
                  };
                  if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
                      nodeData.viewContainer = createViewContainerData(view, nodeDef, nodeData);
                  }
                  break;
              case 2 /* TypeText */:
                  nodeData = createText(view, renderHost, nodeDef);
                  break;
              case 512 /* TypeClassProvider */:
              case 1024 /* TypeFactoryProvider */:
              case 2048 /* TypeUseExistingProvider */:
              case 256 /* TypeValueProvider */: {
                  nodeData = nodes[i];
                  if (!nodeData && !(nodeDef.flags & 4096 /* LazyProvider */)) {
                      var instance = createProviderInstance(view, nodeDef);
                      nodeData = { instance: instance };
                  }
                  break;
              }
              case 16 /* TypePipe */: {
                  var instance = createPipeInstance(view, nodeDef);
                  nodeData = { instance: instance };
                  break;
              }
              case 16384 /* TypeDirective */: {
                  nodeData = nodes[i];
                  if (!nodeData) {
                      var instance = createDirectiveInstance(view, nodeDef);
                      nodeData = { instance: instance };
                  }
                  if (nodeDef.flags & 32768 /* Component */) {
                      var compView = asElementData(view, nodeDef.parent.nodeIndex).componentView;
                      initView(compView, nodeData.instance, nodeData.instance);
                  }
                  break;
              }
              case 32 /* TypePureArray */:
              case 64 /* TypePureObject */:
              case 128 /* TypePurePipe */:
                  nodeData = createPureExpression(view, nodeDef);
                  break;
              case 67108864 /* TypeContentQuery */:
              case 134217728 /* TypeViewQuery */:
                  nodeData = createQuery();
                  break;
              case 8 /* TypeNgContent */:
                  appendNgContent(view, renderHost, nodeDef);
                  // no runtime data needed for NgContent...
                  nodeData = undefined;
                  break;
          }
          nodes[i] = nodeData;
      }
      // Create the ViewData.nodes of component views after we created everything else,
      // so that e.g. ng-content works
      execComponentViewsAction(view, ViewAction.CreateViewNodes);
      // fill static content and view queries
      execQueriesAction(view, 67108864 /* TypeContentQuery */ | 134217728 /* TypeViewQuery */, 268435456 /* StaticQuery */, 0 /* CheckAndUpdate */);
  }
  function checkNoChangesView(view) {
      markProjectedViewsForCheck(view);
      Services.updateDirectives(view, 1 /* CheckNoChanges */);
      execEmbeddedViewsAction(view, ViewAction.CheckNoChanges);
      Services.updateRenderer(view, 1 /* CheckNoChanges */);
      execComponentViewsAction(view, ViewAction.CheckNoChanges);
      // Note: We don't check queries for changes as we didn't do this in v2.x.
      // TODO(tbosch): investigate if we can enable the check again in v5.x with a nicer error message.
      view.state &= ~(64 /* CheckProjectedViews */ | 32 /* CheckProjectedView */);
  }
  function checkAndUpdateView(view) {
      if (view.state & 1 /* BeforeFirstCheck */) {
          view.state &= ~1 /* BeforeFirstCheck */;
          view.state |= 2 /* FirstCheck */;
      }
      else {
          view.state &= ~2 /* FirstCheck */;
      }
      shiftInitState(view, 0 /* InitState_BeforeInit */, 256 /* InitState_CallingOnInit */);
      markProjectedViewsForCheck(view);
      Services.updateDirectives(view, 0 /* CheckAndUpdate */);
      execEmbeddedViewsAction(view, ViewAction.CheckAndUpdate);
      execQueriesAction(view, 67108864 /* TypeContentQuery */, 536870912 /* DynamicQuery */, 0 /* CheckAndUpdate */);
      var callInit = shiftInitState(view, 256 /* InitState_CallingOnInit */, 512 /* InitState_CallingAfterContentInit */);
      callLifecycleHooksChildrenFirst(view, 2097152 /* AfterContentChecked */ | (callInit ? 1048576 /* AfterContentInit */ : 0));
      Services.updateRenderer(view, 0 /* CheckAndUpdate */);
      execComponentViewsAction(view, ViewAction.CheckAndUpdate);
      execQueriesAction(view, 134217728 /* TypeViewQuery */, 536870912 /* DynamicQuery */, 0 /* CheckAndUpdate */);
      callInit = shiftInitState(view, 512 /* InitState_CallingAfterContentInit */, 768 /* InitState_CallingAfterViewInit */);
      callLifecycleHooksChildrenFirst(view, 8388608 /* AfterViewChecked */ | (callInit ? 4194304 /* AfterViewInit */ : 0));
      if (view.def.flags & 2 /* OnPush */) {
          view.state &= ~8 /* ChecksEnabled */;
      }
      view.state &= ~(64 /* CheckProjectedViews */ | 32 /* CheckProjectedView */);
      shiftInitState(view, 768 /* InitState_CallingAfterViewInit */, 1024 /* InitState_AfterInit */);
  }
  function checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      if (argStyle === 0 /* Inline */) {
          return checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
      }
      else {
          return checkAndUpdateNodeDynamic(view, nodeDef, v0);
      }
  }
  function markProjectedViewsForCheck(view) {
      var def = view.def;
      if (!(def.nodeFlags & 4 /* ProjectedTemplate */)) {
          return;
      }
      for (var i = 0; i < def.nodes.length; i++) {
          var nodeDef = def.nodes[i];
          if (nodeDef.flags & 4 /* ProjectedTemplate */) {
              var projectedViews = asElementData(view, i).template._projectedViews;
              if (projectedViews) {
                  for (var i_1 = 0; i_1 < projectedViews.length; i_1++) {
                      var projectedView = projectedViews[i_1];
                      projectedView.state |= 32 /* CheckProjectedView */;
                      markParentViewsForCheckProjectedViews(projectedView, view);
                  }
              }
          }
          else if ((nodeDef.childFlags & 4 /* ProjectedTemplate */) === 0) {
              // a parent with leafs
              // no child is a component,
              // then skip the children
              i += nodeDef.childCount;
          }
      }
  }
  function checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      switch (nodeDef.flags & 201347067 /* Types */) {
          case 1 /* TypeElement */:
              return checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
          case 2 /* TypeText */:
              return checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
          case 16384 /* TypeDirective */:
              return checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
          case 32 /* TypePureArray */:
          case 64 /* TypePureObject */:
          case 128 /* TypePurePipe */:
              return checkAndUpdatePureExpressionInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
          default:
              throw 'unreachable';
      }
  }
  function checkAndUpdateNodeDynamic(view, nodeDef, values) {
      switch (nodeDef.flags & 201347067 /* Types */) {
          case 1 /* TypeElement */:
              return checkAndUpdateElementDynamic(view, nodeDef, values);
          case 2 /* TypeText */:
              return checkAndUpdateTextDynamic(view, nodeDef, values);
          case 16384 /* TypeDirective */:
              return checkAndUpdateDirectiveDynamic(view, nodeDef, values);
          case 32 /* TypePureArray */:
          case 64 /* TypePureObject */:
          case 128 /* TypePurePipe */:
              return checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
          default:
              throw 'unreachable';
      }
  }
  function checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      if (argStyle === 0 /* Inline */) {
          checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
      }
      else {
          checkNoChangesNodeDynamic(view, nodeDef, v0);
      }
      // Returning false is ok here as we would have thrown in case of a change.
      return false;
  }
  function checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var bindLen = nodeDef.bindings.length;
      if (bindLen > 0)
          checkBindingNoChanges(view, nodeDef, 0, v0);
      if (bindLen > 1)
          checkBindingNoChanges(view, nodeDef, 1, v1);
      if (bindLen > 2)
          checkBindingNoChanges(view, nodeDef, 2, v2);
      if (bindLen > 3)
          checkBindingNoChanges(view, nodeDef, 3, v3);
      if (bindLen > 4)
          checkBindingNoChanges(view, nodeDef, 4, v4);
      if (bindLen > 5)
          checkBindingNoChanges(view, nodeDef, 5, v5);
      if (bindLen > 6)
          checkBindingNoChanges(view, nodeDef, 6, v6);
      if (bindLen > 7)
          checkBindingNoChanges(view, nodeDef, 7, v7);
      if (bindLen > 8)
          checkBindingNoChanges(view, nodeDef, 8, v8);
      if (bindLen > 9)
          checkBindingNoChanges(view, nodeDef, 9, v9);
  }
  function checkNoChangesNodeDynamic(view, nodeDef, values) {
      for (var i = 0; i < values.length; i++) {
          checkBindingNoChanges(view, nodeDef, i, values[i]);
      }
  }
  /**
   * Workaround https://github.com/angular/tsickle/issues/497
   * @suppress {misplacedTypeAnnotation}
   */
  function checkNoChangesQuery(view, nodeDef) {
      var queryList = asQueryList(view, nodeDef.nodeIndex);
      if (queryList.dirty) {
          throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, nodeDef.nodeIndex), "Query " + nodeDef.query.id + " not dirty", "Query " + nodeDef.query.id + " dirty", (view.state & 1 /* BeforeFirstCheck */) !== 0);
      }
  }
  function destroyView(view) {
      if (view.state & 128 /* Destroyed */) {
          return;
      }
      execEmbeddedViewsAction(view, ViewAction.Destroy);
      execComponentViewsAction(view, ViewAction.Destroy);
      callLifecycleHooksChildrenFirst(view, 131072 /* OnDestroy */);
      if (view.disposables) {
          for (var i = 0; i < view.disposables.length; i++) {
              view.disposables[i]();
          }
      }
      detachProjectedView(view);
      if (view.renderer.destroyNode) {
          destroyViewNodes(view);
      }
      if (isComponentView(view)) {
          view.renderer.destroy();
      }
      view.state |= 128 /* Destroyed */;
  }
  function destroyViewNodes(view) {
      var len = view.def.nodes.length;
      for (var i = 0; i < len; i++) {
          var def = view.def.nodes[i];
          if (def.flags & 1 /* TypeElement */) {
              view.renderer.destroyNode(asElementData(view, i).renderElement);
          }
          else if (def.flags & 2 /* TypeText */) {
              view.renderer.destroyNode(asTextData(view, i).renderText);
          }
          else if (def.flags & 67108864 /* TypeContentQuery */ || def.flags & 134217728 /* TypeViewQuery */) {
              asQueryList(view, i).destroy();
          }
      }
  }
  var ViewAction;
  (function (ViewAction) {
      ViewAction[ViewAction["CreateViewNodes"] = 0] = "CreateViewNodes";
      ViewAction[ViewAction["CheckNoChanges"] = 1] = "CheckNoChanges";
      ViewAction[ViewAction["CheckNoChangesProjectedViews"] = 2] = "CheckNoChangesProjectedViews";
      ViewAction[ViewAction["CheckAndUpdate"] = 3] = "CheckAndUpdate";
      ViewAction[ViewAction["CheckAndUpdateProjectedViews"] = 4] = "CheckAndUpdateProjectedViews";
      ViewAction[ViewAction["Destroy"] = 5] = "Destroy";
  })(ViewAction || (ViewAction = {}));
  function execComponentViewsAction(view, action) {
      var def = view.def;
      if (!(def.nodeFlags & 33554432 /* ComponentView */)) {
          return;
      }
      for (var i = 0; i < def.nodes.length; i++) {
          var nodeDef = def.nodes[i];
          if (nodeDef.flags & 33554432 /* ComponentView */) {
              // a leaf
              callViewAction(asElementData(view, i).componentView, action);
          }
          else if ((nodeDef.childFlags & 33554432 /* ComponentView */) === 0) {
              // a parent with leafs
              // no child is a component,
              // then skip the children
              i += nodeDef.childCount;
          }
      }
  }
  function execEmbeddedViewsAction(view, action) {
      var def = view.def;
      if (!(def.nodeFlags & 16777216 /* EmbeddedViews */)) {
          return;
      }
      for (var i = 0; i < def.nodes.length; i++) {
          var nodeDef = def.nodes[i];
          if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
              // a leaf
              var embeddedViews = asElementData(view, i).viewContainer._embeddedViews;
              for (var k = 0; k < embeddedViews.length; k++) {
                  callViewAction(embeddedViews[k], action);
              }
          }
          else if ((nodeDef.childFlags & 16777216 /* EmbeddedViews */) === 0) {
              // a parent with leafs
              // no child is a component,
              // then skip the children
              i += nodeDef.childCount;
          }
      }
  }
  function callViewAction(view, action) {
      var viewState = view.state;
      switch (action) {
          case ViewAction.CheckNoChanges:
              if ((viewState & 128 /* Destroyed */) === 0) {
                  if ((viewState & 12 /* CatDetectChanges */) === 12 /* CatDetectChanges */) {
                      checkNoChangesView(view);
                  }
                  else if (viewState & 64 /* CheckProjectedViews */) {
                      execProjectedViewsAction(view, ViewAction.CheckNoChangesProjectedViews);
                  }
              }
              break;
          case ViewAction.CheckNoChangesProjectedViews:
              if ((viewState & 128 /* Destroyed */) === 0) {
                  if (viewState & 32 /* CheckProjectedView */) {
                      checkNoChangesView(view);
                  }
                  else if (viewState & 64 /* CheckProjectedViews */) {
                      execProjectedViewsAction(view, action);
                  }
              }
              break;
          case ViewAction.CheckAndUpdate:
              if ((viewState & 128 /* Destroyed */) === 0) {
                  if ((viewState & 12 /* CatDetectChanges */) === 12 /* CatDetectChanges */) {
                      checkAndUpdateView(view);
                  }
                  else if (viewState & 64 /* CheckProjectedViews */) {
                      execProjectedViewsAction(view, ViewAction.CheckAndUpdateProjectedViews);
                  }
              }
              break;
          case ViewAction.CheckAndUpdateProjectedViews:
              if ((viewState & 128 /* Destroyed */) === 0) {
                  if (viewState & 32 /* CheckProjectedView */) {
                      checkAndUpdateView(view);
                  }
                  else if (viewState & 64 /* CheckProjectedViews */) {
                      execProjectedViewsAction(view, action);
                  }
              }
              break;
          case ViewAction.Destroy:
              // Note: destroyView recurses over all views,
              // so we don't need to special case projected views here.
              destroyView(view);
              break;
          case ViewAction.CreateViewNodes:
              createViewNodes(view);
              break;
      }
  }
  function execProjectedViewsAction(view, action) {
      execEmbeddedViewsAction(view, action);
      execComponentViewsAction(view, action);
  }
  function execQueriesAction(view, queryFlags, staticDynamicQueryFlag, checkType) {
      if (!(view.def.nodeFlags & queryFlags) || !(view.def.nodeFlags & staticDynamicQueryFlag)) {
          return;
      }
      var nodeCount = view.def.nodes.length;
      for (var i = 0; i < nodeCount; i++) {
          var nodeDef = view.def.nodes[i];
          if ((nodeDef.flags & queryFlags) && (nodeDef.flags & staticDynamicQueryFlag)) {
              Services.setCurrentNode(view, nodeDef.nodeIndex);
              switch (checkType) {
                  case 0 /* CheckAndUpdate */:
                      checkAndUpdateQuery(view, nodeDef);
                      break;
                  case 1 /* CheckNoChanges */:
                      checkNoChangesQuery(view, nodeDef);
                      break;
              }
          }
          if (!(nodeDef.childFlags & queryFlags) || !(nodeDef.childFlags & staticDynamicQueryFlag)) {
              // no child has a matching query
              // then skip the children
              i += nodeDef.childCount;
          }
      }
  }

  /**
   * @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
   */
  var initialized = false;
  function initServicesIfNeeded() {
      if (initialized) {
          return;
      }
      initialized = true;
      var services = isDevMode() ? createDebugServices() : createProdServices();
      Services.setCurrentNode = services.setCurrentNode;
      Services.createRootView = services.createRootView;
      Services.createEmbeddedView = services.createEmbeddedView;
      Services.createComponentView = services.createComponentView;
      Services.createNgModuleRef = services.createNgModuleRef;
      Services.overrideProvider = services.overrideProvider;
      Services.overrideComponentView = services.overrideComponentView;
      Services.clearOverrides = services.clearOverrides;
      Services.checkAndUpdateView = services.checkAndUpdateView;
      Services.checkNoChangesView = services.checkNoChangesView;
      Services.destroyView = services.destroyView;
      Services.resolveDep = resolveDep;
      Services.createDebugContext = services.createDebugContext;
      Services.handleEvent = services.handleEvent;
      Services.updateDirectives = services.updateDirectives;
      Services.updateRenderer = services.updateRenderer;
      Services.dirtyParentQueries = dirtyParentQueries;
  }
  function createProdServices() {
      return {
          setCurrentNode: function () { },
          createRootView: createProdRootView,
          createEmbeddedView: createEmbeddedView,
          createComponentView: createComponentView,
          createNgModuleRef: createNgModuleRef,
          overrideProvider: NOOP,
          overrideComponentView: NOOP,
          clearOverrides: NOOP,
          checkAndUpdateView: checkAndUpdateView,
          checkNoChangesView: checkNoChangesView,
          destroyView: destroyView,
          createDebugContext: function (view, nodeIndex) { return new DebugContext_(view, nodeIndex); },
          handleEvent: function (view, nodeIndex, eventName, event) {
              return view.def.handleEvent(view, nodeIndex, eventName, event);
          },
          updateDirectives: function (view, checkType) { return view.def.updateDirectives(checkType === 0 /* CheckAndUpdate */ ? prodCheckAndUpdateNode : prodCheckNoChangesNode, view); },
          updateRenderer: function (view, checkType) { return view.def.updateRenderer(checkType === 0 /* CheckAndUpdate */ ? prodCheckAndUpdateNode : prodCheckNoChangesNode, view); },
      };
  }
  function createDebugServices() {
      return {
          setCurrentNode: debugSetCurrentNode,
          createRootView: debugCreateRootView,
          createEmbeddedView: debugCreateEmbeddedView,
          createComponentView: debugCreateComponentView,
          createNgModuleRef: debugCreateNgModuleRef,
          overrideProvider: debugOverrideProvider,
          overrideComponentView: debugOverrideComponentView,
          clearOverrides: debugClearOverrides,
          checkAndUpdateView: debugCheckAndUpdateView,
          checkNoChangesView: debugCheckNoChangesView,
          destroyView: debugDestroyView,
          createDebugContext: function (view, nodeIndex) { return new DebugContext_(view, nodeIndex); },
          handleEvent: debugHandleEvent,
          updateDirectives: debugUpdateDirectives,
          updateRenderer: debugUpdateRenderer,
      };
  }
  function createProdRootView(elInjector, projectableNodes, rootSelectorOrNode, def, ngModule, context) {
      var rendererFactory = ngModule.injector.get(RendererFactory2);
      return createRootView(createRootData(elInjector, ngModule, rendererFactory, projectableNodes, rootSelectorOrNode), def, context);
  }
  function debugCreateRootView(elInjector, projectableNodes, rootSelectorOrNode, def, ngModule, context) {
      var rendererFactory = ngModule.injector.get(RendererFactory2);
      var root = createRootData(elInjector, ngModule, new DebugRendererFactory2(rendererFactory), projectableNodes, rootSelectorOrNode);
      var defWithOverride = applyProviderOverridesToView(def);
      return callWithDebugContext(DebugAction.create, createRootView, null, [root, defWithOverride, context]);
  }
  function createRootData(elInjector, ngModule, rendererFactory, projectableNodes, rootSelectorOrNode) {
      var sanitizer = ngModule.injector.get(Sanitizer);
      var errorHandler = ngModule.injector.get(ErrorHandler);
      var renderer = rendererFactory.createRenderer(null, null);
      return {
          ngModule: ngModule,
          injector: elInjector,
          projectableNodes: projectableNodes,
          selectorOrNode: rootSelectorOrNode,
          sanitizer: sanitizer,
          rendererFactory: rendererFactory,
          renderer: renderer,
          errorHandler: errorHandler
      };
  }
  function debugCreateEmbeddedView(parentView, anchorDef, viewDef, context) {
      var defWithOverride = applyProviderOverridesToView(viewDef);
      return callWithDebugContext(DebugAction.create, createEmbeddedView, null, [parentView, anchorDef, defWithOverride, context]);
  }
  function debugCreateComponentView(parentView, nodeDef, viewDef, hostElement) {
      var overrideComponentView = viewDefOverrides.get(nodeDef.element.componentProvider.provider.token);
      if (overrideComponentView) {
          viewDef = overrideComponentView;
      }
      else {
          viewDef = applyProviderOverridesToView(viewDef);
      }
      return callWithDebugContext(DebugAction.create, createComponentView, null, [parentView, nodeDef, viewDef, hostElement]);
  }
  function debugCreateNgModuleRef(moduleType, parentInjector, bootstrapComponents, def) {
      var defWithOverride = applyProviderOverridesToNgModule(def);
      return createNgModuleRef(moduleType, parentInjector, bootstrapComponents, defWithOverride);
  }
  var providerOverrides = new Map();
  var providerOverridesWithScope = new Map();
  var viewDefOverrides = new Map();
  function debugOverrideProvider(override) {
      providerOverrides.set(override.token, override);
      var injectableDef;
      if (typeof override.token === 'function' && (injectableDef = getInjectableDef(override.token)) &&
          typeof injectableDef.providedIn === 'function') {
          providerOverridesWithScope.set(override.token, override);
      }
  }
  function debugOverrideComponentView(comp, compFactory) {
      var hostViewDef = resolveDefinition(getComponentViewDefinitionFactory(compFactory));
      var compViewDef = resolveDefinition(hostViewDef.nodes[0].element.componentView);
      viewDefOverrides.set(comp, compViewDef);
  }
  function debugClearOverrides() {
      providerOverrides.clear();
      providerOverridesWithScope.clear();
      viewDefOverrides.clear();
  }
  // Notes about the algorithm:
  // 1) Locate the providers of an element and check if one of them was overwritten
  // 2) Change the providers of that element
  //
  // We only create new datastructures if we need to, to keep perf impact
  // reasonable.
  function applyProviderOverridesToView(def) {
      if (providerOverrides.size === 0) {
          return def;
      }
      var elementIndicesWithOverwrittenProviders = findElementIndicesWithOverwrittenProviders(def);
      if (elementIndicesWithOverwrittenProviders.length === 0) {
          return def;
      }
      // clone the whole view definition,
      // as it maintains references between the nodes that are hard to update.
      def = def.factory(function () { return NOOP; });
      for (var i = 0; i < elementIndicesWithOverwrittenProviders.length; i++) {
          applyProviderOverridesToElement(def, elementIndicesWithOverwrittenProviders[i]);
      }
      return def;
      function findElementIndicesWithOverwrittenProviders(def) {
          var elIndicesWithOverwrittenProviders = [];
          var lastElementDef = null;
          for (var i = 0; i < def.nodes.length; i++) {
              var nodeDef = def.nodes[i];
              if (nodeDef.flags & 1 /* TypeElement */) {
                  lastElementDef = nodeDef;
              }
              if (lastElementDef && nodeDef.flags & 3840 /* CatProviderNoDirective */ &&
                  providerOverrides.has(nodeDef.provider.token)) {
                  elIndicesWithOverwrittenProviders.push(lastElementDef.nodeIndex);
                  lastElementDef = null;
              }
          }
          return elIndicesWithOverwrittenProviders;
      }
      function applyProviderOverridesToElement(viewDef, elIndex) {
          for (var i = elIndex + 1; i < viewDef.nodes.length; i++) {
              var nodeDef = viewDef.nodes[i];
              if (nodeDef.flags & 1 /* TypeElement */) {
                  // stop at the next element
                  return;
              }
              if (nodeDef.flags & 3840 /* CatProviderNoDirective */) {
                  var provider = nodeDef.provider;
                  var override = providerOverrides.get(provider.token);
                  if (override) {
                      nodeDef.flags = (nodeDef.flags & ~3840 /* CatProviderNoDirective */) | override.flags;
                      provider.deps = splitDepsDsl(override.deps);
                      provider.value = override.value;
                  }
              }
          }
      }
  }
  // Notes about the algorithm:
  // We only create new datastructures if we need to, to keep perf impact
  // reasonable.
  function applyProviderOverridesToNgModule(def) {
      var _a = calcHasOverrides(def), hasOverrides = _a.hasOverrides, hasDeprecatedOverrides = _a.hasDeprecatedOverrides;
      if (!hasOverrides) {
          return def;
      }
      // clone the whole view definition,
      // as it maintains references between the nodes that are hard to update.
      def = def.factory(function () { return NOOP; });
      applyProviderOverrides(def);
      return def;
      function calcHasOverrides(def) {
          var hasOverrides = false;
          var hasDeprecatedOverrides = false;
          if (providerOverrides.size === 0) {
              return { hasOverrides: hasOverrides, hasDeprecatedOverrides: hasDeprecatedOverrides };
          }
          def.providers.forEach(function (node) {
              var override = providerOverrides.get(node.token);
              if ((node.flags & 3840 /* CatProviderNoDirective */) && override) {
                  hasOverrides = true;
                  hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
              }
          });
          def.modules.forEach(function (module) {
              providerOverridesWithScope.forEach(function (override, token) {
                  if (getInjectableDef(token).providedIn === module) {
                      hasOverrides = true;
                      hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
                  }
              });
          });
          return { hasOverrides: hasOverrides, hasDeprecatedOverrides: hasDeprecatedOverrides };
      }
      function applyProviderOverrides(def) {
          for (var i = 0; i < def.providers.length; i++) {
              var provider = def.providers[i];
              if (hasDeprecatedOverrides) {
                  // We had a bug where me made
                  // all providers lazy. Keep this logic behind a flag
                  // for migrating existing users.
                  provider.flags |= 4096 /* LazyProvider */;
              }
              var override = providerOverrides.get(provider.token);
              if (override) {
                  provider.flags = (provider.flags & ~3840 /* CatProviderNoDirective */) | override.flags;
                  provider.deps = splitDepsDsl(override.deps);
                  provider.value = override.value;
              }
          }
          if (providerOverridesWithScope.size > 0) {
              var moduleSet_1 = new Set(def.modules);
              providerOverridesWithScope.forEach(function (override, token) {
                  if (moduleSet_1.has(getInjectableDef(token).providedIn)) {
                      var provider = {
                          token: token,
                          flags: override.flags | (hasDeprecatedOverrides ? 4096 /* LazyProvider */ : 0 /* None */),
                          deps: splitDepsDsl(override.deps),
                          value: override.value,
                          index: def.providers.length,
                      };
                      def.providers.push(provider);
                      def.providersByKey[tokenKey(token)] = provider;
                  }
              });
          }
      }
  }
  function prodCheckAndUpdateNode(view, checkIndex, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var nodeDef = view.def.nodes[checkIndex];
      checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
      return (nodeDef.flags & 224 /* CatPureExpression */) ?
          asPureExpressionData(view, checkIndex).value :
          undefined;
  }
  function prodCheckNoChangesNode(view, checkIndex, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
      var nodeDef = view.def.nodes[checkIndex];
      checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
      return (nodeDef.flags & 224 /* CatPureExpression */) ?
          asPureExpressionData(view, checkIndex).value :
          undefined;
  }
  function debugCheckAndUpdateView(view) {
      return callWithDebugContext(DebugAction.detectChanges, checkAndUpdateView, null, [view]);
  }
  function debugCheckNoChangesView(view) {
      return callWithDebugContext(DebugAction.checkNoChanges, checkNoChangesView, null, [view]);
  }
  function debugDestroyView(view) {
      return callWithDebugContext(DebugAction.destroy, destroyView, null, [view]);
  }
  var DebugAction;
  (function (DebugAction) {
      DebugAction[DebugAction["create"] = 0] = "create";
      DebugAction[DebugAction["detectChanges"] = 1] = "detectChanges";
      DebugAction[DebugAction["checkNoChanges"] = 2] = "checkNoChanges";
      DebugAction[DebugAction["destroy"] = 3] = "destroy";
      DebugAction[DebugAction["handleEvent"] = 4] = "handleEvent";
  })(DebugAction || (DebugAction = {}));
  var _currentAction;
  var _currentView;
  var _currentNodeIndex;
  function debugSetCurrentNode(view, nodeIndex) {
      _currentView = view;
      _currentNodeIndex = nodeIndex;
  }
  function debugHandleEvent(view, nodeIndex, eventName, event) {
      debugSetCurrentNode(view, nodeIndex);
      return callWithDebugContext(DebugAction.handleEvent, view.def.handleEvent, null, [view, nodeIndex, eventName, event]);
  }
  function debugUpdateDirectives(view, checkType) {
      if (view.state & 128 /* Destroyed */) {
          throw viewDestroyedError(DebugAction[_currentAction]);
      }
      debugSetCurrentNode(view, nextDirectiveWithBinding(view, 0));
      return view.def.updateDirectives(debugCheckDirectivesFn, view);
      function debugCheckDirectivesFn(view, nodeIndex, argStyle) {
          var values = [];
          for (var _i = 3; _i < arguments.length; _i++) {
              values[_i - 3] = arguments[_i];
          }
          var nodeDef = view.def.nodes[nodeIndex];
          if (checkType === 0 /* CheckAndUpdate */) {
              debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
          }
          else {
              debugCheckNoChangesNode(view, nodeDef, argStyle, values);
          }
          if (nodeDef.flags & 16384 /* TypeDirective */) {
              debugSetCurrentNode(view, nextDirectiveWithBinding(view, nodeIndex));
          }
          return (nodeDef.flags & 224 /* CatPureExpression */) ?
              asPureExpressionData(view, nodeDef.nodeIndex).value :
              undefined;
      }
  }
  function debugUpdateRenderer(view, checkType) {
      if (view.state & 128 /* Destroyed */) {
          throw viewDestroyedError(DebugAction[_currentAction]);
      }
      debugSetCurrentNode(view, nextRenderNodeWithBinding(view, 0));
      return view.def.updateRenderer(debugCheckRenderNodeFn, view);
      function debugCheckRenderNodeFn(view, nodeIndex, argStyle) {
          var values = [];
          for (var _i = 3; _i < arguments.length; _i++) {
              values[_i - 3] = arguments[_i];
          }
          var nodeDef = view.def.nodes[nodeIndex];
          if (checkType === 0 /* CheckAndUpdate */) {
              debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
          }
          else {
              debugCheckNoChangesNode(view, nodeDef, argStyle, values);
          }
          if (nodeDef.flags & 3 /* CatRenderNode */) {
              debugSetCurrentNode(view, nextRenderNodeWithBinding(view, nodeIndex));
          }
          return (nodeDef.flags & 224 /* CatPureExpression */) ?
              asPureExpressionData(view, nodeDef.nodeIndex).value :
              undefined;
      }
  }
  function debugCheckAndUpdateNode(view, nodeDef, argStyle, givenValues) {
      var changed = checkAndUpdateNode.apply(void 0, __spread([view, nodeDef, argStyle], givenValues));
      if (changed) {
          var values = argStyle === 1 /* Dynamic */ ? givenValues[0] : givenValues;
          if (nodeDef.flags & 16384 /* TypeDirective */) {
              var bindingValues = {};
              for (var i = 0; i < nodeDef.bindings.length; i++) {
                  var binding = nodeDef.bindings[i];
                  var value = values[i];
                  if (binding.flags & 8 /* TypeProperty */) {
                      bindingValues[normalizeDebugBindingName(binding.nonMinifiedName)] =
                          normalizeDebugBindingValue(value);
                  }
              }
              var elDef = nodeDef.parent;
              var el = asElementData(view, elDef.nodeIndex).renderElement;
              if (!elDef.element.name) {
                  // a comment.
                  view.renderer.setValue(el, "bindings=" + JSON.stringify(bindingValues, null, 2));
              }
              else {
                  // a regular element.
                  for (var attr in bindingValues) {
                      var value = bindingValues[attr];
                      if (value != null) {
                          view.renderer.setAttribute(el, attr, value);
                      }
                      else {
                          view.renderer.removeAttribute(el, attr);
                      }
                  }
              }
          }
      }
  }
  function debugCheckNoChangesNode(view, nodeDef, argStyle, values) {
      checkNoChangesNode.apply(void 0, __spread([view, nodeDef, argStyle], values));
  }
  function nextDirectiveWithBinding(view, nodeIndex) {
      for (var i = nodeIndex; i < view.def.nodes.length; i++) {
          var nodeDef = view.def.nodes[i];
          if (nodeDef.flags & 16384 /* TypeDirective */ && nodeDef.bindings && nodeDef.bindings.length) {
              return i;
          }
      }
      return null;
  }
  function nextRenderNodeWithBinding(view, nodeIndex) {
      for (var i = nodeIndex; i < view.def.nodes.length; i++) {
          var nodeDef = view.def.nodes[i];
          if ((nodeDef.flags & 3 /* CatRenderNode */) && nodeDef.bindings && nodeDef.bindings.length) {
              return i;
          }
      }
      return null;
  }
  var DebugContext_ = /** @class */ (function () {
      function DebugContext_(view, nodeIndex) {
          this.view = view;
          this.nodeIndex = nodeIndex;
          if (nodeIndex == null) {
              this.nodeIndex = nodeIndex = 0;
          }
          this.nodeDef = view.def.nodes[nodeIndex];
          var elDef = this.nodeDef;
          var elView = view;
          while (elDef && (elDef.flags & 1 /* TypeElement */) === 0) {
              elDef = elDef.parent;
          }
          if (!elDef) {
              while (!elDef && elView) {
                  elDef = viewParentEl(elView);
                  elView = elView.parent;
              }
          }
          this.elDef = elDef;
          this.elView = elView;
      }
      Object.defineProperty(DebugContext_.prototype, "elOrCompView", {
          get: function () {
              // Has to be done lazily as we use the DebugContext also during creation of elements...
              return asElementData(this.elView, this.elDef.nodeIndex).componentView || this.view;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "injector", {
          get: function () {
              return createInjector$1(this.elView, this.elDef);
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "component", {
          get: function () {
              return this.elOrCompView.component;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "context", {
          get: function () {
              return this.elOrCompView.context;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "providerTokens", {
          get: function () {
              var tokens = [];
              if (this.elDef) {
                  for (var i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount; i++) {
                      var childDef = this.elView.def.nodes[i];
                      if (childDef.flags & 20224 /* CatProvider */) {
                          tokens.push(childDef.provider.token);
                      }
                      i += childDef.childCount;
                  }
              }
              return tokens;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "references", {
          get: function () {
              var references = {};
              if (this.elDef) {
                  collectReferences(this.elView, this.elDef, references);
                  for (var i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount; i++) {
                      var childDef = this.elView.def.nodes[i];
                      if (childDef.flags & 20224 /* CatProvider */) {
                          collectReferences(this.elView, childDef, references);
                      }
                      i += childDef.childCount;
                  }
              }
              return references;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "componentRenderElement", {
          get: function () {
              var elData = findHostElement(this.elOrCompView);
              return elData ? elData.renderElement : undefined;
          },
          enumerable: true,
          configurable: true
      });
      Object.defineProperty(DebugContext_.prototype, "renderNode", {
          get: function () {
              return this.nodeDef.flags & 2 /* TypeText */ ? renderNode(this.view, this.nodeDef) :
                  renderNode(this.elView, this.elDef);
          },
          enumerable: true,
          configurable: true
      });
      DebugContext_.prototype.logError = function (console) {
          var values = [];
          for (var _i = 1; _i < arguments.length; _i++) {
              values[_i - 1] = arguments[_i];
          }
          var logViewDef;
          var logNodeIndex;
          if (this.nodeDef.flags & 2 /* TypeText */) {
              logViewDef = this.view.def;
              logNodeIndex = this.nodeDef.nodeIndex;
          }
          else {
              logViewDef = this.elView.def;
              logNodeIndex = this.elDef.nodeIndex;
          }
          // Note: we only generate a log function for text and element nodes
          // to make the generated code as small as possible.
          var renderNodeIndex = getRenderNodeIndex(logViewDef, logNodeIndex);
          var currRenderNodeIndex = -1;
          var nodeLogger = function () {
              var _a;
              currRenderNodeIndex++;
              if (currRenderNodeIndex === renderNodeIndex) {
                  return (_a = console.error).bind.apply(_a, __spread([console], values));
              }
              else {
                  return NOOP;
              }
          };
          logViewDef.factory(nodeLogger);
          if (currRenderNodeIndex < renderNodeIndex) {
              console.error('Illegal state: the ViewDefinitionFactory did not call the logger!');
              console.error.apply(console, __spread(values));
          }
      };
      return DebugContext_;
  }());
  function getRenderNodeIndex(viewDef, nodeIndex) {
      var renderNodeIndex = -1;
      for (var i = 0; i <= nodeIndex; i++) {
          var nodeDef = viewDef.nodes[i];
          if (nodeDef.flags & 3 /* CatRenderNode */) {
              renderNodeIndex++;
          }
      }
      return renderNodeIndex;
  }
  function findHostElement(view) {
      while (view && !isComponentView(view)) {
          view = view.parent;
      }
      if (view.parent) {
          return asElementData(view.parent, viewParentEl(view).nodeIndex);
      }
      return null;
  }
  function collectReferences(view, nodeDef, references) {
      for (var refName in nodeDef.references) {
          references[refName] = getQueryValue(view, nodeDef, nodeDef.references[refName]);
      }
  }
  function callWithDebugContext(action, fn, self, args) {
      var oldAction = _currentAction;
      var oldView = _currentView;
      var oldNodeIndex = _currentNodeIndex;
      try {
          _currentAction = action;
          var result = fn.apply(self, args);
          _currentView = oldView;
          _currentNodeIndex = oldNodeIndex;
          _currentAction = oldAction;
          return result;
      }
      catch (e) {
          if (isViewDebugError(e) || !_currentView) {
              throw e;
          }
          throw viewWrappedDebugError(e, getCurrentDebugContext());
      }
  }
  function getCurrentDebugContext() {
      return _currentView ? new DebugContext_(_currentView, _currentNodeIndex) : null;
  }
  var DebugRendererFactory2 = /** @class */ (function () {
      function DebugRendererFactory2(delegate) {
          this.delegate = delegate;
      }
      DebugRendererFactory2.prototype.createRenderer = function (element, renderData) {
          return new DebugRenderer2(this.delegate.createRenderer(element, renderData));
      };
      DebugRendererFactory2.prototype.begin = function () {
          if (this.delegate.begin) {
              this.delegate.begin();
          }
      };
      DebugRendererFactory2.prototype.end = function () {
          if (this.delegate.end) {
              this.delegate.end();
          }
      };
      DebugRendererFactory2.prototype.whenRenderingDone = function () {
          if (this.delegate.whenRenderingDone) {
              return this.delegate.whenRenderingDone();
          }
          return Promise.resolve(null);
      };
      return DebugRendererFactory2;
  }());
  var DebugRenderer2 = /** @class */ (function () {
      function DebugRenderer2(delegate) {
          this.delegate = delegate;
          /**
           * Factory function used to create a `DebugContext` when a node is created.
           *
           * The `DebugContext` allows to retrieve information about the nodes that are useful in tests.
           *
           * The factory is configurable so that the `DebugRenderer2` could instantiate either a View Engine
           * or a Render context.
           */
          this.debugContextFactory = getCurrentDebugContext;
          this.data = this.delegate.data;
      }
      DebugRenderer2.prototype.createDebugContext = function (nativeElement) {
          return this.debugContextFactory(nativeElement);
      };
      DebugRenderer2.prototype.destroyNode = function (node) {
          var debugNode = getDebugNode$1(node);
          removeDebugNodeFromIndex(debugNode);
          if (debugNode instanceof DebugNode__PRE_R3__) {
              debugNode.listeners.length = 0;
          }
          if (this.delegate.destroyNode) {
              this.delegate.destroyNode(node);
          }
      };
      DebugRenderer2.prototype.destroy = function () {
          this.delegate.destroy();
      };
      DebugRenderer2.prototype.createElement = function (name, namespace) {
          var el = this.delegate.createElement(name, namespace);
          var debugCtx = this.createDebugContext(el);
          if (debugCtx) {
              var debugEl = new DebugElement__PRE_R3__(el, null, debugCtx);
              debugEl.name = name;
              indexDebugNode(debugEl);
          }
          return el;
      };
      DebugRenderer2.prototype.createComment = function (value) {
          var comment = this.delegate.createComment(value);
          var debugCtx = this.createDebugContext(comment);
          if (debugCtx) {
              indexDebugNode(new DebugNode__PRE_R3__(comment, null, debugCtx));
          }
          return comment;
      };
      DebugRenderer2.prototype.createText = function (value) {
          var text = this.delegate.createText(value);
          var debugCtx = this.createDebugContext(text);
          if (debugCtx) {
              indexDebugNode(new DebugNode__PRE_R3__(text, null, debugCtx));
          }
          return text;
      };
      DebugRenderer2.prototype.appendChild = function (parent, newChild) {
          var debugEl = getDebugNode$1(parent);
          var debugChildEl = getDebugNode$1(newChild);
          if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.addChild(debugChildEl);
          }
          this.delegate.appendChild(parent, newChild);
      };
      DebugRenderer2.prototype.insertBefore = function (parent, newChild, refChild) {
          var debugEl = getDebugNode$1(parent);
          var debugChildEl = getDebugNode$1(newChild);
          var debugRefEl = getDebugNode$1(refChild);
          if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.insertBefore(debugRefEl, debugChildEl);
          }
          this.delegate.insertBefore(parent, newChild, refChild);
      };
      DebugRenderer2.prototype.removeChild = function (parent, oldChild) {
          var debugEl = getDebugNode$1(parent);
          var debugChildEl = getDebugNode$1(oldChild);
          if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.removeChild(debugChildEl);
          }
          this.delegate.removeChild(parent, oldChild);
      };
      DebugRenderer2.prototype.selectRootElement = function (selectorOrNode, preserveContent) {
          var el = this.delegate.selectRootElement(selectorOrNode, preserveContent);
          var debugCtx = getCurrentDebugContext();
          if (debugCtx) {
              indexDebugNode(new DebugElement__PRE_R3__(el, null, debugCtx));
          }
          return el;
      };
      DebugRenderer2.prototype.setAttribute = function (el, name, value, namespace) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              var fullName = namespace ? namespace + ':' + name : name;
              debugEl.attributes[fullName] = value;
          }
          this.delegate.setAttribute(el, name, value, namespace);
      };
      DebugRenderer2.prototype.removeAttribute = function (el, name, namespace) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              var fullName = namespace ? namespace + ':' + name : name;
              debugEl.attributes[fullName] = null;
          }
          this.delegate.removeAttribute(el, name, namespace);
      };
      DebugRenderer2.prototype.addClass = function (el, name) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.classes[name] = true;
          }
          this.delegate.addClass(el, name);
      };
      DebugRenderer2.prototype.removeClass = function (el, name) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.classes[name] = false;
          }
          this.delegate.removeClass(el, name);
      };
      DebugRenderer2.prototype.setStyle = function (el, style, value, flags) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.styles[style] = value;
          }
          this.delegate.setStyle(el, style, value, flags);
      };
      DebugRenderer2.prototype.removeStyle = function (el, style, flags) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.styles[style] = null;
          }
          this.delegate.removeStyle(el, style, flags);
      };
      DebugRenderer2.prototype.setProperty = function (el, name, value) {
          var debugEl = getDebugNode$1(el);
          if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
              debugEl.properties[name] = value;
          }
          this.delegate.setProperty(el, name, value);
      };
      DebugRenderer2.prototype.listen = function (target, eventName, callback) {
          if (typeof target !== 'string') {
              var debugEl = getDebugNode$1(target);
              if (debugEl) {
                  debugEl.listeners.push(new DebugEventListener(eventName, callback));
              }
          }
          return this.delegate.listen(target, eventName, callback);
      };
      DebugRenderer2.prototype.parentNode = function (node) {
          return this.delegate.parentNode(node);
      };
      DebugRenderer2.prototype.nextSibling = function (node) {
          return this.delegate.nextSibling(node);
      };
      DebugRenderer2.prototype.setValue = function (node, value) {
          return this.delegate.setValue(node, value);
      };
      return DebugRenderer2;
  }());

  /**
   * @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
   */
  function overrideProvider(override) {
      initServicesIfNeeded();
      return Services.overrideProvider(override);
  }
  function overrideComponentView(comp, componentFactory) {
      initServicesIfNeeded();
      return Services.overrideComponentView(comp, componentFactory);
  }
  function clearOverrides() {
      initServicesIfNeeded();
      return Services.clearOverrides();
  }
  // Attention: this function is called as top level function.
  // Putting any logic in here will destroy closure tree shaking!
  function createNgModuleFactory(ngModuleType, bootstrapComponents, defFactory) {
      return new NgModuleFactory_(ngModuleType, bootstrapComponents, defFactory);
  }
  function cloneNgModuleDefinition(def) {
      var providers = Array.from(def.providers);
      var modules = Array.from(def.modules);
      var providersByKey = {};
      for (var key in def.providersByKey) {
          providersByKey[key] = def.providersByKey[key];
      }
      return {
          factory: def.factory,
          scope: def.scope,
          providers: providers,
          modules: modules,
          providersByKey: providersByKey,
      };
  }
  var NgModuleFactory_ = /** @class */ (function (_super) {
      __extends(NgModuleFactory_, _super);
      function NgModuleFactory_(moduleType, _bootstrapComponents, _ngModuleDefFactory) {
          var _this = 
          // Attention: this ctor is called as top level function.
          // Putting any logic in here will destroy closure tree shaking!
          _super.call(this) || this;
          _this.moduleType = moduleType;
          _this._bootstrapComponents = _bootstrapComponents;
          _this._ngModuleDefFactory = _ngModuleDefFactory;
          return _this;
      }
      NgModuleFactory_.prototype.create = function (parentInjector) {
          initServicesIfNeeded();
          // Clone the NgModuleDefinition so that any tree shakeable provider definition
          // added to this instance of the NgModuleRef doesn't affect the cached copy.
          // See https://github.com/angular/angular/issues/25018.
          var def = cloneNgModuleDefinition(resolveDefinition(this._ngModuleDefFactory));
          return Services.createNgModuleRef(this.moduleType, parentInjector || Injector.NULL, this._bootstrapComponents, def);
      };
      return NgModuleFactory_;
  }(NgModuleFactory));

  /**
   * @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
   */

  /**
   * @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
   */

  /**
   * @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
   */
  // clang-format on

  /**
   * @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
   */

  /**
   * @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
   */
  if (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 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
   */
  // This file only reexports content of the `src` folder. Keep it that way.

  /**
   * @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
   */

  /**
   * Generated bundle index. Do not edit.
   */

  exports.ANALYZE_FOR_ENTRY_COMPONENTS = ANALYZE_FOR_ENTRY_COMPONENTS;
  exports.APP_BOOTSTRAP_LISTENER = APP_BOOTSTRAP_LISTENER;
  exports.APP_ID = APP_ID;
  exports.APP_INITIALIZER = APP_INITIALIZER;
  exports.ApplicationInitStatus = ApplicationInitStatus;
  exports.ApplicationModule = ApplicationModule;
  exports.ApplicationRef = ApplicationRef;
  exports.Attribute = Attribute;
  exports.COMPILER_OPTIONS = COMPILER_OPTIONS;
  exports.CUSTOM_ELEMENTS_SCHEMA = CUSTOM_ELEMENTS_SCHEMA;
  exports.ChangeDetectorRef = ChangeDetectorRef;
  exports.Compiler = Compiler;
  exports.CompilerFactory = CompilerFactory;
  exports.Component = Component;
  exports.ComponentFactory = ComponentFactory;
  exports.ComponentFactoryResolver = ComponentFactoryResolver;
  exports.ComponentRef = ComponentRef;
  exports.ContentChild = ContentChild;
  exports.ContentChildren = ContentChildren;
  exports.DEFAULT_CURRENCY_CODE = DEFAULT_CURRENCY_CODE;
  exports.DebugElement = DebugElement;
  exports.DebugEventListener = DebugEventListener;
  exports.DebugNode = DebugNode;
  exports.DefaultIterableDiffer = DefaultIterableDiffer;
  exports.Directive = Directive;
  exports.ElementRef = ElementRef;
  exports.EmbeddedViewRef = EmbeddedViewRef;
  exports.ErrorHandler = ErrorHandler;
  exports.EventEmitter = EventEmitter;
  exports.Host = Host;
  exports.HostBinding = HostBinding;
  exports.HostListener = HostListener;
  exports.INJECTOR = INJECTOR;
  exports.Inject = Inject;
  exports.Injectable = Injectable;
  exports.InjectionToken = InjectionToken;
  exports.Injector = Injector;
  exports.Input = Input;
  exports.IterableDiffers = IterableDiffers;
  exports.KeyValueDiffers = KeyValueDiffers;
  exports.LOCALE_ID = LOCALE_ID$1;
  exports.ModuleWithComponentFactories = ModuleWithComponentFactories;
  exports.NO_ERRORS_SCHEMA = NO_ERRORS_SCHEMA;
  exports.NgModule = NgModule;
  exports.NgModuleFactory = NgModuleFactory;
  exports.NgModuleFactoryLoader = NgModuleFactoryLoader;
  exports.NgModuleRef = NgModuleRef;
  exports.NgProbeToken = NgProbeToken;
  exports.NgZone = NgZone;
  exports.Optional = Optional;
  exports.Output = Output;
  exports.PACKAGE_ROOT_URL = PACKAGE_ROOT_URL;
  exports.PLATFORM_ID = PLATFORM_ID;
  exports.PLATFORM_INITIALIZER = PLATFORM_INITIALIZER;
  exports.Pipe = Pipe;
  exports.PlatformRef = PlatformRef;
  exports.Query = Query;
  exports.QueryList = QueryList;
  exports.ReflectiveInjector = ReflectiveInjector;
  exports.ReflectiveKey = ReflectiveKey;
  exports.Renderer2 = Renderer2;
  exports.RendererFactory2 = RendererFactory2;
  exports.ResolvedReflectiveFactory = ResolvedReflectiveFactory;
  exports.Sanitizer = Sanitizer;
  exports.Self = Self;
  exports.SimpleChange = SimpleChange;
  exports.SkipSelf = SkipSelf;
  exports.SystemJsNgModuleLoader = SystemJsNgModuleLoader;
  exports.SystemJsNgModuleLoaderConfig = SystemJsNgModuleLoaderConfig;
  exports.TRANSLATIONS = TRANSLATIONS;
  exports.TRANSLATIONS_FORMAT = TRANSLATIONS_FORMAT;
  exports.TemplateRef = TemplateRef;
  exports.Testability = Testability;
  exports.TestabilityRegistry = TestabilityRegistry;
  exports.Type = Type;
  exports.VERSION = VERSION;
  exports.Version = Version;
  exports.ViewChild = ViewChild;
  exports.ViewChildren = ViewChildren;
  exports.ViewContainerRef = ViewContainerRef;
  exports.ViewRef = ViewRef$1;
  exports.WrappedValue = WrappedValue;
  exports.asNativeElements = asNativeElements;
  exports.assertPlatform = assertPlatform;
  exports.createPlatform = createPlatform;
  exports.createPlatformFactory = createPlatformFactory;
  exports.defineInjectable = defineInjectable;
  exports.destroyPlatform = destroyPlatform;
  exports.enableProdMode = enableProdMode;
  exports.forwardRef = forwardRef;
  exports.getDebugNode = getDebugNode$1;
  exports.getModuleFactory = getModuleFactory;
  exports.getPlatform = getPlatform;
  exports.inject = inject;
  exports.isDevMode = isDevMode;
  exports.platformCore = platformCore;
  exports.resolveForwardRef = resolveForwardRef;
  exports.setTestabilityGetter = setTestabilityGetter;
  exports.ɵ0 = ɵ0;
  exports.ɵ1 = ɵ1;
  exports.ɵALLOW_MULTIPLE_PLATFORMS = ALLOW_MULTIPLE_PLATFORMS;
  exports.ɵAPP_ID_RANDOM_PROVIDER = APP_ID_RANDOM_PROVIDER;
  exports.ɵCodegenComponentFactoryResolver = CodegenComponentFactoryResolver;
  exports.ɵCompiler_compileModuleAndAllComponentsAsync__POST_R3__ = Compiler_compileModuleAndAllComponentsAsync__POST_R3__;
  exports.ɵCompiler_compileModuleAndAllComponentsSync__POST_R3__ = Compiler_compileModuleAndAllComponentsSync__POST_R3__;
  exports.ɵCompiler_compileModuleAsync__POST_R3__ = Compiler_compileModuleAsync__POST_R3__;
  exports.ɵCompiler_compileModuleSync__POST_R3__ = Compiler_compileModuleSync__POST_R3__;
  exports.ɵComponentFactory = ComponentFactory;
  exports.ɵConsole = Console;
  exports.ɵDEFAULT_LOCALE_ID = DEFAULT_LOCALE_ID;
  exports.ɵEMPTY_ARRAY = EMPTY_ARRAY$4;
  exports.ɵEMPTY_MAP = EMPTY_MAP;
  exports.ɵINJECTOR_IMPL__POST_R3__ = INJECTOR_IMPL__POST_R3__;
  exports.ɵINJECTOR_SCOPE = INJECTOR_SCOPE;
  exports.ɵLifecycleHooksFeature = LifecycleHooksFeature;
  exports.ɵNG_COMP_DEF = NG_COMP_DEF;
  exports.ɵNG_DIR_DEF = NG_DIR_DEF;
  exports.ɵNG_ELEMENT_ID = NG_ELEMENT_ID;
  exports.ɵNG_INJ_DEF = NG_INJ_DEF;
  exports.ɵNG_MOD_DEF = NG_MOD_DEF;
  exports.ɵNG_PIPE_DEF = NG_PIPE_DEF;
  exports.ɵNG_PROV_DEF = NG_PROV_DEF;
  exports.ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR;
  exports.ɵNO_CHANGE = NO_CHANGE;
  exports.ɵNgModuleFactory = NgModuleFactory$1;
  exports.ɵNoopNgZone = NoopNgZone;
  exports.ɵReflectionCapabilities = ReflectionCapabilities;
  exports.ɵRender3ComponentFactory = ComponentFactory$1;
  exports.ɵRender3ComponentRef = ComponentRef$1;
  exports.ɵRender3NgModuleRef = NgModuleRef$1;
  exports.ɵSWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ = SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__;
  exports.ɵSWITCH_COMPILE_COMPONENT__POST_R3__ = SWITCH_COMPILE_COMPONENT__POST_R3__;
  exports.ɵSWITCH_COMPILE_DIRECTIVE__POST_R3__ = SWITCH_COMPILE_DIRECTIVE__POST_R3__;
  exports.ɵSWITCH_COMPILE_INJECTABLE__POST_R3__ = SWITCH_COMPILE_INJECTABLE__POST_R3__;
  exports.ɵSWITCH_COMPILE_NGMODULE__POST_R3__ = SWITCH_COMPILE_NGMODULE__POST_R3__;
  exports.ɵSWITCH_COMPILE_PIPE__POST_R3__ = SWITCH_COMPILE_PIPE__POST_R3__;
  exports.ɵSWITCH_ELEMENT_REF_FACTORY__POST_R3__ = SWITCH_ELEMENT_REF_FACTORY__POST_R3__;
  exports.ɵSWITCH_IVY_ENABLED__POST_R3__ = SWITCH_IVY_ENABLED__POST_R3__;
  exports.ɵSWITCH_RENDERER2_FACTORY__POST_R3__ = SWITCH_RENDERER2_FACTORY__POST_R3__;
  exports.ɵSWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__;
  exports.ɵSWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__ = SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__;
  exports.ɵ_sanitizeHtml = _sanitizeHtml;
  exports.ɵ_sanitizeStyle = _sanitizeStyle;
  exports.ɵ_sanitizeUrl = _sanitizeUrl;
  exports.ɵallowSanitizationBypassAndThrow = allowSanitizationBypassAndThrow;
  exports.ɵand = anchorDef;
  exports.ɵangular_packages_core_core_a = isForwardRef;
  exports.ɵangular_packages_core_core_b = injectInjectorOnly;
  exports.ɵangular_packages_core_core_ba = getLView;
  exports.ɵangular_packages_core_core_bb = getPreviousOrParentTNode;
  exports.ɵangular_packages_core_core_bc = getBindingRoot;
  exports.ɵangular_packages_core_core_bd = nextContextImpl;
  exports.ɵangular_packages_core_core_bf = pureFunction1Internal;
  exports.ɵangular_packages_core_core_bg = pureFunction2Internal;
  exports.ɵangular_packages_core_core_bh = pureFunction3Internal;
  exports.ɵangular_packages_core_core_bi = pureFunction4Internal;
  exports.ɵangular_packages_core_core_bj = pureFunctionVInternal;
  exports.ɵangular_packages_core_core_bk = getUrlSanitizer;
  exports.ɵangular_packages_core_core_bl = makeParamDecorator;
  exports.ɵangular_packages_core_core_bm = makePropDecorator;
  exports.ɵangular_packages_core_core_bn = getClosureSafeProperty;
  exports.ɵangular_packages_core_core_bp = noSideEffects;
  exports.ɵangular_packages_core_core_bq = getRootContext;
  exports.ɵangular_packages_core_core_c = NullInjector;
  exports.ɵangular_packages_core_core_d = ReflectiveInjector_;
  exports.ɵangular_packages_core_core_e = ReflectiveDependency;
  exports.ɵangular_packages_core_core_f = resolveReflectiveProviders;
  exports.ɵangular_packages_core_core_g = _appIdRandomProviderFactory;
  exports.ɵangular_packages_core_core_h = createElementRef;
  exports.ɵangular_packages_core_core_i = createTemplateRef;
  exports.ɵangular_packages_core_core_j = getModuleFactory__PRE_R3__;
  exports.ɵangular_packages_core_core_k = DebugNode__PRE_R3__;
  exports.ɵangular_packages_core_core_l = DebugElement__PRE_R3__;
  exports.ɵangular_packages_core_core_m = getDebugNodeR2__PRE_R3__;
  exports.ɵangular_packages_core_core_n = DefaultIterableDifferFactory;
  exports.ɵangular_packages_core_core_o = DefaultKeyValueDifferFactory;
  exports.ɵangular_packages_core_core_p = _iterableDiffersFactory;
  exports.ɵangular_packages_core_core_q = _keyValueDiffersFactory;
  exports.ɵangular_packages_core_core_r = _localeFactory;
  exports.ɵangular_packages_core_core_s = APPLICATION_MODULE_PROVIDERS;
  exports.ɵangular_packages_core_core_t = zoneSchedulerFactory;
  exports.ɵangular_packages_core_core_u = USD_CURRENCY_CODE;
  exports.ɵangular_packages_core_core_v = _def;
  exports.ɵangular_packages_core_core_w = DebugContext;
  exports.ɵangular_packages_core_core_x = SCHEDULER;
  exports.ɵangular_packages_core_core_y = injectAttributeImpl;
  exports.ɵangular_packages_core_core_z = instructionState;
  exports.ɵbypassSanitizationTrustHtml = bypassSanitizationTrustHtml;
  exports.ɵbypassSanitizationTrustResourceUrl = bypassSanitizationTrustResourceUrl;
  exports.ɵbypassSanitizationTrustScript = bypassSanitizationTrustScript;
  exports.ɵbypassSanitizationTrustStyle = bypassSanitizationTrustStyle;
  exports.ɵbypassSanitizationTrustUrl = bypassSanitizationTrustUrl;
  exports.ɵccf = createComponentFactory;
  exports.ɵclearOverrides = clearOverrides;
  exports.ɵclearResolutionOfComponentResourcesQueue = clearResolutionOfComponentResourcesQueue;
  exports.ɵcmf = createNgModuleFactory;
  exports.ɵcompileComponent = compileComponent;
  exports.ɵcompileDirective = compileDirective;
  exports.ɵcompileNgModule = compileNgModule;
  exports.ɵcompileNgModuleDefs = compileNgModuleDefs;
  exports.ɵcompileNgModuleFactory__POST_R3__ = compileNgModuleFactory__POST_R3__;
  exports.ɵcompilePipe = compilePipe;
  exports.ɵcreateInjector = createInjector;
  exports.ɵcrt = createRendererType2;
  exports.ɵdefaultIterableDiffers = defaultIterableDiffers;
  exports.ɵdefaultKeyValueDiffers = defaultKeyValueDiffers;
  exports.ɵdetectChanges = detectChanges;
  exports.ɵdevModeEqual = devModeEqual$1;
  exports.ɵdid = directiveDef;
  exports.ɵeld = elementDef;
  exports.ɵfindLocaleData = findLocaleData;
  exports.ɵflushModuleScopingQueueAsMuchAsPossible = flushModuleScopingQueueAsMuchAsPossible;
  exports.ɵgetComponentViewDefinitionFactory = getComponentViewDefinitionFactory;
  exports.ɵgetDebugNodeR2 = getDebugNodeR2;
  exports.ɵgetDebugNode__POST_R3__ = getDebugNode__POST_R3__;
  exports.ɵgetDirectives = getDirectives;
  exports.ɵgetHostElement = getHostElement;
  exports.ɵgetInjectableDef = getInjectableDef;
  exports.ɵgetLContext = getLContext;
  exports.ɵgetLocaleCurrencyCode = getLocaleCurrencyCode;
  exports.ɵgetLocalePluralCase = getLocalePluralCase;
  exports.ɵgetModuleFactory__POST_R3__ = getModuleFactory__POST_R3__;
  exports.ɵgetSanitizationBypassType = getSanitizationBypassType;
  exports.ɵglobal = _global;
  exports.ɵinitServicesIfNeeded = initServicesIfNeeded;
  exports.ɵinlineInterpolate = inlineInterpolate;
  exports.ɵinterpolate = interpolate;
  exports.ɵisBoundToModule__POST_R3__ = isBoundToModule__POST_R3__;
  exports.ɵisDefaultChangeDetectionStrategy = isDefaultChangeDetectionStrategy;
  exports.ɵisListLikeIterable = isListLikeIterable$1;
  exports.ɵisObservable = isObservable;
  exports.ɵisPromise = isPromise;
  exports.ɵivyEnabled = ivyEnabled;
  exports.ɵlooseIdentical = looseIdentical;
  exports.ɵmakeDecorator = makeDecorator;
  exports.ɵmarkDirty = markDirty;
  exports.ɵmod = moduleDef;
  exports.ɵmpd = moduleProvideDef;
  exports.ɵncd = ngContentDef;
  exports.ɵnov = nodeValue;
  exports.ɵoverrideComponentView = overrideComponentView;
  exports.ɵoverrideProvider = overrideProvider;
  exports.ɵpad = pureArrayDef;
  exports.ɵpatchComponentDefWithScope = patchComponentDefWithScope;
  exports.ɵpid = pipeDef;
  exports.ɵpod = pureObjectDef;
  exports.ɵppd = purePipeDef;
  exports.ɵprd = providerDef;
  exports.ɵpublishDefaultGlobalUtils = publishDefaultGlobalUtils;
  exports.ɵpublishGlobalUtil = publishGlobalUtil;
  exports.ɵqud = queryDef;
  exports.ɵregisterLocaleData = registerLocaleData;
  exports.ɵregisterModuleFactory = registerModuleFactory;
  exports.ɵregisterNgModuleType = registerNgModuleType;
  exports.ɵrenderComponent = renderComponent$1;
  exports.ɵresetCompiledComponents = resetCompiledComponents;
  exports.ɵresetJitOptions = resetJitOptions;
  exports.ɵresolveComponentResources = resolveComponentResources;
  exports.ɵsetClassMetadata = setClassMetadata;
  exports.ɵsetCurrentInjector = setCurrentInjector;
  exports.ɵsetDocument = setDocument;
  exports.ɵsetLocaleId = setLocaleId;
  exports.ɵstore = store;
  exports.ɵstringify = stringify;
  exports.ɵted = textDef;
  exports.ɵtransitiveScopesFor = transitiveScopesFor;
  exports.ɵunregisterLocaleData = unregisterAllLocaleData;
  exports.ɵunv = unwrapValue;
  exports.ɵunwrapSafeValue = unwrapSafeValue;
  exports.ɵvid = viewDef;
  exports.ɵwhenRendered = whenRendered;
  exports.ɵɵCopyDefinitionFeature = ɵɵCopyDefinitionFeature;
  exports.ɵɵInheritDefinitionFeature = ɵɵInheritDefinitionFeature;
  exports.ɵɵNgOnChangesFeature = ɵɵNgOnChangesFeature;
  exports.ɵɵProvidersFeature = ɵɵProvidersFeature;
  exports.ɵɵadvance = ɵɵadvance;
  exports.ɵɵattribute = ɵɵattribute;
  exports.ɵɵattributeInterpolate1 = ɵɵattributeInterpolate1;
  exports.ɵɵattributeInterpolate2 = ɵɵattributeInterpolate2;
  exports.ɵɵattributeInterpolate3 = ɵɵattributeInterpolate3;
  exports.ɵɵattributeInterpolate4 = ɵɵattributeInterpolate4;
  exports.ɵɵattributeInterpolate5 = ɵɵattributeInterpolate5;
  exports.ɵɵattributeInterpolate6 = ɵɵattributeInterpolate6;
  exports.ɵɵattributeInterpolate7 = ɵɵattributeInterpolate7;
  exports.ɵɵattributeInterpolate8 = ɵɵattributeInterpolate8;
  exports.ɵɵattributeInterpolateV = ɵɵattributeInterpolateV;
  exports.ɵɵclassMap = ɵɵclassMap;
  exports.ɵɵclassMapInterpolate1 = ɵɵclassMapInterpolate1;
  exports.ɵɵclassMapInterpolate2 = ɵɵclassMapInterpolate2;
  exports.ɵɵclassMapInterpolate3 = ɵɵclassMapInterpolate3;
  exports.ɵɵclassMapInterpolate4 = ɵɵclassMapInterpolate4;
  exports.ɵɵclassMapInterpolate5 = ɵɵclassMapInterpolate5;
  exports.ɵɵclassMapInterpolate6 = ɵɵclassMapInterpolate6;
  exports.ɵɵclassMapInterpolate7 = ɵɵclassMapInterpolate7;
  exports.ɵɵclassMapInterpolate8 = ɵɵclassMapInterpolate8;
  exports.ɵɵclassMapInterpolateV = ɵɵclassMapInterpolateV;
  exports.ɵɵclassProp = ɵɵclassProp;
  exports.ɵɵcomponentHostSyntheticListener = ɵɵcomponentHostSyntheticListener;
  exports.ɵɵcontentQuery = ɵɵcontentQuery;
  exports.ɵɵdefaultStyleSanitizer = ɵɵdefaultStyleSanitizer;
  exports.ɵɵdefineComponent = ɵɵdefineComponent;
  exports.ɵɵdefineDirective = ɵɵdefineDirective;
  exports.ɵɵdefineInjectable = ɵɵdefineInjectable;
  exports.ɵɵdefineInjector = ɵɵdefineInjector;
  exports.ɵɵdefineNgModule = ɵɵdefineNgModule;
  exports.ɵɵdefinePipe = ɵɵdefinePipe;
  exports.ɵɵdirectiveInject = ɵɵdirectiveInject;
  exports.ɵɵdisableBindings = ɵɵdisableBindings;
  exports.ɵɵelement = ɵɵelement;
  exports.ɵɵelementContainer = ɵɵelementContainer;
  exports.ɵɵelementContainerEnd = ɵɵelementContainerEnd;
  exports.ɵɵelementContainerStart = ɵɵelementContainerStart;
  exports.ɵɵelementEnd = ɵɵelementEnd;
  exports.ɵɵelementStart = ɵɵelementStart;
  exports.ɵɵenableBindings = ɵɵenableBindings;
  exports.ɵɵgetCurrentView = ɵɵgetCurrentView;
  exports.ɵɵgetFactoryOf = ɵɵgetFactoryOf;
  exports.ɵɵgetInheritedFactory = ɵɵgetInheritedFactory;
  exports.ɵɵhostProperty = ɵɵhostProperty;
  exports.ɵɵi18n = ɵɵi18n;
  exports.ɵɵi18nApply = ɵɵi18nApply;
  exports.ɵɵi18nAttributes = ɵɵi18nAttributes;
  exports.ɵɵi18nEnd = ɵɵi18nEnd;
  exports.ɵɵi18nExp = ɵɵi18nExp;
  exports.ɵɵi18nPostprocess = ɵɵi18nPostprocess;
  exports.ɵɵi18nStart = ɵɵi18nStart;
  exports.ɵɵinject = ɵɵinject;
  exports.ɵɵinjectAttribute = ɵɵinjectAttribute;
  exports.ɵɵinjectPipeChangeDetectorRef = ɵɵinjectPipeChangeDetectorRef;
  exports.ɵɵinvalidFactory = ɵɵinvalidFactory;
  exports.ɵɵinvalidFactoryDep = ɵɵinvalidFactoryDep;
  exports.ɵɵlistener = ɵɵlistener;
  exports.ɵɵloadQuery = ɵɵloadQuery;
  exports.ɵɵnamespaceHTML = ɵɵnamespaceHTML;
  exports.ɵɵnamespaceMathML = ɵɵnamespaceMathML;
  exports.ɵɵnamespaceSVG = ɵɵnamespaceSVG;
  exports.ɵɵnextContext = ɵɵnextContext;
  exports.ɵɵpipe = ɵɵpipe;
  exports.ɵɵpipeBind1 = ɵɵpipeBind1;
  exports.ɵɵpipeBind2 = ɵɵpipeBind2;
  exports.ɵɵpipeBind3 = ɵɵpipeBind3;
  exports.ɵɵpipeBind4 = ɵɵpipeBind4;
  exports.ɵɵpipeBindV = ɵɵpipeBindV;
  exports.ɵɵprojection = ɵɵprojection;
  exports.ɵɵprojectionDef = ɵɵprojectionDef;
  exports.ɵɵproperty = ɵɵproperty;
  exports.ɵɵpropertyInterpolate = ɵɵpropertyInterpolate;
  exports.ɵɵpropertyInterpolate1 = ɵɵpropertyInterpolate1;
  exports.ɵɵpropertyInterpolate2 = ɵɵpropertyInterpolate2;
  exports.ɵɵpropertyInterpolate3 = ɵɵpropertyInterpolate3;
  exports.ɵɵpropertyInterpolate4 = ɵɵpropertyInterpolate4;
  exports.ɵɵpropertyInterpolate5 = ɵɵpropertyInterpolate5;
  exports.ɵɵpropertyInterpolate6 = ɵɵpropertyInterpolate6;
  exports.ɵɵpropertyInterpolate7 = ɵɵpropertyInterpolate7;
  exports.ɵɵpropertyInterpolate8 = ɵɵpropertyInterpolate8;
  exports.ɵɵpropertyInterpolateV = ɵɵpropertyInterpolateV;
  exports.ɵɵpureFunction0 = ɵɵpureFunction0;
  exports.ɵɵpureFunction1 = ɵɵpureFunction1;
  exports.ɵɵpureFunction2 = ɵɵpureFunction2;
  exports.ɵɵpureFunction3 = ɵɵpureFunction3;
  exports.ɵɵpureFunction4 = ɵɵpureFunction4;
  exports.ɵɵpureFunction5 = ɵɵpureFunction5;
  exports.ɵɵpureFunction6 = ɵɵpureFunction6;
  exports.ɵɵpureFunction7 = ɵɵpureFunction7;
  exports.ɵɵpureFunction8 = ɵɵpureFunction8;
  exports.ɵɵpureFunctionV = ɵɵpureFunctionV;
  exports.ɵɵqueryRefresh = ɵɵqueryRefresh;
  exports.ɵɵreference = ɵɵreference;
  exports.ɵɵresolveBody = ɵɵresolveBody;
  exports.ɵɵresolveDocument = ɵɵresolveDocument;
  exports.ɵɵresolveWindow = ɵɵresolveWindow;
  exports.ɵɵrestoreView = ɵɵrestoreView;
  exports.ɵɵsanitizeHtml = ɵɵsanitizeHtml;
  exports.ɵɵsanitizeResourceUrl = ɵɵsanitizeResourceUrl;
  exports.ɵɵsanitizeScript = ɵɵsanitizeScript;
  exports.ɵɵsanitizeStyle = ɵɵsanitizeStyle;
  exports.ɵɵsanitizeUrl = ɵɵsanitizeUrl;
  exports.ɵɵsanitizeUrlOrResourceUrl = ɵɵsanitizeUrlOrResourceUrl;
  exports.ɵɵselect = ɵɵselect;
  exports.ɵɵsetComponentScope = ɵɵsetComponentScope;
  exports.ɵɵsetNgModuleScope = ɵɵsetNgModuleScope;
  exports.ɵɵstaticContentQuery = ɵɵstaticContentQuery;
  exports.ɵɵstaticViewQuery = ɵɵstaticViewQuery;
  exports.ɵɵstyleMap = ɵɵstyleMap;
  exports.ɵɵstyleMapInterpolate1 = ɵɵstyleMapInterpolate1;
  exports.ɵɵstyleMapInterpolate2 = ɵɵstyleMapInterpolate2;
  exports.ɵɵstyleMapInterpolate3 = ɵɵstyleMapInterpolate3;
  exports.ɵɵstyleMapInterpolate4 = ɵɵstyleMapInterpolate4;
  exports.ɵɵstyleMapInterpolate5 = ɵɵstyleMapInterpolate5;
  exports.ɵɵstyleMapInterpolate6 = ɵɵstyleMapInterpolate6;
  exports.ɵɵstyleMapInterpolate7 = ɵɵstyleMapInterpolate7;
  exports.ɵɵstyleMapInterpolate8 = ɵɵstyleMapInterpolate8;
  exports.ɵɵstyleMapInterpolateV = ɵɵstyleMapInterpolateV;
  exports.ɵɵstyleProp = ɵɵstyleProp;
  exports.ɵɵstylePropInterpolate1 = ɵɵstylePropInterpolate1;
  exports.ɵɵstylePropInterpolate2 = ɵɵstylePropInterpolate2;
  exports.ɵɵstylePropInterpolate3 = ɵɵstylePropInterpolate3;
  exports.ɵɵstylePropInterpolate4 = ɵɵstylePropInterpolate4;
  exports.ɵɵstylePropInterpolate5 = ɵɵstylePropInterpolate5;
  exports.ɵɵstylePropInterpolate6 = ɵɵstylePropInterpolate6;
  exports.ɵɵstylePropInterpolate7 = ɵɵstylePropInterpolate7;
  exports.ɵɵstylePropInterpolate8 = ɵɵstylePropInterpolate8;
  exports.ɵɵstylePropInterpolateV = ɵɵstylePropInterpolateV;
  exports.ɵɵstyleSanitizer = ɵɵstyleSanitizer;
  exports.ɵɵtemplate = ɵɵtemplate;
  exports.ɵɵtemplateRefExtractor = ɵɵtemplateRefExtractor;
  exports.ɵɵtext = ɵɵtext;
  exports.ɵɵtextInterpolate = ɵɵtextInterpolate;
  exports.ɵɵtextInterpolate1 = ɵɵtextInterpolate1;
  exports.ɵɵtextInterpolate2 = ɵɵtextInterpolate2;
  exports.ɵɵtextInterpolate3 = ɵɵtextInterpolate3;
  exports.ɵɵtextInterpolate4 = ɵɵtextInterpolate4;
  exports.ɵɵtextInterpolate5 = ɵɵtextInterpolate5;
  exports.ɵɵtextInterpolate6 = ɵɵtextInterpolate6;
  exports.ɵɵtextInterpolate7 = ɵɵtextInterpolate7;
  exports.ɵɵtextInterpolate8 = ɵɵtextInterpolate8;
  exports.ɵɵtextInterpolateV = ɵɵtextInterpolateV;
  exports.ɵɵupdateSyntheticHostBinding = ɵɵupdateSyntheticHostBinding;
  exports.ɵɵviewQuery = ɵɵviewQuery;

  Object.defineProperty(exports, '__esModule', { value: true });

})));
//# sourceMappingURL=core.umd.js.map