) must have projection slots defined.');\n}\nfunction assertParentView(lView, errMessage) {\n assertDefined(lView, errMessage || 'Component views should always have a parent view (component\\'s host view)');\n}\n/**\n * This is a basic sanity check that the `injectorIndex` seems to point to what looks like a\n * NodeInjector data structure.\n *\n * @param lView `LView` which should be checked.\n * @param injectorIndex index into the `LView` where the `NodeInjector` is expected.\n */\nfunction assertNodeInjector(lView, injectorIndex) {\n assertIndexInExpandoRange(lView, injectorIndex);\n assertIndexInExpandoRange(lView, injectorIndex + 8 /* NodeInjectorOffset.PARENT */);\n assertNumber(lView[injectorIndex + 0], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 1], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 2], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 3], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 4], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 5], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 6], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 7], 'injectorIndex should point to a bloom filter');\n assertNumber(lView[injectorIndex + 8 /* NodeInjectorOffset.PARENT */], 'injectorIndex should point to parent injector');\n}\n\nfunction getFactoryDef(type, throwNotFound) {\n const hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF);\n if (!hasFactoryDef && throwNotFound === true && ngDevMode) {\n throw new Error(`Type ${stringify(type)} does not have 'ɵfac' property.`);\n }\n return hasFactoryDef ? type[NG_FACTORY_DEF] : null;\n}\n\n/**\n * Symbol used to tell `Signal`s apart from other functions.\n *\n * This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.\n */\nconst SIGNAL = Symbol('SIGNAL');\n/**\n * Checks if the given `value` is a reactive `Signal`.\n *\n * @developerPreview\n */\nfunction isSignal(value) {\n return typeof value === 'function' && value[SIGNAL] !== undefined;\n}\n/**\n * Converts `fn` into a marked signal function (where `isSignal(fn)` will be `true`), and\n * potentially add some set of extra properties (passed as an object record `extraApi`).\n */\nfunction createSignalFromFunction(node, fn, extraApi = {}) {\n fn[SIGNAL] = node;\n // Copy properties from `extraApi` to `fn` to complete the desired API of the `Signal`.\n return Object.assign(fn, extraApi);\n}\n/**\n * The default equality function used for `signal` and `computed`, which treats objects and arrays\n * as never equal, and all other primitive values using identity semantics.\n *\n * This allows signals to hold non-primitive values (arrays, objects, other collections) and still\n * propagate change notification upon explicit mutation without identity change.\n *\n * @developerPreview\n */\nfunction defaultEquals(a, b) {\n // `Object.is` compares two values using identity semantics which is desired behavior for\n // primitive values. If `Object.is` determines two values to be equal we need to make sure that\n // those don't represent objects (we want to make sure that 2 objects are always considered\n // \"unequal\"). The null check is needed for the special case of JavaScript reporting null values\n // as objects (`typeof null === 'object'`).\n return (a === null || typeof a !== 'object') && Object.is(a, b);\n}\n\n// Required as the signals library is in a separate package, so we need to explicitly ensure the\n/**\n * A `WeakRef`-compatible reference that fakes the API with a strong reference\n * internally.\n */\nclass LeakyRef {\n constructor(ref) {\n this.ref = ref;\n }\n deref() {\n return this.ref;\n }\n}\n// `WeakRef` is not always defined in every TS environment where Angular is compiled. Instead,\n// read it off of the global context if available.\n// tslint:disable-next-line: no-toplevel-property-access\nlet WeakRefImpl = _global['WeakRef'] ?? LeakyRef;\nfunction newWeakRef(value) {\n if (typeof ngDevMode !== 'undefined' && ngDevMode && WeakRefImpl === undefined) {\n throw new Error(`Angular requires a browser which supports the 'WeakRef' API`);\n }\n return new WeakRefImpl(value);\n}\nfunction setAlternateWeakRefImpl(impl) {\n // no-op since the alternate impl is included by default by the framework. Remove once internal\n // migration is complete.\n}\n\n// Required as the signals library is in a separate package, so we need to explicitly ensure the\n/**\n * Counter tracking the next `ProducerId` or `ConsumerId`.\n */\nlet _nextReactiveId = 0;\n/**\n * Tracks the currently active reactive consumer (or `null` if there is no active\n * consumer).\n */\nlet activeConsumer = null;\n/**\n * Whether the graph is currently propagating change notifications.\n */\nlet inNotificationPhase = false;\nfunction setActiveConsumer(consumer) {\n const prev = activeConsumer;\n activeConsumer = consumer;\n return prev;\n}\n/**\n * A node in the reactive graph.\n *\n * Nodes can be producers of reactive values, consumers of other reactive values, or both.\n *\n * Producers are nodes that produce values, and can be depended upon by consumer nodes.\n *\n * Producers expose a monotonic `valueVersion` counter, and are responsible for incrementing this\n * version when their value semantically changes. Some producers may produce their values lazily and\n * thus at times need to be polled for potential updates to their value (and by extension their\n * `valueVersion`). This is accomplished via the `onProducerUpdateValueVersion` method for\n * implemented by producers, which should perform whatever calculations are necessary to ensure\n * `valueVersion` is up to date.\n *\n * Consumers are nodes that depend on the values of producers and are notified when those values\n * might have changed.\n *\n * Consumers do not wrap the reads they consume themselves, but rather can be set as the active\n * reader via `setActiveConsumer`. Reads of producers that happen while a consumer is active will\n * result in those producers being added as dependencies of that consumer node.\n *\n * The set of dependencies of a consumer is dynamic. Implementers expose a monotonically increasing\n * `trackingVersion` counter, which increments whenever the consumer is about to re-run any reactive\n * reads it needs and establish a new set of dependencies as a result.\n *\n * Producers store the last `trackingVersion` they've seen from `Consumer`s which have read them.\n * This allows a producer to identify whether its record of the dependency is current or stale, by\n * comparing the consumer's `trackingVersion` to the version at which the dependency was\n * last observed.\n */\nclass ReactiveNode {\n constructor() {\n this.id = _nextReactiveId++;\n /**\n * A cached weak reference to this node, which will be used in `ReactiveEdge`s.\n */\n this.ref = newWeakRef(this);\n /**\n * Edges to producers on which this node depends (in its consumer capacity).\n */\n this.producers = new Map();\n /**\n * Edges to consumers on which this node depends (in its producer capacity).\n */\n this.consumers = new Map();\n /**\n * Monotonically increasing counter representing a version of this `Consumer`'s\n * dependencies.\n */\n this.trackingVersion = 0;\n /**\n * Monotonically increasing counter which increases when the value of this `Producer`\n * semantically changes.\n */\n this.valueVersion = 0;\n }\n /**\n * Polls dependencies of a consumer to determine if they have actually changed.\n *\n * If this returns `false`, then even though the consumer may have previously been notified of a\n * change, the values of its dependencies have not actually changed and the consumer should not\n * rerun any reactions.\n */\n consumerPollProducersForChange() {\n for (const [producerId, edge] of this.producers) {\n const producer = edge.producerNode.deref();\n // On Safari < 16.1 deref can return null, we need to check for null also.\n // See https://github.com/WebKit/WebKit/commit/44c15ba58912faab38b534fef909dd9e13e095e0\n if (producer == null || edge.atTrackingVersion !== this.trackingVersion) {\n // This dependency edge is stale, so remove it.\n this.producers.delete(producerId);\n producer?.consumers.delete(this.id);\n continue;\n }\n if (producer.producerPollStatus(edge.seenValueVersion)) {\n // One of the dependencies reports a real value change.\n return true;\n }\n }\n // No dependency reported a real value change, so the `Consumer` has also not been\n // impacted.\n return false;\n }\n /**\n * Notify all consumers of this producer that its value may have changed.\n */\n producerMayHaveChanged() {\n // Prevent signal reads when we're updating the graph\n const prev = inNotificationPhase;\n inNotificationPhase = true;\n try {\n for (const [consumerId, edge] of this.consumers) {\n const consumer = edge.consumerNode.deref();\n // On Safari < 16.1 deref can return null, we need to check for null also.\n // See https://github.com/WebKit/WebKit/commit/44c15ba58912faab38b534fef909dd9e13e095e0\n if (consumer == null || consumer.trackingVersion !== edge.atTrackingVersion) {\n this.consumers.delete(consumerId);\n consumer?.producers.delete(this.id);\n continue;\n }\n consumer.onConsumerDependencyMayHaveChanged();\n }\n }\n finally {\n inNotificationPhase = prev;\n }\n }\n /**\n * Mark that this producer node has been accessed in the current reactive context.\n */\n producerAccessed() {\n if (inNotificationPhase) {\n throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ?\n `Assertion error: signal read during notification phase` :\n '');\n }\n if (activeConsumer === null) {\n return;\n }\n // Either create or update the dependency `Edge` in both directions.\n let edge = activeConsumer.producers.get(this.id);\n if (edge === undefined) {\n edge = {\n consumerNode: activeConsumer.ref,\n producerNode: this.ref,\n seenValueVersion: this.valueVersion,\n atTrackingVersion: activeConsumer.trackingVersion,\n };\n activeConsumer.producers.set(this.id, edge);\n this.consumers.set(activeConsumer.id, edge);\n }\n else {\n edge.seenValueVersion = this.valueVersion;\n edge.atTrackingVersion = activeConsumer.trackingVersion;\n }\n }\n /**\n * Whether this consumer currently has any producers registered.\n */\n get hasProducers() {\n return this.producers.size > 0;\n }\n /**\n * Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,\n * based on the current consumer context.\n */\n get producerUpdatesAllowed() {\n return activeConsumer?.consumerAllowSignalWrites !== false;\n }\n /**\n * Checks if a `Producer` has a current value which is different than the value\n * last seen at a specific version by a `Consumer` which recorded a dependency on\n * this `Producer`.\n */\n producerPollStatus(lastSeenValueVersion) {\n // `producer.valueVersion` may be stale, but a mismatch still means that the value\n // last seen by the `Consumer` is also stale.\n if (this.valueVersion !== lastSeenValueVersion) {\n return true;\n }\n // Trigger the `Producer` to update its `valueVersion` if necessary.\n this.onProducerUpdateValueVersion();\n // At this point, we can trust `producer.valueVersion`.\n return this.valueVersion !== lastSeenValueVersion;\n }\n}\n\n/**\n * Create a computed `Signal` which derives a reactive value from an expression.\n *\n * @developerPreview\n */\nfunction computed(computation, options) {\n const node = new ComputedImpl(computation, options?.equal ?? defaultEquals);\n // Casting here is required for g3, as TS inference behavior is slightly different between our\n // version/options and g3's.\n return createSignalFromFunction(node, node.signal.bind(node));\n}\n/**\n * A dedicated symbol used before a computed value has been calculated for the first time.\n * Explicitly typed as `any` so we can use it as signal's value.\n */\nconst UNSET = Symbol('UNSET');\n/**\n * A dedicated symbol used in place of a computed signal value to indicate that a given computation\n * is in progress. Used to detect cycles in computation chains.\n * Explicitly typed as `any` so we can use it as signal's value.\n */\nconst COMPUTING = Symbol('COMPUTING');\n/**\n * A dedicated symbol used in place of a computed signal value to indicate that a given computation\n * failed. The thrown error is cached until the computation gets dirty again.\n * Explicitly typed as `any` so we can use it as signal's value.\n */\nconst ERRORED = Symbol('ERRORED');\n/**\n * A computation, which derives a value from a declarative reactive expression.\n *\n * `Computed`s are both producers and consumers of reactivity.\n */\nclass ComputedImpl extends ReactiveNode {\n constructor(computation, equal) {\n super();\n this.computation = computation;\n this.equal = equal;\n /**\n * Current value of the computation.\n *\n * This can also be one of the special values `UNSET`, `COMPUTING`, or `ERRORED`.\n */\n this.value = UNSET;\n /**\n * If `value` is `ERRORED`, the error caught from the last computation attempt which will\n * be re-thrown.\n */\n this.error = null;\n /**\n * Flag indicating that the computation is currently stale, meaning that one of the\n * dependencies has notified of a potential change.\n *\n * It's possible that no dependency has _actually_ changed, in which case the `stale`\n * state can be resolved without recomputing the value.\n */\n this.stale = true;\n this.consumerAllowSignalWrites = false;\n }\n onConsumerDependencyMayHaveChanged() {\n if (this.stale) {\n // We've already notified consumers that this value has potentially changed.\n return;\n }\n // Record that the currently cached value may be stale.\n this.stale = true;\n // Notify any consumers about the potential change.\n this.producerMayHaveChanged();\n }\n onProducerUpdateValueVersion() {\n if (!this.stale) {\n // The current value and its version are already up to date.\n return;\n }\n // The current value is stale. Check whether we need to produce a new one.\n if (this.value !== UNSET && this.value !== COMPUTING &&\n !this.consumerPollProducersForChange()) {\n // Even though we were previously notified of a potential dependency update, all of\n // our dependencies report that they have not actually changed in value, so we can\n // resolve the stale state without needing to recompute the current value.\n this.stale = false;\n return;\n }\n // The current value is stale, and needs to be recomputed. It still may not change -\n // that depends on whether the newly computed value is equal to the old.\n this.recomputeValue();\n }\n recomputeValue() {\n if (this.value === COMPUTING) {\n // Our computation somehow led to a cyclic read of itself.\n throw new Error('Detected cycle in computations.');\n }\n const oldValue = this.value;\n this.value = COMPUTING;\n // As we're re-running the computation, update our dependent tracking version number.\n this.trackingVersion++;\n const prevConsumer = setActiveConsumer(this);\n let newValue;\n try {\n newValue = this.computation();\n }\n catch (err) {\n newValue = ERRORED;\n this.error = err;\n }\n finally {\n setActiveConsumer(prevConsumer);\n }\n this.stale = false;\n if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&\n this.equal(oldValue, newValue)) {\n // No change to `valueVersion` - old and new values are\n // semantically equivalent.\n this.value = oldValue;\n return;\n }\n this.value = newValue;\n this.valueVersion++;\n }\n signal() {\n // Check if the value needs updating before returning it.\n this.onProducerUpdateValueVersion();\n // Record that someone looked at this signal.\n this.producerAccessed();\n if (this.value === ERRORED) {\n throw this.error;\n }\n return this.value;\n }\n}\n\nfunction defaultThrowError() {\n throw new Error();\n}\nlet throwInvalidWriteToSignalErrorFn = defaultThrowError;\nfunction throwInvalidWriteToSignalError() {\n throwInvalidWriteToSignalErrorFn();\n}\nfunction setThrowInvalidWriteToSignalError(fn) {\n throwInvalidWriteToSignalErrorFn = fn;\n}\n\n/**\n * If set, called after `WritableSignal`s are updated.\n *\n * This hook can be used to achieve various effects, such as running effects synchronously as part\n * of setting a signal.\n */\nlet postSignalSetFn = null;\nclass WritableSignalImpl extends ReactiveNode {\n constructor(value, equal) {\n super();\n this.value = value;\n this.equal = equal;\n this.consumerAllowSignalWrites = false;\n }\n onConsumerDependencyMayHaveChanged() {\n // This never happens for writable signals as they're not consumers.\n }\n onProducerUpdateValueVersion() {\n // Writable signal value versions are always up to date.\n }\n /**\n * Directly update the value of the signal to a new value, which may or may not be\n * equal to the previous.\n *\n * In the event that `newValue` is semantically equal to the current value, `set` is\n * a no-op.\n */\n set(newValue) {\n if (!this.producerUpdatesAllowed) {\n throwInvalidWriteToSignalError();\n }\n if (!this.equal(this.value, newValue)) {\n this.value = newValue;\n this.valueVersion++;\n this.producerMayHaveChanged();\n postSignalSetFn?.();\n }\n }\n /**\n * Derive a new value for the signal from its current value using the `updater` function.\n *\n * This is equivalent to calling `set` on the result of running `updater` on the current\n * value.\n */\n update(updater) {\n if (!this.producerUpdatesAllowed) {\n throwInvalidWriteToSignalError();\n }\n this.set(updater(this.value));\n }\n /**\n * Calls `mutator` on the current value and assumes that it has been mutated.\n */\n mutate(mutator) {\n if (!this.producerUpdatesAllowed) {\n throwInvalidWriteToSignalError();\n }\n // Mutate bypasses equality checks as it's by definition changing the value.\n mutator(this.value);\n this.valueVersion++;\n this.producerMayHaveChanged();\n postSignalSetFn?.();\n }\n asReadonly() {\n if (this.readonlySignal === undefined) {\n this.readonlySignal = createSignalFromFunction(this, () => this.signal());\n }\n return this.readonlySignal;\n }\n signal() {\n this.producerAccessed();\n return this.value;\n }\n}\n/**\n * Create a `Signal` that can be set or updated directly.\n *\n * @developerPreview\n */\nfunction signal(initialValue, options) {\n const signalNode = new WritableSignalImpl(initialValue, options?.equal ?? defaultEquals);\n // Casting here is required for g3, as TS inference behavior is slightly different between our\n // version/options and g3's.\n const signalFn = createSignalFromFunction(signalNode, signalNode.signal.bind(signalNode), {\n set: signalNode.set.bind(signalNode),\n update: signalNode.update.bind(signalNode),\n mutate: signalNode.mutate.bind(signalNode),\n asReadonly: signalNode.asReadonly.bind(signalNode)\n });\n return signalFn;\n}\nfunction setPostSignalSetFn(fn) {\n const prev = postSignalSetFn;\n postSignalSetFn = fn;\n return prev;\n}\n\n/**\n * Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function\n * can, optionally, return a value.\n *\n * @developerPreview\n */\nfunction untracked(nonReactiveReadsFn) {\n const prevConsumer = setActiveConsumer(null);\n // We are not trying to catch any particular errors here, just making sure that the consumers\n // stack is restored in case of errors.\n try {\n return nonReactiveReadsFn();\n }\n finally {\n setActiveConsumer(prevConsumer);\n }\n}\n\nconst NOOP_CLEANUP_FN = () => { };\n/**\n * Watches a reactive expression and allows it to be scheduled to re-run\n * when any dependencies notify of a change.\n *\n * `Watch` doesn't run reactive expressions itself, but relies on a consumer-\n * provided scheduling operation to coordinate calling `Watch.run()`.\n */\nclass Watch extends ReactiveNode {\n constructor(watch, schedule, allowSignalWrites) {\n super();\n this.watch = watch;\n this.schedule = schedule;\n this.dirty = false;\n this.cleanupFn = NOOP_CLEANUP_FN;\n this.registerOnCleanup = (cleanupFn) => {\n this.cleanupFn = cleanupFn;\n };\n this.consumerAllowSignalWrites = allowSignalWrites;\n }\n notify() {\n if (!this.dirty) {\n this.schedule(this);\n }\n this.dirty = true;\n }\n onConsumerDependencyMayHaveChanged() {\n this.notify();\n }\n onProducerUpdateValueVersion() {\n // Watches are not producers.\n }\n /**\n * Execute the reactive expression in the context of this `Watch` consumer.\n *\n * Should be called by the user scheduling algorithm when the provided\n * `schedule` hook is called by `Watch`.\n */\n run() {\n this.dirty = false;\n if (this.trackingVersion !== 0 && !this.consumerPollProducersForChange()) {\n return;\n }\n const prevConsumer = setActiveConsumer(this);\n this.trackingVersion++;\n try {\n this.cleanupFn();\n this.cleanupFn = NOOP_CLEANUP_FN;\n this.watch(this.registerOnCleanup);\n }\n finally {\n setActiveConsumer(prevConsumer);\n }\n }\n cleanup() {\n this.cleanupFn();\n }\n}\n\n/**\n * Represents a basic change from a previous to a new value for a single\n * property on a directive instance. Passed as a value in a\n * {@link SimpleChanges} object to the `ngOnChanges` hook.\n *\n * @see {@link OnChanges}\n *\n * @publicApi\n */\nclass SimpleChange {\n constructor(previousValue, currentValue, firstChange) {\n this.previousValue = previousValue;\n this.currentValue = currentValue;\n this.firstChange = firstChange;\n }\n /**\n * Check whether the new value is the first value assigned.\n */\n isFirstChange() {\n return this.firstChange;\n }\n}\n\n/**\n * The NgOnChangesFeature decorates a component with support for the ngOnChanges\n * lifecycle hook, so it should be included in any component that implements\n * that hook.\n *\n * If the component or directive uses inheritance, the NgOnChangesFeature MUST\n * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise\n * inherited properties will not be propagated to the ngOnChanges lifecycle\n * hook.\n *\n * Example usage:\n *\n * ```\n * static ɵcmp = defineComponent({\n * ...\n * inputs: {name: 'publicName'},\n * features: [NgOnChangesFeature]\n * });\n * ```\n *\n * @codeGenApi\n */\nfunction ɵɵNgOnChangesFeature() {\n return NgOnChangesFeatureImpl;\n}\nfunction NgOnChangesFeatureImpl(definition) {\n if (definition.type.prototype.ngOnChanges) {\n definition.setInput = ngOnChangesSetInput;\n }\n return rememberChangeHistoryAndInvokeOnChangesHook;\n}\n// This option ensures that the ngOnChanges lifecycle hook will be inherited\n// from superclasses (in InheritDefinitionFeature).\n/** @nocollapse */\n// tslint:disable-next-line:no-toplevel-property-access\nɵɵNgOnChangesFeature.ngInherit = true;\n/**\n * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate\n * `ngOnChanges`.\n *\n * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are\n * found it invokes `ngOnChanges` on the component instance.\n *\n * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,\n * it is guaranteed to be called with component instance.\n */\nfunction rememberChangeHistoryAndInvokeOnChangesHook() {\n const simpleChangesStore = getSimpleChangesStore(this);\n const current = simpleChangesStore?.current;\n if (current) {\n const previous = simpleChangesStore.previous;\n if (previous === EMPTY_OBJ) {\n simpleChangesStore.previous = current;\n }\n else {\n // New changes are copied to the previous store, so that we don't lose history for inputs\n // which were not changed this time\n for (let key in current) {\n previous[key] = current[key];\n }\n }\n simpleChangesStore.current = null;\n this.ngOnChanges(current);\n }\n}\nfunction ngOnChangesSetInput(instance, value, publicName, privateName) {\n const declaredName = this.declaredInputs[publicName];\n ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');\n const simpleChangesStore = getSimpleChangesStore(instance) ||\n setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });\n const current = simpleChangesStore.current || (simpleChangesStore.current = {});\n const previous = simpleChangesStore.previous;\n const previousChange = previous[declaredName];\n current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);\n instance[privateName] = value;\n}\nconst SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';\nfunction getSimpleChangesStore(instance) {\n return instance[SIMPLE_CHANGES_STORE] || null;\n}\nfunction setSimpleChangesStore(instance, store) {\n return instance[SIMPLE_CHANGES_STORE] = store;\n}\n\nlet profilerCallback = null;\n/**\n * Sets the callback function which will be invoked before and after performing certain actions at\n * runtime (for example, before and after running change detection).\n *\n * Warning: this function is *INTERNAL* and should not be relied upon in application's code.\n * The contract of the function might be changed in any release and/or the function can be removed\n * completely.\n *\n * @param profiler function provided by the caller or null value to disable profiling.\n */\nconst setProfiler = (profiler) => {\n profilerCallback = profiler;\n};\n/**\n * Profiler function which wraps user code executed by the runtime.\n *\n * @param event ProfilerEvent corresponding to the execution context\n * @param instance component instance\n * @param hookOrListener lifecycle hook function or output listener. The value depends on the\n * execution context\n * @returns\n */\nconst profiler = function (event, instance, hookOrListener) {\n if (profilerCallback != null /* both `null` and `undefined` */) {\n profilerCallback(event, instance, hookOrListener);\n }\n};\n\nconst SVG_NAMESPACE = 'svg';\nconst MATH_ML_NAMESPACE = 'math';\n\n/**\n * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)\n * in same location in `LView`. This is because we don't want to pre-allocate space for it\n * because the storage is sparse. This file contains utilities for dealing with such data types.\n *\n * How do we know what is stored at a given location in `LView`.\n * - `Array.isArray(value) === false` => `RNode` (The normal storage value)\n * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.\n * - `typeof value[TYPE] === 'object'` => `LView`\n * - This happens when we have a component at a given location\n * - `typeof value[TYPE] === true` => `LContainer`\n * - This happens when we have `LContainer` binding at a given location.\n *\n *\n * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.\n */\n/**\n * Returns `RNode`.\n * @param value wrapped value of `RNode`, `LView`, `LContainer`\n */\nfunction unwrapRNode(value) {\n while (Array.isArray(value)) {\n value = value[HOST];\n }\n return value;\n}\n/**\n * Returns `LView` or `null` if not found.\n * @param value wrapped value of `RNode`, `LView`, `LContainer`\n */\nfunction unwrapLView(value) {\n while (Array.isArray(value)) {\n // This check is same as `isLView()` but we don't call at as we don't want to call\n // `Array.isArray()` twice and give JITer more work for inlining.\n if (typeof value[TYPE] === 'object')\n return value;\n value = value[HOST];\n }\n return null;\n}\n/**\n * Retrieves an element value from the provided `viewData`, by unwrapping\n * from any containers, component views, or style contexts.\n */\nfunction getNativeByIndex(index, lView) {\n ngDevMode && assertIndexInRange(lView, index);\n ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');\n return unwrapRNode(lView[index]);\n}\n/**\n * Retrieve an `RNode` for a given `TNode` and `LView`.\n *\n * This function guarantees in dev mode to retrieve a non-null `RNode`.\n *\n * @param tNode\n * @param lView\n */\nfunction getNativeByTNode(tNode, lView) {\n ngDevMode && assertTNodeForLView(tNode, lView);\n ngDevMode && assertIndexInRange(lView, tNode.index);\n const node = unwrapRNode(lView[tNode.index]);\n return node;\n}\n/**\n * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.\n *\n * Some `TNode`s don't have associated `RNode`s. For example `Projection`\n *\n * @param tNode\n * @param lView\n */\nfunction getNativeByTNodeOrNull(tNode, lView) {\n const index = tNode === null ? -1 : tNode.index;\n if (index !== -1) {\n ngDevMode && assertTNodeForLView(tNode, lView);\n const node = unwrapRNode(lView[index]);\n return node;\n }\n return null;\n}\n// fixme(misko): The return Type should be `TNode|null`\nfunction getTNode(tView, index) {\n ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');\n ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');\n const tNode = tView.data[index];\n ngDevMode && tNode !== null && assertTNode(tNode);\n return tNode;\n}\n/** Retrieves a value from any `LView` or `TData`. */\nfunction load(view, index) {\n ngDevMode && assertIndexInRange(view, index);\n return view[index];\n}\nfunction getComponentLViewByIndex(nodeIndex, hostView) {\n // Could be an LView or an LContainer. If LContainer, unwrap to find LView.\n ngDevMode && assertIndexInRange(hostView, nodeIndex);\n const slotValue = hostView[nodeIndex];\n const lView = isLView(slotValue) ? slotValue : slotValue[HOST];\n return lView;\n}\n/** Checks whether a given view is in creation mode */\nfunction isCreationMode(view) {\n return (view[FLAGS] & 4 /* LViewFlags.CreationMode */) === 4 /* LViewFlags.CreationMode */;\n}\n/**\n * Returns a boolean for whether the view is attached to the change detection tree.\n *\n * Note: This determines whether a view should be checked, not whether it's inserted\n * into a container. For that, you'll want `viewAttachedToContainer` below.\n */\nfunction viewAttachedToChangeDetector(view) {\n return (view[FLAGS] & 128 /* LViewFlags.Attached */) === 128 /* LViewFlags.Attached */;\n}\n/** Returns a boolean for whether the view is attached to a container. */\nfunction viewAttachedToContainer(view) {\n return isLContainer(view[PARENT]);\n}\nfunction getConstant(consts, index) {\n if (index === null || index === undefined)\n return null;\n ngDevMode && assertIndexInRange(consts, index);\n return consts[index];\n}\n/**\n * Resets the pre-order hook flags of the view.\n * @param lView the LView on which the flags are reset\n */\nfunction resetPreOrderHookFlags(lView) {\n lView[PREORDER_HOOK_FLAGS] = 0;\n}\n/**\n * Adds the `RefreshView` flag from the lView and updates DESCENDANT_VIEWS_TO_REFRESH counters of\n * parents.\n */\nfunction markViewForRefresh(lView) {\n if ((lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) === 0) {\n lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;\n updateViewsToRefresh(lView, 1);\n }\n}\n/**\n * Removes the `RefreshView` flag from the lView and updates DESCENDANT_VIEWS_TO_REFRESH counters of\n * parents.\n */\nfunction clearViewRefreshFlag(lView) {\n if (lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {\n lView[FLAGS] &= ~1024 /* LViewFlags.RefreshView */;\n updateViewsToRefresh(lView, -1);\n }\n}\n/**\n * Updates the `DESCENDANT_VIEWS_TO_REFRESH` counter on the parents of the `LView` as well as the\n * parents above that whose\n * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh\n * or\n * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh\n */\nfunction updateViewsToRefresh(lView, amount) {\n let parent = lView[PARENT];\n if (parent === null) {\n return;\n }\n parent[DESCENDANT_VIEWS_TO_REFRESH] += amount;\n let viewOrContainer = parent;\n parent = parent[PARENT];\n while (parent !== null &&\n ((amount === 1 && viewOrContainer[DESCENDANT_VIEWS_TO_REFRESH] === 1) ||\n (amount === -1 && viewOrContainer[DESCENDANT_VIEWS_TO_REFRESH] === 0))) {\n parent[DESCENDANT_VIEWS_TO_REFRESH] += amount;\n viewOrContainer = parent;\n parent = parent[PARENT];\n }\n}\n/**\n * Stores a LView-specific destroy callback.\n */\nfunction storeLViewOnDestroy(lView, onDestroyCallback) {\n if ((lView[FLAGS] & 256 /* LViewFlags.Destroyed */) === 256 /* LViewFlags.Destroyed */) {\n throw new RuntimeError(911 /* RuntimeErrorCode.VIEW_ALREADY_DESTROYED */, ngDevMode && 'View has already been destroyed.');\n }\n if (lView[ON_DESTROY_HOOKS] === null) {\n lView[ON_DESTROY_HOOKS] = [];\n }\n lView[ON_DESTROY_HOOKS].push(onDestroyCallback);\n}\n/**\n * Removes previously registered LView-specific destroy callback.\n */\nfunction removeLViewOnDestroy(lView, onDestroyCallback) {\n if (lView[ON_DESTROY_HOOKS] === null)\n return;\n const destroyCBIdx = lView[ON_DESTROY_HOOKS].indexOf(onDestroyCallback);\n if (destroyCBIdx !== -1) {\n lView[ON_DESTROY_HOOKS].splice(destroyCBIdx, 1);\n }\n}\n\nconst instructionState = {\n lFrame: createLFrame(null),\n bindingsEnabled: true,\n skipHydrationRootTNode: null,\n};\n/**\n * In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.\n *\n * Necessary to support ChangeDetectorRef.checkNoChanges().\n *\n * The `checkNoChanges` function is invoked only in ngDevMode=true and verifies that no unintended\n * changes exist in the change detector or its children.\n */\nlet _isInCheckNoChangesMode = false;\n/**\n * Returns true if the instruction state stack is empty.\n *\n * Intended to be called from tests only (tree shaken otherwise).\n */\nfunction specOnlyIsInstructionStateEmpty() {\n return instructionState.lFrame.parent === null;\n}\nfunction getElementDepthCount() {\n return instructionState.lFrame.elementDepthCount;\n}\nfunction increaseElementDepthCount() {\n instructionState.lFrame.elementDepthCount++;\n}\nfunction decreaseElementDepthCount() {\n instructionState.lFrame.elementDepthCount--;\n}\nfunction getBindingsEnabled() {\n return instructionState.bindingsEnabled;\n}\n/**\n * Returns true if currently inside a skip hydration block.\n * @returns boolean\n */\nfunction isInSkipHydrationBlock$1() {\n return instructionState.skipHydrationRootTNode !== null;\n}\n/**\n * Returns true if this is the root TNode of the skip hydration block.\n * @param tNode the current TNode\n * @returns boolean\n */\nfunction isSkipHydrationRootTNode(tNode) {\n return instructionState.skipHydrationRootTNode === tNode;\n}\n/**\n * Enables directive matching on elements.\n *\n * * Example:\n * ```\n * \n * Should match component / directive.\n * \n * \n * \n * \n * Should not match component / directive because we are in ngNonBindable.\n * \n * \n *
\n * ```\n *\n * @codeGenApi\n */\nfunction ɵɵenableBindings() {\n instructionState.bindingsEnabled = true;\n}\n/**\n * Sets a flag to specify that the TNode is in a skip hydration block.\n * @param tNode the current TNode\n */\nfunction enterSkipHydrationBlock(tNode) {\n instructionState.skipHydrationRootTNode = tNode;\n}\n/**\n * Disables directive matching on element.\n *\n * * Example:\n * ```\n * \n * Should match component / directive.\n * \n * \n * \n * \n * Should not match component / directive because we are in ngNonBindable.\n * \n * \n *
\n * ```\n *\n * @codeGenApi\n */\nfunction ɵɵdisableBindings() {\n instructionState.bindingsEnabled = false;\n}\n/**\n * Clears the root skip hydration node when leaving a skip hydration block.\n */\nfunction leaveSkipHydrationBlock() {\n instructionState.skipHydrationRootTNode = null;\n}\n/**\n * Return the current `LView`.\n */\nfunction getLView() {\n return instructionState.lFrame.lView;\n}\n/**\n * Return the current `TView`.\n */\nfunction getTView() {\n return instructionState.lFrame.tView;\n}\n/**\n * Restores `contextViewData` to the given OpaqueViewState instance.\n *\n * Used in conjunction with the getCurrentView() instruction to save a snapshot\n * of the current view and restore it when listeners are invoked. This allows\n * walking the declaration view tree in listeners to get vars from parent views.\n *\n * @param viewToRestore The OpaqueViewState instance to restore.\n * @returns Context of the restored OpaqueViewState instance.\n *\n * @codeGenApi\n */\nfunction ɵɵrestoreView(viewToRestore) {\n instructionState.lFrame.contextLView = viewToRestore;\n return viewToRestore[CONTEXT];\n}\n/**\n * Clears the view set in `ɵɵrestoreView` from memory. Returns the passed in\n * value so that it can be used as a return value of an instruction.\n *\n * @codeGenApi\n */\nfunction ɵɵresetView(value) {\n instructionState.lFrame.contextLView = null;\n return value;\n}\nfunction getCurrentTNode() {\n let currentTNode = getCurrentTNodePlaceholderOk();\n while (currentTNode !== null && currentTNode.type === 64 /* TNodeType.Placeholder */) {\n currentTNode = currentTNode.parent;\n }\n return currentTNode;\n}\nfunction getCurrentTNodePlaceholderOk() {\n return instructionState.lFrame.currentTNode;\n}\nfunction getCurrentParentTNode() {\n const lFrame = instructionState.lFrame;\n const currentTNode = lFrame.currentTNode;\n return lFrame.isParent ? currentTNode : currentTNode.parent;\n}\nfunction setCurrentTNode(tNode, isParent) {\n ngDevMode && tNode && assertTNodeForTView(tNode, instructionState.lFrame.tView);\n const lFrame = instructionState.lFrame;\n lFrame.currentTNode = tNode;\n lFrame.isParent = isParent;\n}\nfunction isCurrentTNodeParent() {\n return instructionState.lFrame.isParent;\n}\nfunction setCurrentTNodeAsNotParent() {\n instructionState.lFrame.isParent = false;\n}\nfunction getContextLView() {\n const contextLView = instructionState.lFrame.contextLView;\n ngDevMode && assertDefined(contextLView, 'contextLView must be defined.');\n return contextLView;\n}\nfunction isInCheckNoChangesMode() {\n !ngDevMode && throwError('Must never be called in production mode');\n return _isInCheckNoChangesMode;\n}\nfunction setIsInCheckNoChangesMode(mode) {\n !ngDevMode && throwError('Must never be called in production mode');\n _isInCheckNoChangesMode = mode;\n}\n// top level variables should not be exported for performance reasons (PERF_NOTES.md)\nfunction getBindingRoot() {\n const lFrame = instructionState.lFrame;\n let index = lFrame.bindingRootIndex;\n if (index === -1) {\n index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex;\n }\n return index;\n}\nfunction getBindingIndex() {\n return instructionState.lFrame.bindingIndex;\n}\nfunction setBindingIndex(value) {\n return instructionState.lFrame.bindingIndex = value;\n}\nfunction nextBindingIndex() {\n return instructionState.lFrame.bindingIndex++;\n}\nfunction incrementBindingIndex(count) {\n const lFrame = instructionState.lFrame;\n const index = lFrame.bindingIndex;\n lFrame.bindingIndex = lFrame.bindingIndex + count;\n return index;\n}\nfunction isInI18nBlock() {\n return instructionState.lFrame.inI18n;\n}\nfunction setInI18nBlock(isInI18nBlock) {\n instructionState.lFrame.inI18n = isInI18nBlock;\n}\n/**\n * Set a new binding root index so that host template functions can execute.\n *\n * Bindings inside the host template are 0 index. But because we don't know ahead of time\n * how many host bindings we have we can't pre-compute them. For this reason they are all\n * 0 index and we just shift the root so that they match next available location in the LView.\n *\n * @param bindingRootIndex Root index for `hostBindings`\n * @param currentDirectiveIndex `TData[currentDirectiveIndex]` will point to the current directive\n * whose `hostBindings` are being processed.\n */\nfunction setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex) {\n const lFrame = instructionState.lFrame;\n lFrame.bindingIndex = lFrame.bindingRootIndex = bindingRootIndex;\n setCurrentDirectiveIndex(currentDirectiveIndex);\n}\n/**\n * When host binding is executing this points to the directive index.\n * `TView.data[getCurrentDirectiveIndex()]` is `DirectiveDef`\n * `LView[getCurrentDirectiveIndex()]` is directive instance.\n */\nfunction getCurrentDirectiveIndex() {\n return instructionState.lFrame.currentDirectiveIndex;\n}\n/**\n * Sets an index of a directive whose `hostBindings` are being processed.\n *\n * @param currentDirectiveIndex `TData` index where current directive instance can be found.\n */\nfunction setCurrentDirectiveIndex(currentDirectiveIndex) {\n instructionState.lFrame.currentDirectiveIndex = currentDirectiveIndex;\n}\n/**\n * Retrieve the current `DirectiveDef` which is active when `hostBindings` instruction is being\n * executed.\n *\n * @param tData Current `TData` where the `DirectiveDef` will be looked up at.\n */\nfunction getCurrentDirectiveDef(tData) {\n const currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex;\n return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex];\n}\nfunction getCurrentQueryIndex() {\n return instructionState.lFrame.currentQueryIndex;\n}\nfunction setCurrentQueryIndex(value) {\n instructionState.lFrame.currentQueryIndex = value;\n}\n/**\n * Returns a `TNode` of the location where the current `LView` is declared at.\n *\n * @param lView an `LView` that we want to find parent `TNode` for.\n */\nfunction getDeclarationTNode(lView) {\n const tView = lView[TVIEW];\n // Return the declaration parent for embedded views\n if (tView.type === 2 /* TViewType.Embedded */) {\n ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');\n return tView.declTNode;\n }\n // Components don't have `TView.declTNode` because each instance of component could be\n // inserted in different location, hence `TView.declTNode` is meaningless.\n // Falling back to `T_HOST` in case we cross component boundary.\n if (tView.type === 1 /* TViewType.Component */) {\n return lView[T_HOST];\n }\n // Remaining TNode type is `TViewType.Root` which doesn't have a parent TNode.\n return null;\n}\n/**\n * This is a light weight version of the `enterView` which is needed by the DI system.\n *\n * @param lView `LView` location of the DI context.\n * @param tNode `TNode` for DI context\n * @param flags DI context flags. if `SkipSelf` flag is set than we walk up the declaration\n * tree from `tNode` until we find parent declared `TElementNode`.\n * @returns `true` if we have successfully entered DI associated with `tNode` (or with declared\n * `TNode` if `flags` has `SkipSelf`). Failing to enter DI implies that no associated\n * `NodeInjector` can be found and we should instead use `ModuleInjector`.\n * - If `true` than this call must be fallowed by `leaveDI`\n * - If `false` than this call failed and we should NOT call `leaveDI`\n */\nfunction enterDI(lView, tNode, flags) {\n ngDevMode && assertLViewOrUndefined(lView);\n if (flags & InjectFlags.SkipSelf) {\n ngDevMode && assertTNodeForTView(tNode, lView[TVIEW]);\n let parentTNode = tNode;\n let parentLView = lView;\n while (true) {\n ngDevMode && assertDefined(parentTNode, 'Parent TNode should be defined');\n parentTNode = parentTNode.parent;\n if (parentTNode === null && !(flags & InjectFlags.Host)) {\n parentTNode = getDeclarationTNode(parentLView);\n if (parentTNode === null)\n break;\n // In this case, a parent exists and is definitely an element. So it will definitely\n // have an existing lView as the declaration view, which is why we can assume it's defined.\n ngDevMode && assertDefined(parentLView, 'Parent LView should be defined');\n parentLView = parentLView[DECLARATION_VIEW];\n // In Ivy there are Comment nodes that correspond to ngIf and NgFor embedded directives\n // We want to skip those and look only at Elements and ElementContainers to ensure\n // we're looking at true parent nodes, and not content or other types.\n if (parentTNode.type & (2 /* TNodeType.Element */ | 8 /* TNodeType.ElementContainer */)) {\n break;\n }\n }\n else {\n break;\n }\n }\n if (parentTNode === null) {\n // If we failed to find a parent TNode this means that we should use module injector.\n return false;\n }\n else {\n tNode = parentTNode;\n lView = parentLView;\n }\n }\n ngDevMode && assertTNodeForLView(tNode, lView);\n const lFrame = instructionState.lFrame = allocLFrame();\n lFrame.currentTNode = tNode;\n lFrame.lView = lView;\n return true;\n}\n/**\n * Swap the current lView with a new lView.\n *\n * For performance reasons we store the lView in the top level of the module.\n * This way we minimize the number of properties to read. Whenever a new view\n * is entered we have to store the lView for later, and when the view is\n * exited the state has to be restored\n *\n * @param newView New lView to become active\n * @returns the previously active lView;\n */\nfunction enterView(newView) {\n ngDevMode && assertNotEqual(newView[0], newView[1], '????');\n ngDevMode && assertLViewOrUndefined(newView);\n const newLFrame = allocLFrame();\n if (ngDevMode) {\n assertEqual(newLFrame.isParent, true, 'Expected clean LFrame');\n assertEqual(newLFrame.lView, null, 'Expected clean LFrame');\n assertEqual(newLFrame.tView, null, 'Expected clean LFrame');\n assertEqual(newLFrame.selectedIndex, -1, 'Expected clean LFrame');\n assertEqual(newLFrame.elementDepthCount, 0, 'Expected clean LFrame');\n assertEqual(newLFrame.currentDirectiveIndex, -1, 'Expected clean LFrame');\n assertEqual(newLFrame.currentNamespace, null, 'Expected clean LFrame');\n assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame');\n assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame');\n }\n const tView = newView[TVIEW];\n instructionState.lFrame = newLFrame;\n ngDevMode && tView.firstChild && assertTNodeForTView(tView.firstChild, tView);\n newLFrame.currentTNode = tView.firstChild;\n newLFrame.lView = newView;\n newLFrame.tView = tView;\n newLFrame.contextLView = newView;\n newLFrame.bindingIndex = tView.bindingStartIndex;\n newLFrame.inI18n = false;\n}\n/**\n * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.\n */\nfunction allocLFrame() {\n const currentLFrame = instructionState.lFrame;\n const childLFrame = currentLFrame === null ? null : currentLFrame.child;\n const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;\n return newLFrame;\n}\nfunction createLFrame(parent) {\n const lFrame = {\n currentTNode: null,\n isParent: true,\n lView: null,\n tView: null,\n selectedIndex: -1,\n contextLView: null,\n elementDepthCount: 0,\n currentNamespace: null,\n currentDirectiveIndex: -1,\n bindingRootIndex: -1,\n bindingIndex: -1,\n currentQueryIndex: 0,\n parent: parent,\n child: null,\n inI18n: false,\n };\n parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.\n return lFrame;\n}\n/**\n * A lightweight version of leave which is used with DI.\n *\n * This function only resets `currentTNode` and `LView` as those are the only properties\n * used with DI (`enterDI()`).\n *\n * NOTE: This function is reexported as `leaveDI`. However `leaveDI` has return type of `void` where\n * as `leaveViewLight` has `LFrame`. This is so that `leaveViewLight` can be used in `leaveView`.\n */\nfunction leaveViewLight() {\n const oldLFrame = instructionState.lFrame;\n instructionState.lFrame = oldLFrame.parent;\n oldLFrame.currentTNode = null;\n oldLFrame.lView = null;\n return oldLFrame;\n}\n/**\n * This is a lightweight version of the `leaveView` which is needed by the DI system.\n *\n * NOTE: this function is an alias so that we can change the type of the function to have `void`\n * return type.\n */\nconst leaveDI = leaveViewLight;\n/**\n * Leave the current `LView`\n *\n * This pops the `LFrame` with the associated `LView` from the stack.\n *\n * IMPORTANT: We must zero out the `LFrame` values here otherwise they will be retained. This is\n * because for performance reasons we don't release `LFrame` but rather keep it for next use.\n */\nfunction leaveView() {\n const oldLFrame = leaveViewLight();\n oldLFrame.isParent = true;\n oldLFrame.tView = null;\n oldLFrame.selectedIndex = -1;\n oldLFrame.contextLView = null;\n oldLFrame.elementDepthCount = 0;\n oldLFrame.currentDirectiveIndex = -1;\n oldLFrame.currentNamespace = null;\n oldLFrame.bindingRootIndex = -1;\n oldLFrame.bindingIndex = -1;\n oldLFrame.currentQueryIndex = 0;\n}\nfunction nextContextImpl(level) {\n const contextLView = instructionState.lFrame.contextLView =\n walkUpViews(level, instructionState.lFrame.contextLView);\n return contextLView[CONTEXT];\n}\nfunction walkUpViews(nestingLevel, currentView) {\n while (nestingLevel > 0) {\n ngDevMode &&\n assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');\n currentView = currentView[DECLARATION_VIEW];\n nestingLevel--;\n }\n return currentView;\n}\n/**\n * Gets the currently selected element index.\n *\n * Used with {@link property} instruction (and more in the future) to identify the index in the\n * current `LView` to act on.\n */\nfunction getSelectedIndex() {\n return instructionState.lFrame.selectedIndex;\n}\n/**\n * Sets the most recent index passed to {@link select}\n *\n * Used with {@link property} instruction (and more in the future) to identify the index in the\n * current `LView` to act on.\n *\n * (Note that if an \"exit function\" was set earlier (via `setElementExitFn()`) then that will be\n * run if and when the provided `index` value is different from the current selected index value.)\n */\nfunction setSelectedIndex(index) {\n ngDevMode && index !== -1 &&\n assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Index must be past HEADER_OFFSET (or -1).');\n ngDevMode &&\n assertLessThan(index, instructionState.lFrame.lView.length, 'Can\\'t set index passed end of LView');\n instructionState.lFrame.selectedIndex = index;\n}\n/**\n * Gets the `tNode` that represents currently selected element.\n */\nfunction getSelectedTNode() {\n const lFrame = instructionState.lFrame;\n return getTNode(lFrame.tView, lFrame.selectedIndex);\n}\n/**\n * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.\n *\n * @codeGenApi\n */\nfunction ɵɵnamespaceSVG() {\n instructionState.lFrame.currentNamespace = SVG_NAMESPACE;\n}\n/**\n * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state.\n *\n * @codeGenApi\n */\nfunction ɵɵnamespaceMathML() {\n instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;\n}\n/**\n * Sets the namespace used to create elements to `null`, which forces element creation to use\n * `createElement` rather than `createElementNS`.\n *\n * @codeGenApi\n */\nfunction ɵɵnamespaceHTML() {\n namespaceHTMLInternal();\n}\n/**\n * Sets the namespace used to create elements to `null`, which forces element creation to use\n * `createElement` rather than `createElementNS`.\n */\nfunction namespaceHTMLInternal() {\n instructionState.lFrame.currentNamespace = null;\n}\nfunction getNamespace$1() {\n return instructionState.lFrame.currentNamespace;\n}\nlet _wasLastNodeCreated = true;\n/**\n * Retrieves a global flag that indicates whether the most recent DOM node\n * was created or hydrated.\n */\nfunction wasLastNodeCreated() {\n return _wasLastNodeCreated;\n}\n/**\n * Sets a global flag to indicate whether the most recent DOM node\n * was created or hydrated.\n */\nfunction lastNodeWasCreated(flag) {\n _wasLastNodeCreated = flag;\n}\n\n/**\n * Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.\n *\n * Must be run *only* on the first template pass.\n *\n * Sets up the pre-order hooks on the provided `tView`,\n * see {@link HookData} for details about the data structure.\n *\n * @param directiveIndex The index of the directive in LView\n * @param directiveDef The definition containing the hooks to setup in tView\n * @param tView The current TView\n */\nfunction registerPreOrderHooks(directiveIndex, directiveDef, tView) {\n ngDevMode && assertFirstCreatePass(tView);\n const { ngOnChanges, ngOnInit, ngDoCheck } = directiveDef.type.prototype;\n if (ngOnChanges) {\n const wrappedOnChanges = NgOnChangesFeatureImpl(directiveDef);\n (tView.preOrderHooks ??= []).push(directiveIndex, wrappedOnChanges);\n (tView.preOrderCheckHooks ??= []).push(directiveIndex, wrappedOnChanges);\n }\n if (ngOnInit) {\n (tView.preOrderHooks ??= []).push(0 - directiveIndex, ngOnInit);\n }\n if (ngDoCheck) {\n (tView.preOrderHooks ??= []).push(directiveIndex, ngDoCheck);\n (tView.preOrderCheckHooks ??= []).push(directiveIndex, ngDoCheck);\n }\n}\n/**\n *\n * Loops through the directives on the provided `tNode` and queues hooks to be\n * run that are not initialization hooks.\n *\n * Should be executed during `elementEnd()` and similar to\n * preserve hook execution order. Content, view, and destroy hooks for projected\n * components and directives must be called *before* their hosts.\n *\n * Sets up the content, view, and destroy hooks on the provided `tView`,\n * see {@link HookData} for details about the data structure.\n *\n * NOTE: This does not set up `onChanges`, `onInit` or `doCheck`, those are set up\n * separately at `elementStart`.\n *\n * @param tView The current TView\n * @param tNode The TNode whose directives are to be searched for hooks to queue\n */\nfunction registerPostOrderHooks(tView, tNode) {\n ngDevMode && assertFirstCreatePass(tView);\n // It's necessary to loop through the directives at elementEnd() (rather than processing in\n // directiveCreate) so we can preserve the current hook order. Content, view, and destroy\n // hooks for projected components and directives must be called *before* their hosts.\n for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) {\n const directiveDef = tView.data[i];\n ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef');\n const lifecycleHooks = directiveDef.type.prototype;\n const { ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, ngAfterViewChecked, ngOnDestroy } = lifecycleHooks;\n if (ngAfterContentInit) {\n (tView.contentHooks ??= []).push(-i, ngAfterContentInit);\n }\n if (ngAfterContentChecked) {\n (tView.contentHooks ??= []).push(i, ngAfterContentChecked);\n (tView.contentCheckHooks ??= []).push(i, ngAfterContentChecked);\n }\n if (ngAfterViewInit) {\n (tView.viewHooks ??= []).push(-i, ngAfterViewInit);\n }\n if (ngAfterViewChecked) {\n (tView.viewHooks ??= []).push(i, ngAfterViewChecked);\n (tView.viewCheckHooks ??= []).push(i, ngAfterViewChecked);\n }\n if (ngOnDestroy != null) {\n (tView.destroyHooks ??= []).push(i, ngOnDestroy);\n }\n }\n}\n/**\n * Executing hooks requires complex logic as we need to deal with 2 constraints.\n *\n * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only\n * once, across many change detection cycles. This must be true even if some hooks throw, or if\n * some recursively trigger a change detection cycle.\n * To solve that, it is required to track the state of the execution of these init hooks.\n * This is done by storing and maintaining flags in the view: the {@link InitPhaseState},\n * and the index within that phase. They can be seen as a cursor in the following structure:\n * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]]\n * They are stored as flags in LView[FLAGS].\n *\n * 2. Pre-order hooks can be executed in batches, because of the select instruction.\n * To be able to pause and resume their execution, we also need some state about the hook's array\n * that is being processed:\n * - the index of the next hook to be executed\n * - the number of init hooks already found in the processed part of the array\n * They are stored as flags in LView[PREORDER_HOOK_FLAGS].\n */\n/**\n * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were\n * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read\n * / write of the init-hooks related flags.\n * @param lView The LView where hooks are defined\n * @param hooks Hooks to be run\n * @param nodeIndex 3 cases depending on the value:\n * - undefined: all hooks from the array should be executed (post-order case)\n * - null: execute hooks only from the saved index until the end of the array (pre-order case, when\n * flushing the remaining hooks)\n * - number: execute hooks only from the saved index until that node index exclusive (pre-order\n * case, when executing select(number))\n */\nfunction executeCheckHooks(lView, hooks, nodeIndex) {\n callHooks(lView, hooks, 3 /* InitPhaseState.InitPhaseCompleted */, nodeIndex);\n}\n/**\n * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked,\n * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed.\n * @param lView The LView where hooks are defined\n * @param hooks Hooks to be run\n * @param initPhase A phase for which hooks should be run\n * @param nodeIndex 3 cases depending on the value:\n * - undefined: all hooks from the array should be executed (post-order case)\n * - null: execute hooks only from the saved index until the end of the array (pre-order case, when\n * flushing the remaining hooks)\n * - number: execute hooks only from the saved index until that node index exclusive (pre-order\n * case, when executing select(number))\n */\nfunction executeInitAndCheckHooks(lView, hooks, initPhase, nodeIndex) {\n ngDevMode &&\n assertNotEqual(initPhase, 3 /* InitPhaseState.InitPhaseCompleted */, 'Init pre-order hooks should not be called more than once');\n if ((lView[FLAGS] & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {\n callHooks(lView, hooks, initPhase, nodeIndex);\n }\n}\nfunction incrementInitPhaseFlags(lView, initPhase) {\n ngDevMode &&\n assertNotEqual(initPhase, 3 /* InitPhaseState.InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');\n let flags = lView[FLAGS];\n if ((flags & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {\n flags &= 8191 /* LViewFlags.IndexWithinInitPhaseReset */;\n flags += 1 /* LViewFlags.InitPhaseStateIncrementer */;\n lView[FLAGS] = flags;\n }\n}\n/**\n * Calls lifecycle hooks with their contexts, skipping init hooks if it's not\n * the first LView pass\n *\n * @param currentView The current view\n * @param arr The array in which the hooks are found\n * @param initPhaseState the current state of the init phase\n * @param currentNodeIndex 3 cases depending on the value:\n * - undefined: all hooks from the array should be executed (post-order case)\n * - null: execute hooks only from the saved index until the end of the array (pre-order case, when\n * flushing the remaining hooks)\n * - number: execute hooks only from the saved index until that node index exclusive (pre-order\n * case, when executing select(number))\n */\nfunction callHooks(currentView, arr, initPhase, currentNodeIndex) {\n ngDevMode &&\n assertEqual(isInCheckNoChangesMode(), false, 'Hooks should never be run when in check no changes mode.');\n const startIndex = currentNodeIndex !== undefined ?\n (currentView[PREORDER_HOOK_FLAGS] & 65535 /* PreOrderHookFlags.IndexOfTheNextPreOrderHookMaskMask */) :\n 0;\n const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;\n const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1\n let lastNodeIndexFound = 0;\n for (let i = startIndex; i < max; i++) {\n const hook = arr[i + 1];\n if (typeof hook === 'number') {\n lastNodeIndexFound = arr[i];\n if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) {\n break;\n }\n }\n else {\n const isInitHook = arr[i] < 0;\n if (isInitHook) {\n currentView[PREORDER_HOOK_FLAGS] += 65536 /* PreOrderHookFlags.NumberOfInitHooksCalledIncrementer */;\n }\n if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {\n callHook(currentView, initPhase, arr, i);\n currentView[PREORDER_HOOK_FLAGS] =\n (currentView[PREORDER_HOOK_FLAGS] & 4294901760 /* PreOrderHookFlags.NumberOfInitHooksCalledMask */) + i +\n 2;\n }\n i++;\n }\n }\n}\n/**\n * Executes a single lifecycle hook, making sure that:\n * - it is called in the non-reactive context;\n * - profiling data are registered.\n */\nfunction callHookInternal(directive, hook) {\n profiler(4 /* ProfilerEvent.LifecycleHookStart */, directive, hook);\n const prevConsumer = setActiveConsumer(null);\n try {\n hook.call(directive);\n }\n finally {\n setActiveConsumer(prevConsumer);\n profiler(5 /* ProfilerEvent.LifecycleHookEnd */, directive, hook);\n }\n}\n/**\n * Execute one hook against the current `LView`.\n *\n * @param currentView The current view\n * @param initPhaseState the current state of the init phase\n * @param arr The array in which the hooks are found\n * @param i The current index within the hook data array\n */\nfunction callHook(currentView, initPhase, arr, i) {\n const isInitHook = arr[i] < 0;\n const hook = arr[i + 1];\n const directiveIndex = isInitHook ? -arr[i] : arr[i];\n const directive = currentView[directiveIndex];\n if (isInitHook) {\n const indexWithintInitPhase = currentView[FLAGS] >> 13 /* LViewFlags.IndexWithinInitPhaseShift */;\n // The init phase state must be always checked here as it may have been recursively updated.\n if (indexWithintInitPhase <\n (currentView[PREORDER_HOOK_FLAGS] >> 16 /* PreOrderHookFlags.NumberOfInitHooksCalledShift */) &&\n (currentView[FLAGS] & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {\n currentView[FLAGS] += 8192 /* LViewFlags.IndexWithinInitPhaseIncrementer */;\n callHookInternal(directive, hook);\n }\n }\n else {\n callHookInternal(directive, hook);\n }\n}\n\nconst NO_PARENT_INJECTOR = -1;\n/**\n * Each injector is saved in 9 contiguous slots in `LView` and 9 contiguous slots in\n * `TView.data`. This allows us to store information about the current node's tokens (which\n * can be shared in `TView`) as well as the tokens of its ancestor nodes (which cannot be\n * shared, so they live in `LView`).\n *\n * Each of these slots (aside from the last slot) contains a bloom filter. This bloom filter\n * determines whether a directive is available on the associated node or not. This prevents us\n * from searching the directives array at this level unless it's probable the directive is in it.\n *\n * See: https://en.wikipedia.org/wiki/Bloom_filter for more about bloom filters.\n *\n * Because all injectors have been flattened into `LView` and `TViewData`, they cannot typed\n * using interfaces as they were previously. The start index of each `LInjector` and `TInjector`\n * will differ based on where it is flattened into the main array, so it's not possible to know\n * the indices ahead of time and save their types here. The interfaces are still included here\n * for documentation purposes.\n *\n * export interface LInjector extends Array {\n *\n * // Cumulative bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)\n * [0]: number;\n *\n * // Cumulative bloom for directive IDs 32-63\n * [1]: number;\n *\n * // Cumulative bloom for directive IDs 64-95\n * [2]: number;\n *\n * // Cumulative bloom for directive IDs 96-127\n * [3]: number;\n *\n * // Cumulative bloom for directive IDs 128-159\n * [4]: number;\n *\n * // Cumulative bloom for directive IDs 160 - 191\n * [5]: number;\n *\n * // Cumulative bloom for directive IDs 192 - 223\n * [6]: number;\n *\n * // Cumulative bloom for directive IDs 224 - 255\n * [7]: number;\n *\n * // We need to store a reference to the injector's parent so DI can keep looking up\n * // the injector tree until it finds the dependency it's looking for.\n * [PARENT_INJECTOR]: number;\n * }\n *\n * export interface TInjector extends Array {\n *\n * // Shared node bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)\n * [0]: number;\n *\n * // Shared node bloom for directive IDs 32-63\n * [1]: number;\n *\n * // Shared node bloom for directive IDs 64-95\n * [2]: number;\n *\n * // Shared node bloom for directive IDs 96-127\n * [3]: number;\n *\n * // Shared node bloom for directive IDs 128-159\n * [4]: number;\n *\n * // Shared node bloom for directive IDs 160 - 191\n * [5]: number;\n *\n * // Shared node bloom for directive IDs 192 - 223\n * [6]: number;\n *\n * // Shared node bloom for directive IDs 224 - 255\n * [7]: number;\n *\n * // Necessary to find directive indices for a particular node.\n * [TNODE]: TElementNode|TElementContainerNode|TContainerNode;\n * }\n */\n/**\n * Factory for creating instances of injectors in the NodeInjector.\n *\n * This factory is complicated by the fact that it can resolve `multi` factories as well.\n *\n * NOTE: Some of the fields are optional which means that this class has two hidden classes.\n * - One without `multi` support (most common)\n * - One with `multi` values, (rare).\n *\n * Since VMs can cache up to 4 inline hidden classes this is OK.\n *\n * - Single factory: Only `resolving` and `factory` is defined.\n * - `providers` factory: `componentProviders` is a number and `index = -1`.\n * - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`.\n */\nclass NodeInjectorFactory {\n constructor(\n /**\n * Factory to invoke in order to create a new instance.\n */\n factory, \n /**\n * Set to `true` if the token is declared in `viewProviders` (or if it is component).\n */\n isViewProvider, injectImplementation) {\n this.factory = factory;\n /**\n * Marker set to true during factory invocation to see if we get into recursive loop.\n * Recursive loop causes an error to be displayed.\n */\n this.resolving = false;\n ngDevMode && assertDefined(factory, 'Factory not specified');\n ngDevMode && assertEqual(typeof factory, 'function', 'Expected factory function.');\n this.canSeeViewProviders = isViewProvider;\n this.injectImpl = injectImplementation;\n }\n}\nfunction isFactory(obj) {\n return obj instanceof NodeInjectorFactory;\n}\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nconst unusedValueExportToPlacateAjd$2 = 1;\n\n/**\n * Converts `TNodeType` into human readable text.\n * Make sure this matches with `TNodeType`\n */\nfunction toTNodeTypeAsString(tNodeType) {\n let text = '';\n (tNodeType & 1 /* TNodeType.Text */) && (text += '|Text');\n (tNodeType & 2 /* TNodeType.Element */) && (text += '|Element');\n (tNodeType & 4 /* TNodeType.Container */) && (text += '|Container');\n (tNodeType & 8 /* TNodeType.ElementContainer */) && (text += '|ElementContainer');\n (tNodeType & 16 /* TNodeType.Projection */) && (text += '|Projection');\n (tNodeType & 32 /* TNodeType.Icu */) && (text += '|IcuContainer');\n (tNodeType & 64 /* TNodeType.Placeholder */) && (text += '|Placeholder');\n return text.length > 0 ? text.substring(1) : text;\n}\n// Note: This hack is necessary so we don't erroneously get a circular dependency\n// failure based on types.\nconst unusedValueExportToPlacateAjd$1 = 1;\n/**\n * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.\n *\n * ```\n * \n * ```\n * and\n * ```\n * @Directive({\n * })\n * class MyDirective {\n * @Input()\n * class: string;\n * }\n * ```\n *\n * In the above case it is necessary to write the reconciled styling information into the\n * directive's input.\n *\n * @param tNode\n */\nfunction hasClassInput(tNode) {\n return (tNode.flags & 8 /* TNodeFlags.hasClassInput */) !== 0;\n}\n/**\n * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.\n *\n * ```\n * \n * ```\n * and\n * ```\n * @Directive({\n * })\n * class MyDirective {\n * @Input()\n * class: string;\n * }\n * ```\n *\n * In the above case it is necessary to write the reconciled styling information into the\n * directive's input.\n *\n * @param tNode\n */\nfunction hasStyleInput(tNode) {\n return (tNode.flags & 16 /* TNodeFlags.hasStyleInput */) !== 0;\n}\n\nfunction assertTNodeType(tNode, expectedTypes, message) {\n assertDefined(tNode, 'should be called with a TNode');\n if ((tNode.type & expectedTypes) === 0) {\n throwError(message ||\n `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`);\n }\n}\nfunction assertPureTNodeType(type) {\n if (!(type === 2 /* TNodeType.Element */ || //\n type === 1 /* TNodeType.Text */ || //\n type === 4 /* TNodeType.Container */ || //\n type === 8 /* TNodeType.ElementContainer */ || //\n type === 32 /* TNodeType.Icu */ || //\n type === 16 /* TNodeType.Projection */ || //\n type === 64 /* TNodeType.Placeholder */)) {\n throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`);\n }\n}\n\n/// Parent Injector Utils ///////////////////////////////////////////////////////////////\nfunction hasParentInjector(parentLocation) {\n return parentLocation !== NO_PARENT_INJECTOR;\n}\nfunction getParentInjectorIndex(parentLocation) {\n ngDevMode && assertNumber(parentLocation, 'Number expected');\n ngDevMode && assertNotEqual(parentLocation, -1, 'Not a valid state.');\n const parentInjectorIndex = parentLocation & 32767 /* RelativeInjectorLocationFlags.InjectorIndexMask */;\n ngDevMode &&\n assertGreaterThan(parentInjectorIndex, HEADER_OFFSET, 'Parent injector must be pointing past HEADER_OFFSET.');\n return parentLocation & 32767 /* RelativeInjectorLocationFlags.InjectorIndexMask */;\n}\nfunction getParentInjectorViewOffset(parentLocation) {\n return parentLocation >> 16 /* RelativeInjectorLocationFlags.ViewOffsetShift */;\n}\n/**\n * Unwraps a parent injector location number to find the view offset from the current injector,\n * then walks up the declaration view tree until the view is found that contains the parent\n * injector.\n *\n * @param location The location of the parent injector, which contains the view offset\n * @param startView The LView instance from which to start walking up the view tree\n * @returns The LView instance that contains the parent injector\n */\nfunction getParentInjectorView(location, startView) {\n let viewOffset = getParentInjectorViewOffset(location);\n let parentView = startView;\n // For most cases, the parent injector can be found on the host node (e.g. for component\n // or container), but we must keep the loop here to support the rarer case of deeply nested\n // tags or inline views, where the parent injector might live many views\n // above the child injector.\n while (viewOffset > 0) {\n parentView = parentView[DECLARATION_VIEW];\n viewOffset--;\n }\n return parentView;\n}\n\n/**\n * Defines if the call to `inject` should include `viewProviders` in its resolution.\n *\n * This is set to true when we try to instantiate a component. This value is reset in\n * `getNodeInjectable` to a value which matches the declaration location of the token about to be\n * instantiated. This is done so that if we are injecting a token which was declared outside of\n * `viewProviders` we don't accidentally pull `viewProviders` in.\n *\n * Example:\n *\n * ```\n * @Injectable()\n * class MyService {\n * constructor(public value: String) {}\n * }\n *\n * @Component({\n * providers: [\n * MyService,\n * {provide: String, value: 'providers' }\n * ]\n * viewProviders: [\n * {provide: String, value: 'viewProviders'}\n * ]\n * })\n * class MyComponent {\n * constructor(myService: MyService, value: String) {\n * // We expect that Component can see into `viewProviders`.\n * expect(value).toEqual('viewProviders');\n * // `MyService` was not declared in `viewProviders` hence it can't see it.\n * expect(myService.value).toEqual('providers');\n * }\n * }\n *\n * ```\n */\nlet includeViewProviders = true;\nfunction setIncludeViewProviders(v) {\n const oldValue = includeViewProviders;\n includeViewProviders = v;\n return oldValue;\n}\n/**\n * The number of slots in each bloom filter (used by DI). The larger this number, the fewer\n * directives that will share slots, and thus, the fewer false positives when checking for\n * the existence of a directive.\n */\nconst BLOOM_SIZE = 256;\nconst BLOOM_MASK = BLOOM_SIZE - 1;\n/**\n * The number of bits that is represented by a single bloom bucket. JS bit operations are 32 bits,\n * so each bucket represents 32 distinct tokens which accounts for log2(32) = 5 bits of a bloom hash\n * number.\n */\nconst BLOOM_BUCKET_BITS = 5;\n/** Counter used to generate unique IDs for directives. */\nlet nextNgElementId = 0;\n/** Value used when something wasn't found by an injector. */\nconst NOT_FOUND = {};\n/**\n * Registers this directive as present in its node's injector by flipping the directive's\n * corresponding bit in the injector's bloom filter.\n *\n * @param injectorIndex The index of the node injector where this token should be registered\n * @param tView The TView for the injector's bloom filters\n * @param type The directive token to register\n */\nfunction bloomAdd(injectorIndex, tView, type) {\n ngDevMode && assertEqual(tView.firstCreatePass, true, 'expected firstCreatePass to be true');\n let id;\n if (typeof type === 'string') {\n id = type.charCodeAt(0) || 0;\n }\n else if (type.hasOwnProperty(NG_ELEMENT_ID)) {\n id = type[NG_ELEMENT_ID];\n }\n // Set a unique ID on the directive type, so if something tries to inject the directive,\n // we can easily retrieve the ID and hash it into the bloom bit that should be checked.\n if (id == null) {\n id = type[NG_ELEMENT_ID] = nextNgElementId++;\n }\n // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),\n // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.\n const bloomHash = id & BLOOM_MASK;\n // Create a mask that targets the specific bit associated with the directive.\n // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding\n // to bit positions 0 - 31 in a 32 bit integer.\n const mask = 1 << bloomHash;\n // Each bloom bucket in `tData` represents `BLOOM_BUCKET_BITS` number of bits of `bloomHash`.\n // Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset that the mask\n // should be written to.\n tView.data[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)] |= mask;\n}\n/**\n * Creates (or gets an existing) injector for a given element or container.\n *\n * @param tNode for which an injector should be retrieved / created.\n * @param lView View where the node is stored\n * @returns Node injector\n */\nfunction getOrCreateNodeInjectorForNode(tNode, lView) {\n const existingInjectorIndex = getInjectorIndex(tNode, lView);\n if (existingInjectorIndex !== -1) {\n return existingInjectorIndex;\n }\n const tView = lView[TVIEW];\n if (tView.firstCreatePass) {\n tNode.injectorIndex = lView.length;\n insertBloom(tView.data, tNode); // foundation for node bloom\n insertBloom(lView, null); // foundation for cumulative bloom\n insertBloom(tView.blueprint, null);\n }\n const parentLoc = getParentInjectorLocation(tNode, lView);\n const injectorIndex = tNode.injectorIndex;\n // If a parent injector can't be found, its location is set to -1.\n // In that case, we don't need to set up a cumulative bloom\n if (hasParentInjector(parentLoc)) {\n const parentIndex = getParentInjectorIndex(parentLoc);\n const parentLView = getParentInjectorView(parentLoc, lView);\n const parentData = parentLView[TVIEW].data;\n // Creates a cumulative bloom filter that merges the parent's bloom filter\n // and its own cumulative bloom (which contains tokens for all ancestors)\n for (let i = 0; i < 8 /* NodeInjectorOffset.BLOOM_SIZE */; i++) {\n lView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i];\n }\n }\n lView[injectorIndex + 8 /* NodeInjectorOffset.PARENT */] = parentLoc;\n return injectorIndex;\n}\nfunction insertBloom(arr, footer) {\n arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);\n}\nfunction getInjectorIndex(tNode, lView) {\n if (tNode.injectorIndex === -1 ||\n // If the injector index is the same as its parent's injector index, then the index has been\n // copied down from the parent node. No injector has been created yet on this node.\n (tNode.parent && tNode.parent.injectorIndex === tNode.injectorIndex) ||\n // After the first template pass, the injector index might exist but the parent values\n // might not have been calculated yet for this instance\n lView[tNode.injectorIndex + 8 /* NodeInjectorOffset.PARENT */] === null) {\n return -1;\n }\n else {\n ngDevMode && assertIndexInRange(lView, tNode.injectorIndex);\n return tNode.injectorIndex;\n }\n}\n/**\n * Finds the index of the parent injector, with a view offset if applicable. Used to set the\n * parent injector initially.\n *\n * @returns Returns a number that is the combination of the number of LViews that we have to go up\n * to find the LView containing the parent inject AND the index of the injector within that LView.\n */\nfunction getParentInjectorLocation(tNode, lView) {\n if (tNode.parent && tNode.parent.injectorIndex !== -1) {\n // If we have a parent `TNode` and there is an injector associated with it we are done, because\n // the parent injector is within the current `LView`.\n return tNode.parent.injectorIndex; // ViewOffset is 0\n }\n // When parent injector location is computed it may be outside of the current view. (ie it could\n // be pointing to a declared parent location). This variable stores number of declaration parents\n // we need to walk up in order to find the parent injector location.\n let declarationViewOffset = 0;\n let parentTNode = null;\n let lViewCursor = lView;\n // The parent injector is not in the current `LView`. We will have to walk the declared parent\n // `LView` hierarchy and look for it. If we walk of the top, that means that there is no parent\n // `NodeInjector`.\n while (lViewCursor !== null) {\n parentTNode = getTNodeFromLView(lViewCursor);\n if (parentTNode === null) {\n // If we have no parent, than we are done.\n return NO_PARENT_INJECTOR;\n }\n ngDevMode && parentTNode && assertTNodeForLView(parentTNode, lViewCursor[DECLARATION_VIEW]);\n // Every iteration of the loop requires that we go to the declared parent.\n declarationViewOffset++;\n lViewCursor = lViewCursor[DECLARATION_VIEW];\n if (parentTNode.injectorIndex !== -1) {\n // We found a NodeInjector which points to something.\n return (parentTNode.injectorIndex |\n (declarationViewOffset << 16 /* RelativeInjectorLocationFlags.ViewOffsetShift */));\n }\n }\n return NO_PARENT_INJECTOR;\n}\n/**\n * Makes a type or an injection token public to the DI system by adding it to an\n * injector's bloom filter.\n *\n * @param di The node injector in which a directive will be added\n * @param token The type or the injection token to be made public\n */\nfunction diPublicInInjector(injectorIndex, tView, token) {\n bloomAdd(injectorIndex, tView, token);\n}\n/**\n * Inject static attribute value into directive constructor.\n *\n * This method is used with `factory` functions which are generated as part of\n * `defineDirective` or `defineComponent`. The method retrieves the static value\n * of an attribute. (Dynamic attributes are not supported since they are not resolved\n * at the time of injection and can change over time.)\n *\n * # Example\n * Given:\n * ```\n * @Component(...)\n * class MyComponent {\n * constructor(@Attribute('title') title: string) { ... }\n * }\n * ```\n * When instantiated with\n * ```\n * \n * ```\n *\n * Then factory method generated is:\n * ```\n * MyComponent.ɵcmp = defineComponent({\n * factory: () => new MyComponent(injectAttribute('title'))\n * ...\n * })\n * ```\n *\n * @publicApi\n */\nfunction injectAttributeImpl(tNode, attrNameToInject) {\n ngDevMode && assertTNodeType(tNode, 12 /* TNodeType.AnyContainer */ | 3 /* TNodeType.AnyRNode */);\n ngDevMode && assertDefined(tNode, 'expecting tNode');\n if (attrNameToInject === 'class') {\n return tNode.classes;\n }\n if (attrNameToInject === 'style') {\n return tNode.styles;\n }\n const attrs = tNode.attrs;\n if (attrs) {\n const attrsLength = attrs.length;\n let i = 0;\n while (i < attrsLength) {\n const value = attrs[i];\n // If we hit a `Bindings` or `Template` marker then we are done.\n if (isNameOnlyAttributeMarker(value))\n break;\n // Skip namespaced attributes\n if (value === 0 /* AttributeMarker.NamespaceURI */) {\n // we skip the next two values\n // as namespaced attributes looks like\n // [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist',\n // 'existValue', ...]\n i = i + 2;\n }\n else if (typeof value === 'number') {\n // Skip to the first value of the marked attribute.\n i++;\n while (i < attrsLength && typeof attrs[i] === 'string') {\n i++;\n }\n }\n else if (value === attrNameToInject) {\n return attrs[i + 1];\n }\n else {\n i = i + 2;\n }\n }\n }\n return null;\n}\nfunction notFoundValueOrThrow(notFoundValue, token, flags) {\n if ((flags & InjectFlags.Optional) || notFoundValue !== undefined) {\n return notFoundValue;\n }\n else {\n throwProviderNotFoundError(token, 'NodeInjector');\n }\n}\n/**\n * Returns the value associated to the given token from the ModuleInjector or throws exception\n *\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector or throws an exception\n */\nfunction lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue) {\n if ((flags & InjectFlags.Optional) && notFoundValue === undefined) {\n // This must be set or the NullInjector will throw for optional deps\n notFoundValue = null;\n }\n if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {\n const moduleInjector = lView[INJECTOR$1];\n // switch to `injectInjectorOnly` implementation for module injector, since module injector\n // should not have access to Component/Directive DI scope (that may happen through\n // `directiveInject` implementation)\n const previousInjectImplementation = setInjectImplementation(undefined);\n try {\n if (moduleInjector) {\n return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);\n }\n else {\n return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);\n }\n }\n finally {\n setInjectImplementation(previousInjectImplementation);\n }\n }\n return notFoundValueOrThrow(notFoundValue, token, flags);\n}\n/**\n * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.\n *\n * Look for the injector providing the token by walking up the node injector tree and then\n * the module injector tree.\n *\n * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom\n * filter. `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)\n *\n * @param tNode The Node where the search for the injector should start\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided\n */\nfunction getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default, notFoundValue) {\n if (tNode !== null) {\n // If the view or any of its ancestors have an embedded\n // view injector, we have to look it up there first.\n if (lView[FLAGS] & 2048 /* LViewFlags.HasEmbeddedViewInjector */ &&\n // The token must be present on the current node injector when the `Self`\n // flag is set, so the lookup on embedded view injector(s) can be skipped.\n !(flags & InjectFlags.Self)) {\n const embeddedInjectorValue = lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, NOT_FOUND);\n if (embeddedInjectorValue !== NOT_FOUND) {\n return embeddedInjectorValue;\n }\n }\n // Otherwise try the node injector.\n const value = lookupTokenUsingNodeInjector(tNode, lView, token, flags, NOT_FOUND);\n if (value !== NOT_FOUND) {\n return value;\n }\n }\n // Finally, fall back to the module injector.\n return lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);\n}\n/**\n * Returns the value associated to the given token from the node injector.\n *\n * @param tNode The Node where the search for the injector should start\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided\n */\nfunction lookupTokenUsingNodeInjector(tNode, lView, token, flags, notFoundValue) {\n const bloomHash = bloomHashBitOrFactory(token);\n // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef\n // so just call the factory function to create it.\n if (typeof bloomHash === 'function') {\n if (!enterDI(lView, tNode, flags)) {\n // Failed to enter DI, try module injector instead. If a token is injected with the @Host\n // flag, the module injector is not searched for that token in Ivy.\n return (flags & InjectFlags.Host) ?\n notFoundValueOrThrow(notFoundValue, token, flags) :\n lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);\n }\n try {\n let value;\n if (ngDevMode) {\n runInInjectorProfilerContext(new NodeInjector(getCurrentTNode(), getLView()), token, () => {\n value = bloomHash(flags);\n if (value != null) {\n emitInstanceCreatedByInjectorEvent(value);\n }\n });\n }\n else {\n value = bloomHash(flags);\n }\n if (value == null && !(flags & InjectFlags.Optional)) {\n throwProviderNotFoundError(token);\n }\n else {\n return value;\n }\n }\n finally {\n leaveDI();\n }\n }\n else if (typeof bloomHash === 'number') {\n // A reference to the previous injector TView that was found while climbing the element\n // injector tree. This is used to know if viewProviders can be accessed on the current\n // injector.\n let previousTView = null;\n let injectorIndex = getInjectorIndex(tNode, lView);\n let parentLocation = NO_PARENT_INJECTOR;\n let hostTElementNode = flags & InjectFlags.Host ? lView[DECLARATION_COMPONENT_VIEW][T_HOST] : null;\n // If we should skip this injector, or if there is no injector on this node, start by\n // searching the parent injector.\n if (injectorIndex === -1 || flags & InjectFlags.SkipSelf) {\n parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) :\n lView[injectorIndex + 8 /* NodeInjectorOffset.PARENT */];\n if (parentLocation === NO_PARENT_INJECTOR || !shouldSearchParent(flags, false)) {\n injectorIndex = -1;\n }\n else {\n previousTView = lView[TVIEW];\n injectorIndex = getParentInjectorIndex(parentLocation);\n lView = getParentInjectorView(parentLocation, lView);\n }\n }\n // Traverse up the injector tree until we find a potential match or until we know there\n // *isn't* a match.\n while (injectorIndex !== -1) {\n ngDevMode && assertNodeInjector(lView, injectorIndex);\n // Check the current injector. If it matches, see if it contains token.\n const tView = lView[TVIEW];\n ngDevMode &&\n assertTNodeForLView(tView.data[injectorIndex + 8 /* NodeInjectorOffset.TNODE */], lView);\n if (bloomHasToken(bloomHash, injectorIndex, tView.data)) {\n // At this point, we have an injector which *may* contain the token, so we step through\n // the providers and directives associated with the injector's corresponding node to get\n // the instance.\n const instance = searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode);\n if (instance !== NOT_FOUND) {\n return instance;\n }\n }\n parentLocation = lView[injectorIndex + 8 /* NodeInjectorOffset.PARENT */];\n if (parentLocation !== NO_PARENT_INJECTOR &&\n shouldSearchParent(flags, lView[TVIEW].data[injectorIndex + 8 /* NodeInjectorOffset.TNODE */] === hostTElementNode) &&\n bloomHasToken(bloomHash, injectorIndex, lView)) {\n // The def wasn't found anywhere on this node, so it was a false positive.\n // Traverse up the tree and continue searching.\n previousTView = tView;\n injectorIndex = getParentInjectorIndex(parentLocation);\n lView = getParentInjectorView(parentLocation, lView);\n }\n else {\n // If we should not search parent OR If the ancestor bloom filter value does not have the\n // bit corresponding to the directive we can give up on traversing up to find the specific\n // injector.\n injectorIndex = -1;\n }\n }\n }\n return notFoundValue;\n}\nfunction searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode) {\n const currentTView = lView[TVIEW];\n const tNode = currentTView.data[injectorIndex + 8 /* NodeInjectorOffset.TNODE */];\n // First, we need to determine if view providers can be accessed by the starting element.\n // There are two possibilities\n const canAccessViewProviders = previousTView == null ?\n // 1) This is the first invocation `previousTView == null` which means that we are at the\n // `TNode` of where injector is starting to look. In such a case the only time we are allowed\n // to look into the ViewProviders is if:\n // - we are on a component\n // - AND the injector set `includeViewProviders` to true (implying that the token can see\n // ViewProviders because it is the Component or a Service which itself was declared in\n // ViewProviders)\n (isComponentHost(tNode) && includeViewProviders) :\n // 2) `previousTView != null` which means that we are now walking across the parent nodes.\n // In such a case we are only allowed to look into the ViewProviders if:\n // - We just crossed from child View to Parent View `previousTView != currentTView`\n // - AND the parent TNode is an Element.\n // This means that we just came from the Component's View and therefore are allowed to see\n // into the ViewProviders.\n (previousTView != currentTView && ((tNode.type & 3 /* TNodeType.AnyRNode */) !== 0));\n // This special case happens when there is a @host on the inject and when we are searching\n // on the host element node.\n const isHostSpecialCase = (flags & InjectFlags.Host) && hostTElementNode === tNode;\n const injectableIdx = locateDirectiveOrProvider(tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase);\n if (injectableIdx !== null) {\n return getNodeInjectable(lView, currentTView, injectableIdx, tNode);\n }\n else {\n return NOT_FOUND;\n }\n}\n/**\n * Searches for the given token among the node's directives and providers.\n *\n * @param tNode TNode on which directives are present.\n * @param tView The tView we are currently processing\n * @param token Provider token or type of a directive to look for.\n * @param canAccessViewProviders Whether view providers should be considered.\n * @param isHostSpecialCase Whether the host special case applies.\n * @returns Index of a found directive or provider, or null when none found.\n */\nfunction locateDirectiveOrProvider(tNode, tView, token, canAccessViewProviders, isHostSpecialCase) {\n const nodeProviderIndexes = tNode.providerIndexes;\n const tInjectables = tView.data;\n const injectablesStart = nodeProviderIndexes & 1048575 /* TNodeProviderIndexes.ProvidersStartIndexMask */;\n const directivesStart = tNode.directiveStart;\n const directiveEnd = tNode.directiveEnd;\n const cptViewProvidersCount = nodeProviderIndexes >> 20 /* TNodeProviderIndexes.CptViewProvidersCountShift */;\n const startingIndex = canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount;\n // When the host special case applies, only the viewProviders and the component are visible\n const endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd;\n for (let i = startingIndex; i < endIndex; i++) {\n const providerTokenOrDef = tInjectables[i];\n if (i < directivesStart && token === providerTokenOrDef ||\n i >= directivesStart && providerTokenOrDef.type === token) {\n return i;\n }\n }\n if (isHostSpecialCase) {\n const dirDef = tInjectables[directivesStart];\n if (dirDef && isComponentDef(dirDef) && dirDef.type === token) {\n return directivesStart;\n }\n }\n return null;\n}\n/**\n * Retrieve or instantiate the injectable from the `LView` at particular `index`.\n *\n * This function checks to see if the value has already been instantiated and if so returns the\n * cached `injectable`. Otherwise if it detects that the value is still a factory it\n * instantiates the `injectable` and caches the value.\n */\nfunction getNodeInjectable(lView, tView, index, tNode) {\n let value = lView[index];\n const tData = tView.data;\n if (isFactory(value)) {\n const factory = value;\n if (factory.resolving) {\n throwCyclicDependencyError(stringifyForError(tData[index]));\n }\n const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);\n factory.resolving = true;\n let prevInjectContext;\n if (ngDevMode) {\n // tData indexes mirror the concrete instances in its corresponding LView.\n // lView[index] here is either the injectable instace itself or a factory,\n // therefore tData[index] is the constructor of that injectable or a\n // definition object that contains the constructor in a `.type` field.\n const token = tData[index].type || tData[index];\n const injector = new NodeInjector(tNode, lView);\n prevInjectContext = setInjectorProfilerContext({ injector, token });\n }\n const previousInjectImplementation = factory.injectImpl ? setInjectImplementation(factory.injectImpl) : null;\n const success = enterDI(lView, tNode, InjectFlags.Default);\n ngDevMode &&\n assertEqual(success, true, 'Because flags do not contain \\`SkipSelf\\' we expect this to always succeed.');\n try {\n value = lView[index] = factory.factory(undefined, tData, lView, tNode);\n ngDevMode && emitInstanceCreatedByInjectorEvent(value);\n // This code path is hit for both directives and providers.\n // For perf reasons, we want to avoid searching for hooks on providers.\n // It does no harm to try (the hooks just won't exist), but the extra\n // checks are unnecessary and this is a hot path. So we check to see\n // if the index of the dependency is in the directive range for this\n // tNode. If it's not, we know it's a provider and skip hook registration.\n if (tView.firstCreatePass && index >= tNode.directiveStart) {\n ngDevMode && assertDirectiveDef(tData[index]);\n registerPreOrderHooks(index, tData[index], tView);\n }\n }\n finally {\n ngDevMode && setInjectorProfilerContext(prevInjectContext);\n previousInjectImplementation !== null &&\n setInjectImplementation(previousInjectImplementation);\n setIncludeViewProviders(previousIncludeViewProviders);\n factory.resolving = false;\n leaveDI();\n }\n }\n return value;\n}\n/**\n * Returns the bit in an injector's bloom filter that should be used to determine whether or not\n * the directive might be provided by the injector.\n *\n * When a directive is public, it is added to the bloom filter and given a unique ID that can be\n * retrieved on the Type. When the directive isn't public or the token is not a directive `null`\n * is returned as the node injector can not possibly provide that token.\n *\n * @param token the injection token\n * @returns the matching bit to check in the bloom filter or `null` if the token is not known.\n * When the returned value is negative then it represents special values such as `Injector`.\n */\nfunction bloomHashBitOrFactory(token) {\n ngDevMode && assertDefined(token, 'token must be defined');\n if (typeof token === 'string') {\n return token.charCodeAt(0) || 0;\n }\n const tokenId = \n // First check with `hasOwnProperty` so we don't get an inherited ID.\n token.hasOwnProperty(NG_ELEMENT_ID) ? token[NG_ELEMENT_ID] : undefined;\n // Negative token IDs are used for special objects such as `Injector`\n if (typeof tokenId === 'number') {\n if (tokenId >= 0) {\n return tokenId & BLOOM_MASK;\n }\n else {\n ngDevMode &&\n assertEqual(tokenId, -1 /* InjectorMarkers.Injector */, 'Expecting to get Special Injector Id');\n return createNodeInjector;\n }\n }\n else {\n return tokenId;\n }\n}\nfunction bloomHasToken(bloomHash, injectorIndex, injectorView) {\n // Create a mask that targets the specific bit associated with the directive we're looking for.\n // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding\n // to bit positions 0 - 31 in a 32 bit integer.\n const mask = 1 << bloomHash;\n // Each bloom bucket in `injectorView` represents `BLOOM_BUCKET_BITS` number of bits of\n // `bloomHash`. Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset\n // that should be used.\n const value = injectorView[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)];\n // If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,\n // this injector is a potential match.\n return !!(value & mask);\n}\n/** Returns true if flags prevent parent injector from being searched for tokens */\nfunction shouldSearchParent(flags, isFirstHostTNode) {\n return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode);\n}\nfunction getNodeInjectorLView(nodeInjector) {\n return nodeInjector._lView;\n}\nfunction getNodeInjectorTNode(nodeInjector) {\n return nodeInjector._tNode;\n}\nclass NodeInjector {\n constructor(_tNode, _lView) {\n this._tNode = _tNode;\n this._lView = _lView;\n }\n get(token, notFoundValue, flags) {\n return getOrCreateInjectable(this._tNode, this._lView, token, convertToBitFlags(flags), notFoundValue);\n }\n}\n/** Creates a `NodeInjector` for the current node. */\nfunction createNodeInjector() {\n return new NodeInjector(getCurrentTNode(), getLView());\n}\n/**\n * @codeGenApi\n */\nfunction ɵɵgetInheritedFactory(type) {\n return noSideEffects(() => {\n const ownConstructor = type.prototype.constructor;\n const ownFactory = ownConstructor[NG_FACTORY_DEF] || getFactoryOf(ownConstructor);\n const objectPrototype = Object.prototype;\n let parent = Object.getPrototypeOf(type.prototype).constructor;\n // Go up the prototype until we hit `Object`.\n while (parent && parent !== objectPrototype) {\n const factory = parent[NG_FACTORY_DEF] || getFactoryOf(parent);\n // If we hit something that has a factory and the factory isn't the same as the type,\n // we've found the inherited factory. Note the check that the factory isn't the type's\n // own factory is redundant in most cases, but if the user has custom decorators on the\n // class, this lookup will start one level down in the prototype chain, causing us to\n // find the own factory first and potentially triggering an infinite loop downstream.\n if (factory && factory !== ownFactory) {\n return factory;\n }\n parent = Object.getPrototypeOf(parent);\n }\n // There is no factory defined. Either this was improper usage of inheritance\n // (no Angular decorator on the superclass) or there is no constructor at all\n // in the inheritance chain. Since the two cases cannot be distinguished, the\n // latter has to be assumed.\n return (t) => new t();\n });\n}\nfunction getFactoryOf(type) {\n if (isForwardRef(type)) {\n return () => {\n const factory = getFactoryOf(resolveForwardRef(type));\n return factory && factory();\n };\n }\n return getFactoryDef(type);\n}\n/**\n * Returns a value from the closest embedded or node injector.\n *\n * @param tNode The Node where the search for the injector should start\n * @param lView The `LView` that contains the `tNode`\n * @param token The token to look for\n * @param flags Injection flags\n * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`\n * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided\n */\nfunction lookupTokenUsingEmbeddedInjector(tNode, lView, token, flags, notFoundValue) {\n let currentTNode = tNode;\n let currentLView = lView;\n // When an LView with an embedded view injector is inserted, it'll likely be interlaced with\n // nodes who may have injectors (e.g. node injector -> embedded view injector -> node injector).\n // Since the bloom filters for the node injectors have already been constructed and we don't\n // have a way of extracting the records from an injector, the only way to maintain the correct\n // hierarchy when resolving the value is to walk it node-by-node while attempting to resolve\n // the token at each level.\n while (currentTNode !== null && currentLView !== null &&\n (currentLView[FLAGS] & 2048 /* LViewFlags.HasEmbeddedViewInjector */) &&\n !(currentLView[FLAGS] & 512 /* LViewFlags.IsRoot */)) {\n ngDevMode && assertTNodeForLView(currentTNode, currentLView);\n // Note that this lookup on the node injector is using the `Self` flag, because\n // we don't want the node injector to look at any parent injectors since we\n // may hit the embedded view injector first.\n const nodeInjectorValue = lookupTokenUsingNodeInjector(currentTNode, currentLView, token, flags | InjectFlags.Self, NOT_FOUND);\n if (nodeInjectorValue !== NOT_FOUND) {\n return nodeInjectorValue;\n }\n // Has an explicit type due to a TS bug: https://github.com/microsoft/TypeScript/issues/33191\n let parentTNode = currentTNode.parent;\n // `TNode.parent` includes the parent within the current view only. If it doesn't exist,\n // it means that we've hit the view boundary and we need to go up to the next view.\n if (!parentTNode) {\n // Before we go to the next LView, check if the token exists on the current embedded injector.\n const embeddedViewInjector = currentLView[EMBEDDED_VIEW_INJECTOR];\n if (embeddedViewInjector) {\n const embeddedViewInjectorValue = embeddedViewInjector.get(token, NOT_FOUND, flags);\n if (embeddedViewInjectorValue !== NOT_FOUND) {\n return embeddedViewInjectorValue;\n }\n }\n // Otherwise keep going up the tree.\n parentTNode = getTNodeFromLView(currentLView);\n currentLView = currentLView[DECLARATION_VIEW];\n }\n currentTNode = parentTNode;\n }\n return notFoundValue;\n}\n/** Gets the TNode associated with an LView inside of the declaration view. */\nfunction getTNodeFromLView(lView) {\n const tView = lView[TVIEW];\n const tViewType = tView.type;\n // The parent pointer differs based on `TView.type`.\n if (tViewType === 2 /* TViewType.Embedded */) {\n ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');\n return tView.declTNode;\n }\n else if (tViewType === 1 /* TViewType.Component */) {\n // Components don't have `TView.declTNode` because each instance of component could be\n // inserted in different location, hence `TView.declTNode` is meaningless.\n return lView[T_HOST];\n }\n return null;\n}\n\n/**\n * Facade for the attribute injection from DI.\n *\n * @codeGenApi\n */\nfunction ɵɵinjectAttribute(attrNameToInject) {\n return injectAttributeImpl(getCurrentTNode(), attrNameToInject);\n}\n\nconst ANNOTATIONS = '__annotations__';\nconst PARAMETERS = '__parameters__';\nconst PROP_METADATA = '__prop__metadata__';\n/**\n * @suppress {globalThis}\n */\nfunction makeDecorator(name, props, parentClass, additionalProcessing, typeFn) {\n return noSideEffects(() => {\n const metaCtor = makeMetadataCtor(props);\n function DecoratorFactory(...args) {\n if (this instanceof DecoratorFactory) {\n metaCtor.call(this, ...args);\n return this;\n }\n const annotationInstance = new DecoratorFactory(...args);\n return function TypeDecorator(cls) {\n if (typeFn)\n typeFn(cls, ...args);\n // Use of Object.defineProperty is important since it creates non-enumerable property which\n // prevents the property is copied during subclassing.\n const annotations = cls.hasOwnProperty(ANNOTATIONS) ?\n cls[ANNOTATIONS] :\n Object.defineProperty(cls, ANNOTATIONS, { value: [] })[ANNOTATIONS];\n annotations.push(annotationInstance);\n if (additionalProcessing)\n additionalProcessing(cls);\n return cls;\n };\n }\n if (parentClass) {\n DecoratorFactory.prototype = Object.create(parentClass.prototype);\n }\n DecoratorFactory.prototype.ngMetadataName = name;\n DecoratorFactory.annotationCls = DecoratorFactory;\n return DecoratorFactory;\n });\n}\nfunction makeMetadataCtor(props) {\n return function ctor(...args) {\n if (props) {\n const values = props(...args);\n for (const propName in values) {\n this[propName] = values[propName];\n }\n }\n };\n}\nfunction makeParamDecorator(name, props, parentClass) {\n return noSideEffects(() => {\n const metaCtor = makeMetadataCtor(props);\n function ParamDecoratorFactory(...args) {\n if (this instanceof ParamDecoratorFactory) {\n metaCtor.apply(this, args);\n return this;\n }\n const annotationInstance = new ParamDecoratorFactory(...args);\n ParamDecorator.annotation = annotationInstance;\n return ParamDecorator;\n function ParamDecorator(cls, unusedKey, index) {\n // Use of Object.defineProperty is important since it creates non-enumerable property which\n // prevents the property is copied during subclassing.\n const parameters = cls.hasOwnProperty(PARAMETERS) ?\n cls[PARAMETERS] :\n Object.defineProperty(cls, PARAMETERS, { value: [] })[PARAMETERS];\n // there might be gaps if some in between parameters do not have annotations.\n // we pad with nulls.\n while (parameters.length <= index) {\n parameters.push(null);\n }\n (parameters[index] = parameters[index] || []).push(annotationInstance);\n return cls;\n }\n }\n if (parentClass) {\n ParamDecoratorFactory.prototype = Object.create(parentClass.prototype);\n }\n ParamDecoratorFactory.prototype.ngMetadataName = name;\n ParamDecoratorFactory.annotationCls = ParamDecoratorFactory;\n return ParamDecoratorFactory;\n });\n}\nfunction makePropDecorator(name, props, parentClass, additionalProcessing) {\n return noSideEffects(() => {\n const metaCtor = makeMetadataCtor(props);\n function PropDecoratorFactory(...args) {\n if (this instanceof PropDecoratorFactory) {\n metaCtor.apply(this, args);\n return this;\n }\n const decoratorInstance = new PropDecoratorFactory(...args);\n function PropDecorator(target, name) {\n // target is undefined with standard decorators. This case is not supported and will throw\n // if this decorator is used in JIT mode with standard decorators.\n if (target === undefined) {\n throw new Error('Standard Angular field decorators are not supported in JIT mode.');\n }\n const constructor = target.constructor;\n // Use of Object.defineProperty is important because it creates a non-enumerable property\n // which prevents the property from being copied during subclassing.\n const meta = constructor.hasOwnProperty(PROP_METADATA) ?\n constructor[PROP_METADATA] :\n Object.defineProperty(constructor, PROP_METADATA, { value: {} })[PROP_METADATA];\n meta[name] = meta.hasOwnProperty(name) && meta[name] || [];\n meta[name].unshift(decoratorInstance);\n if (additionalProcessing)\n additionalProcessing(target, name, ...args);\n }\n return PropDecorator;\n }\n if (parentClass) {\n PropDecoratorFactory.prototype = Object.create(parentClass.prototype);\n }\n PropDecoratorFactory.prototype.ngMetadataName = name;\n PropDecoratorFactory.annotationCls = PropDecoratorFactory;\n return PropDecoratorFactory;\n });\n}\n\n/**\n * Attribute decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst Attribute = makeParamDecorator('Attribute', (attributeName) => ({ attributeName, __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName) }));\n\n// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not\n// explicitly set.\nconst emitDistinctChangesOnlyDefaultValue = true;\n/**\n * Base class for query metadata.\n *\n * @see {@link ContentChildren}\n * @see {@link ContentChild}\n * @see {@link ViewChildren}\n * @see {@link ViewChild}\n *\n * @publicApi\n */\nclass Query {\n}\n/**\n * ContentChildren decorator and metadata.\n *\n *\n * @Annotation\n * @publicApi\n */\nconst ContentChildren = makePropDecorator('ContentChildren', (selector, data = {}) => ({\n selector,\n first: false,\n isViewQuery: false,\n descendants: false,\n emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue,\n ...data\n}), Query);\n/**\n * ContentChild decorator and metadata.\n *\n *\n * @Annotation\n *\n * @publicApi\n */\nconst ContentChild = makePropDecorator('ContentChild', (selector, data = {}) => ({ selector, first: true, isViewQuery: false, descendants: true, ...data }), Query);\n/**\n * ViewChildren decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst ViewChildren = makePropDecorator('ViewChildren', (selector, data = {}) => ({\n selector,\n first: false,\n isViewQuery: true,\n descendants: true,\n emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue,\n ...data\n}), Query);\n/**\n * ViewChild decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst ViewChild = makePropDecorator('ViewChild', (selector, data) => ({ selector, first: true, isViewQuery: true, descendants: true, ...data }), Query);\n\nvar FactoryTarget;\n(function (FactoryTarget) {\n FactoryTarget[FactoryTarget[\"Directive\"] = 0] = \"Directive\";\n FactoryTarget[FactoryTarget[\"Component\"] = 1] = \"Component\";\n FactoryTarget[FactoryTarget[\"Injectable\"] = 2] = \"Injectable\";\n FactoryTarget[FactoryTarget[\"Pipe\"] = 3] = \"Pipe\";\n FactoryTarget[FactoryTarget[\"NgModule\"] = 4] = \"NgModule\";\n})(FactoryTarget || (FactoryTarget = {}));\nvar R3TemplateDependencyKind;\n(function (R3TemplateDependencyKind) {\n R3TemplateDependencyKind[R3TemplateDependencyKind[\"Directive\"] = 0] = \"Directive\";\n R3TemplateDependencyKind[R3TemplateDependencyKind[\"Pipe\"] = 1] = \"Pipe\";\n R3TemplateDependencyKind[R3TemplateDependencyKind[\"NgModule\"] = 2] = \"NgModule\";\n})(R3TemplateDependencyKind || (R3TemplateDependencyKind = {}));\nvar ViewEncapsulation;\n(function (ViewEncapsulation) {\n ViewEncapsulation[ViewEncapsulation[\"Emulated\"] = 0] = \"Emulated\";\n // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.\n ViewEncapsulation[ViewEncapsulation[\"None\"] = 2] = \"None\";\n ViewEncapsulation[ViewEncapsulation[\"ShadowDom\"] = 3] = \"ShadowDom\";\n})(ViewEncapsulation || (ViewEncapsulation = {}));\n\nfunction getCompilerFacade(request) {\n const globalNg = _global['ng'];\n if (globalNg && globalNg.ɵcompilerFacade) {\n return globalNg.ɵcompilerFacade;\n }\n if (typeof ngDevMode === 'undefined' || ngDevMode) {\n // Log the type as an error so that a developer can easily navigate to the type from the\n // console.\n console.error(`JIT compilation failed for ${request.kind}`, request.type);\n let message = `The ${request.kind} '${request\n .type.name}' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available.\\n\\n`;\n if (request.usage === 1 /* JitCompilerUsage.PartialDeclaration */) {\n message += `The ${request.kind} is part of a library that has been partially compiled.\\n`;\n message +=\n `However, the Angular Linker has not processed the library such that JIT compilation is used as fallback.\\n`;\n message += '\\n';\n message +=\n `Ideally, the library is processed using the Angular Linker to become fully AOT compiled.\\n`;\n }\n else {\n message +=\n `JIT compilation is discouraged for production use-cases! Consider using AOT mode instead.\\n`;\n }\n message +=\n `Alternatively, the JIT compiler should be loaded by bootstrapping using '@angular/platform-browser-dynamic' or '@angular/platform-server',\\n`;\n message +=\n `or manually provide the compiler with 'import \"@angular/compiler\";' before bootstrapping.`;\n throw new Error(message);\n }\n else {\n throw new Error('JIT compiler unavailable');\n }\n}\n\n/**\n * @description\n *\n * Represents a type that a Component or other object is instances of.\n *\n * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is represented by\n * the `MyCustomComponent` constructor function.\n *\n * @publicApi\n */\nconst Type = Function;\nfunction isType(v) {\n return typeof v === 'function';\n}\n\n/**\n * Determines if the contents of two arrays is identical\n *\n * @param a first array\n * @param b second array\n * @param identityAccessor Optional function for extracting stable object identity from a value in\n * the array.\n */\nfunction arrayEquals(a, b, identityAccessor) {\n if (a.length !== b.length)\n return false;\n for (let i = 0; i < a.length; i++) {\n let valueA = a[i];\n let valueB = b[i];\n if (identityAccessor) {\n valueA = identityAccessor(valueA);\n valueB = identityAccessor(valueB);\n }\n if (valueB !== valueA) {\n return false;\n }\n }\n return true;\n}\n/**\n * Flattens an array.\n */\nfunction flatten(list) {\n return list.flat(Number.POSITIVE_INFINITY);\n}\nfunction deepForEach(input, fn) {\n input.forEach(value => Array.isArray(value) ? deepForEach(value, fn) : fn(value));\n}\nfunction addToArray(arr, index, value) {\n // perf: array.push is faster than array.splice!\n if (index >= arr.length) {\n arr.push(value);\n }\n else {\n arr.splice(index, 0, value);\n }\n}\nfunction removeFromArray(arr, index) {\n // perf: array.pop is faster than array.splice!\n if (index >= arr.length - 1) {\n return arr.pop();\n }\n else {\n return arr.splice(index, 1)[0];\n }\n}\nfunction newArray(size, value) {\n const list = [];\n for (let i = 0; i < size; i++) {\n list.push(value);\n }\n return list;\n}\n/**\n * Remove item from array (Same as `Array.splice()` but faster.)\n *\n * `Array.splice()` is not as fast because it has to allocate an array for the elements which were\n * removed. This causes memory pressure and slows down code when most of the time we don't\n * care about the deleted items array.\n *\n * https://jsperf.com/fast-array-splice (About 20x faster)\n *\n * @param array Array to splice\n * @param index Index of element in array to remove.\n * @param count Number of items to remove.\n */\nfunction arraySplice(array, index, count) {\n const length = array.length - count;\n while (index < length) {\n array[index] = array[index + count];\n index++;\n }\n while (count--) {\n array.pop(); // shrink the array\n }\n}\n/**\n * Same as `Array.splice(index, 0, value)` but faster.\n *\n * `Array.splice()` is not fast because it has to allocate an array for the elements which were\n * removed. This causes memory pressure and slows down code when most of the time we don't\n * care about the deleted items array.\n *\n * @param array Array to splice.\n * @param index Index in array where the `value` should be added.\n * @param value Value to add to array.\n */\nfunction arrayInsert(array, index, value) {\n ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\\'t insert past array end.');\n let end = array.length;\n while (end > index) {\n const previousEnd = end - 1;\n array[end] = array[previousEnd];\n end = previousEnd;\n }\n array[index] = value;\n}\n/**\n * Same as `Array.splice2(index, 0, value1, value2)` but faster.\n *\n * `Array.splice()` is not fast because it has to allocate an array for the elements which were\n * removed. This causes memory pressure and slows down code when most of the time we don't\n * care about the deleted items array.\n *\n * @param array Array to splice.\n * @param index Index in array where the `value` should be added.\n * @param value1 Value to add to array.\n * @param value2 Value to add to array.\n */\nfunction arrayInsert2(array, index, value1, value2) {\n ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\\'t insert past array end.');\n let end = array.length;\n if (end == index) {\n // inserting at the end.\n array.push(value1, value2);\n }\n else if (end === 1) {\n // corner case when we have less items in array than we have items to insert.\n array.push(value2, array[0]);\n array[0] = value1;\n }\n else {\n end--;\n array.push(array[end - 1], array[end]);\n while (end > index) {\n const previousEnd = end - 2;\n array[end] = array[previousEnd];\n end--;\n }\n array[index] = value1;\n array[index + 1] = value2;\n }\n}\n/**\n * Get an index of an `value` in a sorted `array`.\n *\n * NOTE:\n * - This uses binary search algorithm for fast removals.\n *\n * @param array A sorted array to binary search.\n * @param value The value to look for.\n * @returns index of the value.\n * - positive index if value found.\n * - negative index if value not found. (`~index` to get the value where it should have been\n * located)\n */\nfunction arrayIndexOfSorted(array, value) {\n return _arrayIndexOfSorted(array, value, 0);\n}\n/**\n * Set a `value` for a `key`.\n *\n * @param keyValueArray to modify.\n * @param key The key to locate or create.\n * @param value The value to set for a `key`.\n * @returns index (always even) of where the value vas set.\n */\nfunction keyValueArraySet(keyValueArray, key, value) {\n let index = keyValueArrayIndexOf(keyValueArray, key);\n if (index >= 0) {\n // if we found it set it.\n keyValueArray[index | 1] = value;\n }\n else {\n index = ~index;\n arrayInsert2(keyValueArray, index, key, value);\n }\n return index;\n}\n/**\n * Retrieve a `value` for a `key` (on `undefined` if not found.)\n *\n * @param keyValueArray to search.\n * @param key The key to locate.\n * @return The `value` stored at the `key` location or `undefined if not found.\n */\nfunction keyValueArrayGet(keyValueArray, key) {\n const index = keyValueArrayIndexOf(keyValueArray, key);\n if (index >= 0) {\n // if we found it retrieve it.\n return keyValueArray[index | 1];\n }\n return undefined;\n}\n/**\n * Retrieve a `key` index value in the array or `-1` if not found.\n *\n * @param keyValueArray to search.\n * @param key The key to locate.\n * @returns index of where the key is (or should have been.)\n * - positive (even) index if key found.\n * - negative index if key not found. (`~index` (even) to get the index where it should have\n * been inserted.)\n */\nfunction keyValueArrayIndexOf(keyValueArray, key) {\n return _arrayIndexOfSorted(keyValueArray, key, 1);\n}\n/**\n * Delete a `key` (and `value`) from the `KeyValueArray`.\n *\n * @param keyValueArray to modify.\n * @param key The key to locate or delete (if exist).\n * @returns index of where the key was (or should have been.)\n * - positive (even) index if key found and deleted.\n * - negative index if key not found. (`~index` (even) to get the index where it should have\n * been.)\n */\nfunction keyValueArrayDelete(keyValueArray, key) {\n const index = keyValueArrayIndexOf(keyValueArray, key);\n if (index >= 0) {\n // if we found it remove it.\n arraySplice(keyValueArray, index, 2);\n }\n return index;\n}\n/**\n * INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`.\n *\n * NOTE:\n * - This uses binary search algorithm for fast removals.\n *\n * @param array A sorted array to binary search.\n * @param value The value to look for.\n * @param shift grouping shift.\n * - `0` means look at every location\n * - `1` means only look at every other (even) location (the odd locations are to be ignored as\n * they are values.)\n * @returns index of the value.\n * - positive index if value found.\n * - negative index if value not found. (`~index` to get the value where it should have been\n * inserted)\n */\nfunction _arrayIndexOfSorted(array, value, shift) {\n ngDevMode && assertEqual(Array.isArray(array), true, 'Expecting an array');\n let start = 0;\n let end = array.length >> shift;\n while (end !== start) {\n const middle = start + ((end - start) >> 1); // find the middle.\n const current = array[middle << shift];\n if (value === current) {\n return (middle << shift);\n }\n else if (current > value) {\n end = middle;\n }\n else {\n start = middle + 1; // We already searched middle so make it non-inclusive by adding 1\n }\n }\n return ~(end << shift);\n}\n\n/*\n * #########################\n * Attention: These Regular expressions have to hold even if the code is minified!\n * ##########################\n */\n/**\n * Regular expression that detects pass-through constructors for ES5 output. This Regex\n * intends to capture the common delegation pattern emitted by TypeScript and Babel. Also\n * it intends to capture the pattern where existing constructors have been downleveled from\n * ES2015 to ES5 using TypeScript w/ downlevel iteration. e.g.\n *\n * ```\n * function MyClass() {\n * var _this = _super.apply(this, arguments) || this;\n * ```\n *\n * downleveled to ES5 with `downlevelIteration` for TypeScript < 4.2:\n * ```\n * function MyClass() {\n * var _this = _super.apply(this, __spread(arguments)) || this;\n * ```\n *\n * or downleveled to ES5 with `downlevelIteration` for TypeScript >= 4.2:\n * ```\n * function MyClass() {\n * var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;\n * ```\n *\n * More details can be found in: https://github.com/angular/angular/issues/38453.\n */\nconst ES5_DELEGATE_CTOR = /^function\\s+\\S+\\(\\)\\s*{[\\s\\S]+\\.apply\\(this,\\s*(arguments|(?:[^()]+\\(\\[\\],)?[^()]+\\(arguments\\).*)\\)/;\n/** Regular expression that detects ES2015 classes which extend from other classes. */\nconst ES2015_INHERITED_CLASS = /^class\\s+[A-Za-z\\d$_]*\\s*extends\\s+[^{]+{/;\n/**\n * Regular expression that detects ES2015 classes which extend from other classes and\n * have an explicit constructor defined.\n */\nconst ES2015_INHERITED_CLASS_WITH_CTOR = /^class\\s+[A-Za-z\\d$_]*\\s*extends\\s+[^{]+{[\\s\\S]*constructor\\s*\\(/;\n/**\n * Regular expression that detects ES2015 classes which extend from other classes\n * and inherit a constructor.\n */\nconst ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR = /^class\\s+[A-Za-z\\d$_]*\\s*extends\\s+[^{]+{[\\s\\S]*constructor\\s*\\(\\)\\s*{[^}]*super\\(\\.\\.\\.arguments\\)/;\n/**\n * Determine whether a stringified type is a class which delegates its constructor\n * to its parent.\n *\n * This is not trivial since compiled code can actually contain a constructor function\n * even if the original source code did not. For instance, when the child class contains\n * an initialized instance property.\n */\nfunction isDelegateCtor(typeStr) {\n return ES5_DELEGATE_CTOR.test(typeStr) ||\n ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR.test(typeStr) ||\n (ES2015_INHERITED_CLASS.test(typeStr) && !ES2015_INHERITED_CLASS_WITH_CTOR.test(typeStr));\n}\nclass ReflectionCapabilities {\n constructor(reflect) {\n this._reflect = reflect || _global['Reflect'];\n }\n factory(t) {\n return (...args) => new t(...args);\n }\n /** @internal */\n _zipTypesAndAnnotations(paramTypes, paramAnnotations) {\n let result;\n if (typeof paramTypes === 'undefined') {\n result = newArray(paramAnnotations.length);\n }\n else {\n result = newArray(paramTypes.length);\n }\n for (let i = 0; i < result.length; i++) {\n // TS outputs Object for parameters without types, while Traceur omits\n // the annotations. For now we preserve the Traceur behavior to aid\n // migration, but this can be revisited.\n if (typeof paramTypes === 'undefined') {\n result[i] = [];\n }\n else if (paramTypes[i] && paramTypes[i] != Object) {\n result[i] = [paramTypes[i]];\n }\n else {\n result[i] = [];\n }\n if (paramAnnotations && paramAnnotations[i] != null) {\n result[i] = result[i].concat(paramAnnotations[i]);\n }\n }\n return result;\n }\n _ownParameters(type, parentCtor) {\n const typeStr = type.toString();\n // If we have no decorators, we only have function.length as metadata.\n // In that case, to detect whether a child class declared an own constructor or not,\n // we need to look inside of that constructor to check whether it is\n // just calling the parent.\n // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439\n // that sets 'design:paramtypes' to []\n // if a class inherits from another class but has no ctor declared itself.\n if (isDelegateCtor(typeStr)) {\n return null;\n }\n // Prefer the direct API.\n if (type.parameters && type.parameters !== parentCtor.parameters) {\n return type.parameters;\n }\n // API of tsickle for lowering decorators to properties on the class.\n const tsickleCtorParams = type.ctorParameters;\n if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) {\n // Newer tsickle uses a function closure\n // Retain the non-function case for compatibility with older tsickle\n const ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams;\n const paramTypes = ctorParameters.map((ctorParam) => ctorParam && ctorParam.type);\n const paramAnnotations = ctorParameters.map((ctorParam) => ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators));\n return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);\n }\n // API for metadata created by invoking the decorators.\n const paramAnnotations = type.hasOwnProperty(PARAMETERS) && type[PARAMETERS];\n const paramTypes = this._reflect && this._reflect.getOwnMetadata &&\n this._reflect.getOwnMetadata('design:paramtypes', type);\n if (paramTypes || paramAnnotations) {\n return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);\n }\n // If a class has no decorators, at least create metadata\n // based on function.length.\n // Note: We know that this is a real constructor as we checked\n // the content of the constructor above.\n return newArray(type.length);\n }\n parameters(type) {\n // Note: only report metadata if we have at least one class decorator\n // to stay in sync with the static reflector.\n if (!isType(type)) {\n return [];\n }\n const parentCtor = getParentCtor(type);\n let parameters = this._ownParameters(type, parentCtor);\n if (!parameters && parentCtor !== Object) {\n parameters = this.parameters(parentCtor);\n }\n return parameters || [];\n }\n _ownAnnotations(typeOrFunc, parentCtor) {\n // Prefer the direct API.\n if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) {\n let annotations = typeOrFunc.annotations;\n if (typeof annotations === 'function' && annotations.annotations) {\n annotations = annotations.annotations;\n }\n return annotations;\n }\n // API of tsickle for lowering decorators to properties on the class.\n if (typeOrFunc.decorators && typeOrFunc.decorators !== parentCtor.decorators) {\n return convertTsickleDecoratorIntoMetadata(typeOrFunc.decorators);\n }\n // API for metadata created by invoking the decorators.\n if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {\n return typeOrFunc[ANNOTATIONS];\n }\n return null;\n }\n annotations(typeOrFunc) {\n if (!isType(typeOrFunc)) {\n return [];\n }\n const parentCtor = getParentCtor(typeOrFunc);\n const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];\n const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];\n return parentAnnotations.concat(ownAnnotations);\n }\n _ownPropMetadata(typeOrFunc, parentCtor) {\n // Prefer the direct API.\n if (typeOrFunc.propMetadata &&\n typeOrFunc.propMetadata !== parentCtor.propMetadata) {\n let propMetadata = typeOrFunc.propMetadata;\n if (typeof propMetadata === 'function' && propMetadata.propMetadata) {\n propMetadata = propMetadata.propMetadata;\n }\n return propMetadata;\n }\n // API of tsickle for lowering decorators to properties on the class.\n if (typeOrFunc.propDecorators &&\n typeOrFunc.propDecorators !== parentCtor.propDecorators) {\n const propDecorators = typeOrFunc.propDecorators;\n const propMetadata = {};\n Object.keys(propDecorators).forEach(prop => {\n propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]);\n });\n return propMetadata;\n }\n // API for metadata created by invoking the decorators.\n if (typeOrFunc.hasOwnProperty(PROP_METADATA)) {\n return typeOrFunc[PROP_METADATA];\n }\n return null;\n }\n propMetadata(typeOrFunc) {\n if (!isType(typeOrFunc)) {\n return {};\n }\n const parentCtor = getParentCtor(typeOrFunc);\n const propMetadata = {};\n if (parentCtor !== Object) {\n const parentPropMetadata = this.propMetadata(parentCtor);\n Object.keys(parentPropMetadata).forEach((propName) => {\n propMetadata[propName] = parentPropMetadata[propName];\n });\n }\n const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor);\n if (ownPropMetadata) {\n Object.keys(ownPropMetadata).forEach((propName) => {\n const decorators = [];\n if (propMetadata.hasOwnProperty(propName)) {\n decorators.push(...propMetadata[propName]);\n }\n decorators.push(...ownPropMetadata[propName]);\n propMetadata[propName] = decorators;\n });\n }\n return propMetadata;\n }\n ownPropMetadata(typeOrFunc) {\n if (!isType(typeOrFunc)) {\n return {};\n }\n return this._ownPropMetadata(typeOrFunc, getParentCtor(typeOrFunc)) || {};\n }\n hasLifecycleHook(type, lcProperty) {\n return type instanceof Type && lcProperty in type.prototype;\n }\n}\nfunction convertTsickleDecoratorIntoMetadata(decoratorInvocations) {\n if (!decoratorInvocations) {\n return [];\n }\n return decoratorInvocations.map(decoratorInvocation => {\n const decoratorType = decoratorInvocation.type;\n const annotationCls = decoratorType.annotationCls;\n const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];\n return new annotationCls(...annotationArgs);\n });\n}\nfunction getParentCtor(ctor) {\n const parentProto = ctor.prototype ? Object.getPrototypeOf(ctor.prototype) : null;\n const parentCtor = parentProto ? parentProto.constructor : null;\n // Note: We always use `Object` as the null value\n // to simplify checking later on.\n return parentCtor || Object;\n}\n\n/**\n * Inject decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst Inject = attachInjectFlag(\n// Disable tslint because `DecoratorFlags` is a const enum which gets inlined.\n// tslint:disable-next-line: no-toplevel-property-access\nmakeParamDecorator('Inject', (token) => ({ token })), -1 /* DecoratorFlags.Inject */);\n/**\n * Optional decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst Optional = \n// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n// tslint:disable-next-line: no-toplevel-property-access\nattachInjectFlag(makeParamDecorator('Optional'), 8 /* InternalInjectFlags.Optional */);\n/**\n * Self decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst Self = \n// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n// tslint:disable-next-line: no-toplevel-property-access\nattachInjectFlag(makeParamDecorator('Self'), 2 /* InternalInjectFlags.Self */);\n/**\n * `SkipSelf` decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst SkipSelf = \n// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n// tslint:disable-next-line: no-toplevel-property-access\nattachInjectFlag(makeParamDecorator('SkipSelf'), 4 /* InternalInjectFlags.SkipSelf */);\n/**\n * Host decorator and metadata.\n *\n * @Annotation\n * @publicApi\n */\nconst Host = \n// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.\n// tslint:disable-next-line: no-toplevel-property-access\nattachInjectFlag(makeParamDecorator('Host'), 1 /* InternalInjectFlags.Host */);\n\nlet _reflect = null;\nfunction getReflect() {\n return (_reflect = _reflect || new ReflectionCapabilities());\n}\nfunction reflectDependencies(type) {\n return convertDependencies(getReflect().parameters(type));\n}\nfunction convertDependencies(deps) {\n return deps.map(dep => reflectDependency(dep));\n}\nfunction reflectDependency(dep) {\n const meta = {\n token: null,\n attribute: null,\n host: false,\n optional: false,\n self: false,\n skipSelf: false,\n };\n if (Array.isArray(dep) && dep.length > 0) {\n for (let j = 0; j < dep.length; j++) {\n const param = dep[j];\n if (param === undefined) {\n // param may be undefined if type of dep is not set by ngtsc\n continue;\n }\n const proto = Object.getPrototypeOf(param);\n if (param instanceof Optional || proto.ngMetadataName === 'Optional') {\n meta.optional = true;\n }\n else if (param instanceof SkipSelf || proto.ngMetadataName === 'SkipSelf') {\n meta.skipSelf = true;\n }\n else if (param instanceof Self || proto.ngMetadataName === 'Self') {\n meta.self = true;\n }\n else if (param instanceof Host || proto.ngMetadataName === 'Host') {\n meta.host = true;\n }\n else if (param instanceof Inject) {\n meta.token = param.token;\n }\n else if (param instanceof Attribute) {\n if (param.attributeName === undefined) {\n throw new RuntimeError(204 /* RuntimeErrorCode.INVALID_INJECTION_TOKEN */, ngDevMode && `Attribute name must be defined.`);\n }\n meta.attribute = param.attributeName;\n }\n else {\n meta.token = param;\n }\n }\n }\n else if (dep === undefined || (Array.isArray(dep) && dep.length === 0)) {\n meta.token = null;\n }\n else {\n meta.token = dep;\n }\n return meta;\n}\n\n/**\n * Used to resolve resource URLs on `@Component` when used with JIT compilation.\n *\n * Example:\n * ```\n * @Component({\n * selector: 'my-comp',\n * templateUrl: 'my-comp.html', // This requires asynchronous resolution\n * })\n * class MyComponent{\n * }\n *\n * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process\n * // and `MyComponent`'s `@Component.templateUrl` needs to be resolved asynchronously.\n *\n * // Calling `resolveComponentResources()` will resolve `@Component.templateUrl` into\n * // `@Component.template`, which allows `renderComponent` to proceed in a synchronous manner.\n *\n * // Use browser's `fetch()` function as the default resource resolution strategy.\n * resolveComponentResources(fetch).then(() => {\n * // After resolution all URLs have been converted into `template` strings.\n * renderComponent(MyComponent);\n * });\n *\n * ```\n *\n * NOTE: In AOT the resolution happens during compilation, and so there should be no need\n * to call this method outside JIT mode.\n *\n * @param resourceResolver a function which is responsible for returning a `Promise` to the\n * contents of the resolved URL. Browser's `fetch()` method is a good default implementation.\n */\nfunction resolveComponentResources(resourceResolver) {\n // Store all promises which are fetching the resources.\n const componentResolved = [];\n // Cache so that we don't fetch the same resource more than once.\n const urlMap = new Map();\n function cachedResourceResolve(url) {\n let promise = urlMap.get(url);\n if (!promise) {\n const resp = resourceResolver(url);\n urlMap.set(url, promise = resp.then(unwrapResponse));\n }\n return promise;\n }\n componentResourceResolutionQueue.forEach((component, type) => {\n const promises = [];\n if (component.templateUrl) {\n promises.push(cachedResourceResolve(component.templateUrl).then((template) => {\n component.template = template;\n }));\n }\n const styleUrls = component.styleUrls;\n const styles = component.styles || (component.styles = []);\n const styleOffset = component.styles.length;\n styleUrls && styleUrls.forEach((styleUrl, index) => {\n styles.push(''); // pre-allocate array.\n promises.push(cachedResourceResolve(styleUrl).then((style) => {\n styles[styleOffset + index] = style;\n styleUrls.splice(styleUrls.indexOf(styleUrl), 1);\n if (styleUrls.length == 0) {\n component.styleUrls = undefined;\n }\n }));\n });\n const fullyResolved = Promise.all(promises).then(() => componentDefResolved(type));\n componentResolved.push(fullyResolved);\n });\n clearResolutionOfComponentResourcesQueue();\n return Promise.all(componentResolved).then(() => undefined);\n}\nlet componentResourceResolutionQueue = new Map();\n// Track when existing ɵcmp for a Type is waiting on resources.\nconst componentDefPendingResolution = new Set();\nfunction maybeQueueResolutionOfComponentResources(type, metadata) {\n if (componentNeedsResolution(metadata)) {\n componentResourceResolutionQueue.set(type, metadata);\n componentDefPendingResolution.add(type);\n }\n}\nfunction isComponentDefPendingResolution(type) {\n return componentDefPendingResolution.has(type);\n}\nfunction componentNeedsResolution(component) {\n return !!((component.templateUrl && !component.hasOwnProperty('template')) ||\n component.styleUrls && component.styleUrls.length);\n}\nfunction clearResolutionOfComponentResourcesQueue() {\n const old = componentResourceResolutionQueue;\n componentResourceResolutionQueue = new Map();\n return old;\n}\nfunction restoreComponentResolutionQueue(queue) {\n componentDefPendingResolution.clear();\n queue.forEach((_, type) => componentDefPendingResolution.add(type));\n componentResourceResolutionQueue = queue;\n}\nfunction isComponentResourceResolutionQueueEmpty() {\n return componentResourceResolutionQueue.size === 0;\n}\nfunction unwrapResponse(response) {\n return typeof response == 'string' ? response : response.text();\n}\nfunction componentDefResolved(type) {\n componentDefPendingResolution.delete(type);\n}\n\n/**\n * Map of module-id to the corresponding NgModule.\n */\nconst modules = new Map();\n/**\n * Whether to check for duplicate NgModule registrations.\n *\n * This can be disabled for testing.\n */\nlet checkForDuplicateNgModules = true;\nfunction assertSameOrNotExisting(id, type, incoming) {\n if (type && type !== incoming && checkForDuplicateNgModules) {\n throw new Error(`Duplicate module registered for ${id} - ${stringify(type)} vs ${stringify(type.name)}`);\n }\n}\n/**\n * Adds the given NgModule type to Angular's NgModule registry.\n *\n * This is generated as a side-effect of NgModule compilation. Note that the `id` is passed in\n * explicitly and not read from the NgModule definition. This is for two reasons: it avoids a\n * megamorphic read, and in JIT there's a chicken-and-egg problem where the NgModule may not be\n * fully resolved when it's registered.\n *\n * @codeGenApi\n */\nfunction registerNgModuleType(ngModuleType, id) {\n const existing = modules.get(id) || null;\n assertSameOrNotExisting(id, existing, ngModuleType);\n modules.set(id, ngModuleType);\n}\nfunction clearModulesForTest() {\n modules.clear();\n}\nfunction getRegisteredNgModuleType(id) {\n return modules.get(id);\n}\n/**\n * Control whether the NgModule registration system enforces that each NgModule type registered has\n * a unique id.\n *\n * This is useful for testing as the NgModule registry cannot be properly reset between tests with\n * Angular's current API.\n */\nfunction setAllowDuplicateNgModuleIdsForTest(allowDuplicates) {\n checkForDuplicateNgModules = !allowDuplicates;\n}\n\n/**\n * Defines a schema that allows an NgModule to contain the following:\n * - Non-Angular elements named with dash case (`-`).\n * - Element properties named with dash case (`-`).\n * Dash case is the naming convention for custom elements.\n *\n * @publicApi\n */\nconst CUSTOM_ELEMENTS_SCHEMA = {\n name: 'custom-elements'\n};\n/**\n * Defines a schema that allows any property on any element.\n *\n * This schema allows you to ignore the errors related to any unknown elements or properties in a\n * template. The usage of this schema is generally discouraged because it prevents useful validation\n * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.\n *\n * @publicApi\n */\nconst NO_ERRORS_SCHEMA = {\n name: 'no-errors-schema'\n};\n\nlet shouldThrowErrorOnUnknownElement = false;\n/**\n * Sets a strict mode for JIT-compiled components to throw an error on unknown elements,\n * instead of just logging the error.\n * (for AOT-compiled ones this check happens at build time).\n */\nfunction ɵsetUnknownElementStrictMode(shouldThrow) {\n shouldThrowErrorOnUnknownElement = shouldThrow;\n}\n/**\n * Gets the current value of the strict mode.\n */\nfunction ɵgetUnknownElementStrictMode() {\n return shouldThrowErrorOnUnknownElement;\n}\nlet shouldThrowErrorOnUnknownProperty = false;\n/**\n * Sets a strict mode for JIT-compiled components to throw an error on unknown properties,\n * instead of just logging the error.\n * (for AOT-compiled ones this check happens at build time).\n */\nfunction ɵsetUnknownPropertyStrictMode(shouldThrow) {\n shouldThrowErrorOnUnknownProperty = shouldThrow;\n}\n/**\n * Gets the current value of the strict mode.\n */\nfunction ɵgetUnknownPropertyStrictMode() {\n return shouldThrowErrorOnUnknownProperty;\n}\n/**\n * Validates that the element is known at runtime and produces\n * an error if it's not the case.\n * This check is relevant for JIT-compiled components (for AOT-compiled\n * ones this check happens at build time).\n *\n * The element is considered known if either:\n * - it's a known HTML element\n * - it's a known custom element\n * - the element matches any directive\n * - the element is allowed by one of the schemas\n *\n * @param element Element to validate\n * @param lView An `LView` that represents a current component that is being rendered\n * @param tagName Name of the tag to check\n * @param schemas Array of schemas\n * @param hasDirectives Boolean indicating that the element matches any directive\n */\nfunction validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) {\n // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT\n // mode where this check happens at compile time. In JIT mode, `schemas` is always present and\n // defined as an array (as an empty array in case `schemas` field is not defined) and we should\n // execute the check below.\n if (schemas === null)\n return;\n // If the element matches any directive, it's considered as valid.\n if (!hasDirectives && tagName !== null) {\n // The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered\n // as a custom element. Note that unknown elements with a dash in their name won't be instances\n // of HTMLUnknownElement in browsers that support web components.\n const isUnknown = \n // Note that we can't check for `typeof HTMLUnknownElement === 'function'` because\n // Domino doesn't expose HTMLUnknownElement globally.\n (typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&\n element instanceof HTMLUnknownElement) ||\n (typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&\n !customElements.get(tagName));\n if (isUnknown && !matchingSchemas(schemas, tagName)) {\n const isHostStandalone = isHostComponentStandalone(lView);\n const templateLocation = getTemplateLocationDetails(lView);\n const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;\n let message = `'${tagName}' is not a known element${templateLocation}:\\n`;\n message += `1. If '${tagName}' is an Angular component, then verify that it is ${isHostStandalone ? 'included in the \\'@Component.imports\\' of this component' :\n 'a part of an @NgModule where this component is declared'}.\\n`;\n if (tagName && tagName.indexOf('-') > -1) {\n message +=\n `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the ${schemas} of this component to suppress this message.`;\n }\n else {\n message +=\n `2. To allow any element add 'NO_ERRORS_SCHEMA' to the ${schemas} of this component.`;\n }\n if (shouldThrowErrorOnUnknownElement) {\n throw new RuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message);\n }\n else {\n console.error(formatRuntimeError(304 /* RuntimeErrorCode.UNKNOWN_ELEMENT */, message));\n }\n }\n }\n}\n/**\n * Validates that the property of the element is known at runtime and returns\n * false if it's not the case.\n * This check is relevant for JIT-compiled components (for AOT-compiled\n * ones this check happens at build time).\n *\n * The property is considered known if either:\n * - it's a known property of the element\n * - the element is allowed by one of the schemas\n * - the property is used for animations\n *\n * @param element Element to validate\n * @param propName Name of the property to check\n * @param tagName Name of the tag hosting the property\n * @param schemas Array of schemas\n */\nfunction isPropertyValid(element, propName, tagName, schemas) {\n // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT\n // mode where this check happens at compile time. In JIT mode, `schemas` is always present and\n // defined as an array (as an empty array in case `schemas` field is not defined) and we should\n // execute the check below.\n if (schemas === null)\n return true;\n // The property is considered valid if the element matches the schema, it exists on the element,\n // or it is synthetic.\n if (matchingSchemas(schemas, tagName) || propName in element || isAnimationProp(propName)) {\n return true;\n }\n // Note: `typeof Node` returns 'function' in most browsers, but is undefined with domino.\n return typeof Node === 'undefined' || Node === null || !(element instanceof Node);\n}\n/**\n * Logs or throws an error that a property is not supported on an element.\n *\n * @param propName Name of the invalid property\n * @param tagName Name of the tag hosting the property\n * @param nodeType Type of the node hosting the property\n * @param lView An `LView` that represents a current component\n */\nfunction handleUnknownPropertyError(propName, tagName, nodeType, lView) {\n // Special-case a situation when a structural directive is applied to\n // an `` element, for example: ``.\n // In this case the compiler generates the `ɵɵtemplate` instruction with\n // the `null` as the tagName. The directive matching logic at runtime relies\n // on this effect (see `isInlineTemplate`), thus using the 'ng-template' as\n // a default value of the `tNode.value` is not feasible at this moment.\n if (!tagName && nodeType === 4 /* TNodeType.Container */) {\n tagName = 'ng-template';\n }\n const isHostStandalone = isHostComponentStandalone(lView);\n const templateLocation = getTemplateLocationDetails(lView);\n let message = `Can't bind to '${propName}' since it isn't a known property of '${tagName}'${templateLocation}.`;\n const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;\n const importLocation = isHostStandalone ?\n 'included in the \\'@Component.imports\\' of this component' :\n 'a part of an @NgModule where this component is declared';\n if (KNOWN_CONTROL_FLOW_DIRECTIVES.has(propName)) {\n // Most likely this is a control flow directive (such as `*ngIf`) used in\n // a template, but the directive or the `CommonModule` is not imported.\n const correspondingImport = KNOWN_CONTROL_FLOW_DIRECTIVES.get(propName);\n message += `\\nIf the '${propName}' is an Angular control flow directive, ` +\n `please make sure that either the '${correspondingImport}' directive or the 'CommonModule' is ${importLocation}.`;\n }\n else {\n // May be an Angular component, which is not imported/declared?\n message += `\\n1. If '${tagName}' is an Angular component and it has the ` +\n `'${propName}' input, then verify that it is ${importLocation}.`;\n // May be a Web Component?\n if (tagName && tagName.indexOf('-') > -1) {\n message += `\\n2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' ` +\n `to the ${schemas} of this component to suppress this message.`;\n message += `\\n3. To allow any property add 'NO_ERRORS_SCHEMA' to ` +\n `the ${schemas} of this component.`;\n }\n else {\n // If it's expected, the error can be suppressed by the `NO_ERRORS_SCHEMA` schema.\n message += `\\n2. To allow any property add 'NO_ERRORS_SCHEMA' to ` +\n `the ${schemas} of this component.`;\n }\n }\n reportUnknownPropertyError(message);\n}\nfunction reportUnknownPropertyError(message) {\n if (shouldThrowErrorOnUnknownProperty) {\n throw new RuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message);\n }\n else {\n console.error(formatRuntimeError(303 /* RuntimeErrorCode.UNKNOWN_BINDING */, message));\n }\n}\n/**\n * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)\n * and must **not** be used in production bundles. The function makes megamorphic reads, which might\n * be too slow for production mode and also it relies on the constructor function being available.\n *\n * Gets a reference to the host component def (where a current component is declared).\n *\n * @param lView An `LView` that represents a current component that is being rendered.\n */\nfunction getDeclarationComponentDef(lView) {\n !ngDevMode && throwError('Must never be called in production mode');\n const declarationLView = lView[DECLARATION_COMPONENT_VIEW];\n const context = declarationLView[CONTEXT];\n // Unable to obtain a context.\n if (!context)\n return null;\n return context.constructor ? getComponentDef(context.constructor) : null;\n}\n/**\n * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)\n * and must **not** be used in production bundles. The function makes megamorphic reads, which might\n * be too slow for production mode.\n *\n * Checks if the current component is declared inside of a standalone component template.\n *\n * @param lView An `LView` that represents a current component that is being rendered.\n */\nfunction isHostComponentStandalone(lView) {\n !ngDevMode && throwError('Must never be called in production mode');\n const componentDef = getDeclarationComponentDef(lView);\n // Treat host component as non-standalone if we can't obtain the def.\n return !!componentDef?.standalone;\n}\n/**\n * WARNING: this is a **dev-mode only** function (thus should always be guarded by the `ngDevMode`)\n * and must **not** be used in production bundles. The function makes megamorphic reads, which might\n * be too slow for production mode.\n *\n * Constructs a string describing the location of the host component template. The function is used\n * in dev mode to produce error messages.\n *\n * @param lView An `LView` that represents a current component that is being rendered.\n */\nfunction getTemplateLocationDetails(lView) {\n !ngDevMode && throwError('Must never be called in production mode');\n const hostComponentDef = getDeclarationComponentDef(lView);\n const componentClassName = hostComponentDef?.type?.name;\n return componentClassName ? ` (used in the '${componentClassName}' component template)` : '';\n}\n/**\n * The set of known control flow directives and their corresponding imports.\n * We use this set to produce a more precises error message with a note\n * that the `CommonModule` should also be included.\n */\nconst KNOWN_CONTROL_FLOW_DIRECTIVES = new Map([\n ['ngIf', 'NgIf'], ['ngFor', 'NgFor'], ['ngSwitchCase', 'NgSwitchCase'],\n ['ngSwitchDefault', 'NgSwitchDefault']\n]);\n/**\n * Returns true if the tag name is allowed by specified schemas.\n * @param schemas Array of schemas\n * @param tagName Name of the tag\n */\nfunction matchingSchemas(schemas, tagName) {\n if (schemas !== null) {\n for (let i = 0; i < schemas.length; i++) {\n const schema = schemas[i];\n if (schema === NO_ERRORS_SCHEMA ||\n schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * The name of an attribute that can be added to the hydration boundary node\n * (component host node) to disable hydration for the content within that boundary.\n */\nconst SKIP_HYDRATION_ATTR_NAME = 'ngSkipHydration';\n/**\n * Helper function to check if a given TNode has the 'ngSkipHydration' attribute.\n */\nfunction hasSkipHydrationAttrOnTNode(tNode) {\n const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = SKIP_HYDRATION_ATTR_NAME.toLowerCase();\n const attrs = tNode.mergedAttrs;\n if (attrs === null)\n return false;\n // only ever look at the attribute name and skip the values\n for (let i = 0; i < attrs.length; i += 2) {\n const value = attrs[i];\n // This is a marker, which means that the static attributes section is over,\n // so we can exit early.\n if (typeof value === 'number')\n return false;\n if (typeof value === 'string' && value.toLowerCase() === SKIP_HYDRATION_ATTR_NAME_LOWER_CASE) {\n return true;\n }\n }\n return false;\n}\n/**\n * Helper function to check if a given RElement has the 'ngSkipHydration' attribute.\n */\nfunction hasSkipHydrationAttrOnRElement(rNode) {\n return rNode.hasAttribute(SKIP_HYDRATION_ATTR_NAME);\n}\n/**\n * Checks whether a TNode has a flag to indicate that it's a part of\n * a skip hydration block.\n */\nfunction hasInSkipHydrationBlockFlag(tNode) {\n return (tNode.flags & 128 /* TNodeFlags.inSkipHydrationBlock */) === 128 /* TNodeFlags.inSkipHydrationBlock */;\n}\n/**\n * Helper function that determines if a given node is within a skip hydration block\n * by navigating up the TNode tree to see if any parent nodes have skip hydration\n * attribute.\n *\n * TODO(akushnir): this function should contain the logic of `hasInSkipHydrationBlockFlag`,\n * there is no need to traverse parent nodes when we have a TNode flag (which would also\n * make this lookup O(1)).\n */\nfunction isInSkipHydrationBlock(tNode) {\n let currentTNode = tNode.parent;\n while (currentTNode) {\n if (hasSkipHydrationAttrOnTNode(currentTNode)) {\n return true;\n }\n currentTNode = currentTNode.parent;\n }\n return false;\n}\n\n/**\n * Flags for renderer-specific style modifiers.\n * @publicApi\n */\nvar RendererStyleFlags2;\n(function (RendererStyleFlags2) {\n // TODO(misko): This needs to be refactored into a separate file so that it can be imported from\n // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails\n // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.\n /**\n * Marks a style as important.\n */\n RendererStyleFlags2[RendererStyleFlags2[\"Important\"] = 1] = \"Important\";\n /**\n * Marks a style as using dash case naming (this-is-dash-case).\n */\n RendererStyleFlags2[RendererStyleFlags2[\"DashCase\"] = 2] = \"DashCase\";\n})(RendererStyleFlags2 || (RendererStyleFlags2 = {}));\n\n/**\n * Disallowed strings in the comment.\n *\n * see: https://html.spec.whatwg.org/multipage/syntax.html#comments\n */\nconst COMMENT_DISALLOWED = /^>|^->||--!>|)/;\nconst COMMENT_DELIMITER_ESCAPED = '\\u200B$1\\u200B';\n/**\n * Escape the content of comment strings so that it can be safely inserted into a comment node.\n *\n * The issue is that HTML does not specify any way to escape comment end text inside the comment.\n * Consider: `\" or\n * \"--!>\" at the end. -->`. Above the `\"-->\"` is meant to be text not an end to the comment. This\n * can be created programmatically through DOM APIs. (`` or `--!>`) the\n * text it will render normally but it will not cause the HTML parser to close/open the comment.\n *\n * @param value text to make safe for comment node by escaping the comment open/close character\n * sequence.\n */\nfunction escapeCommentText(value) {\n return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));\n}\n\n// Keeps track of the currently-active LViews.\nconst TRACKED_LVIEWS = new Map();\n// Used for generating unique IDs for LViews.\nlet uniqueIdCounter = 0;\n/** Gets a unique ID that can be assigned to an LView. */\nfunction getUniqueLViewId() {\n return uniqueIdCounter++;\n}\n/** Starts tracking an LView. */\nfunction registerLView(lView) {\n ngDevMode && assertNumber(lView[ID], 'LView must have an ID in order to be registered');\n TRACKED_LVIEWS.set(lView[ID], lView);\n}\n/** Gets an LView by its unique ID. */\nfunction getLViewById(id) {\n ngDevMode && assertNumber(id, 'ID used for LView lookup must be a number');\n return TRACKED_LVIEWS.get(id) || null;\n}\n/** Stops tracking an LView. */\nfunction unregisterLView(lView) {\n ngDevMode && assertNumber(lView[ID], 'Cannot stop tracking an LView that does not have an ID');\n TRACKED_LVIEWS.delete(lView[ID]);\n}\n\n/**\n * The internal view context which is specific to a given DOM element, directive or\n * component instance. Each value in here (besides the LView and element node details)\n * can be present, null or undefined. If undefined then it implies the value has not been\n * looked up yet, otherwise, if null, then a lookup was executed and nothing was found.\n *\n * Each value will get filled when the respective value is examined within the getContext\n * function. The component, element and each directive instance will share the same instance\n * of the context.\n */\nclass LContext {\n /** Component's parent view data. */\n get lView() {\n return getLViewById(this.lViewId);\n }\n constructor(\n /**\n * ID of the component's parent view data.\n */\n lViewId, \n /**\n * The index instance of the node.\n */\n nodeIndex, \n /**\n * The instance of the DOM node that is attached to the lNode.\n */\n native) {\n this.lViewId = lViewId;\n this.nodeIndex = nodeIndex;\n this.native = native;\n }\n}\n\n/**\n * Returns the matching `LContext` data for a given DOM node, directive or component instance.\n *\n * This function will examine the provided DOM element, component, or directive instance\\'s\n * monkey-patched property to derive the `LContext` data. Once called then the monkey-patched\n * value will be that of the newly created `LContext`.\n *\n * If the monkey-patched value is the `LView` instance then the context value for that\n * target will be created and the monkey-patch reference will be updated. Therefore when this\n * function is called it may mutate the provided element\\'s, component\\'s or any of the associated\n * directive\\'s monkey-patch values.\n *\n * If the monkey-patch value is not detected then the code will walk up the DOM until an element\n * is found which contains a monkey-patch reference. When that occurs then the provided element\n * will be updated with a new context (which is then returned). If the monkey-patch value is not\n * detected for a component/directive instance then it will throw an error (all components and\n * directives should be automatically monkey-patched by ivy).\n *\n * @param target Component, Directive or DOM Node.\n */\nfunction getLContext(target) {\n let mpValue = readPatchedData(target);\n if (mpValue) {\n // only when it's an array is it considered an LView instance\n // ... otherwise it's an already constructed LContext instance\n if (isLView(mpValue)) {\n const lView = mpValue;\n let nodeIndex;\n let component = undefined;\n let directives = undefined;\n if (isComponentInstance(target)) {\n nodeIndex = findViaComponent(lView, target);\n if (nodeIndex == -1) {\n throw new Error('The provided component was not found in the application');\n }\n component = target;\n }\n else if (isDirectiveInstance(target)) {\n nodeIndex = findViaDirective(lView, target);\n if (nodeIndex == -1) {\n throw new Error('The provided directive was not found in the application');\n }\n directives = getDirectivesAtNodeIndex(nodeIndex, lView);\n }\n else {\n nodeIndex = findViaNativeElement(lView, target);\n if (nodeIndex == -1) {\n return null;\n }\n }\n // the goal is not to fill the entire context full of data because the lookups\n // are expensive. Instead, only the target data (the element, component, container, ICU\n // expression or directive details) are filled into the context. If called multiple times\n // with different target values then the missing target data will be filled in.\n const native = unwrapRNode(lView[nodeIndex]);\n const existingCtx = readPatchedData(native);\n const context = (existingCtx && !Array.isArray(existingCtx)) ?\n existingCtx :\n createLContext(lView, nodeIndex, native);\n // only when the component has been discovered then update the monkey-patch\n if (component && context.component === undefined) {\n context.component = component;\n attachPatchData(context.component, context);\n }\n // only when the directives have been discovered then update the monkey-patch\n if (directives && context.directives === undefined) {\n context.directives = directives;\n for (let i = 0; i < directives.length; i++) {\n attachPatchData(directives[i], context);\n }\n }\n attachPatchData(context.native, context);\n mpValue = context;\n }\n }\n else {\n const rElement = target;\n ngDevMode && assertDomNode(rElement);\n // if the context is not found then we need to traverse upwards up the DOM\n // to find the nearest element that has already been monkey patched with data\n let parent = rElement;\n while (parent = parent.parentNode) {\n const parentContext = readPatchedData(parent);\n if (parentContext) {\n const lView = Array.isArray(parentContext) ? parentContext : parentContext.lView;\n // the edge of the app was also reached here through another means\n // (maybe because the DOM was changed manually).\n if (!lView) {\n return null;\n }\n const index = findViaNativeElement(lView, rElement);\n if (index >= 0) {\n const native = unwrapRNode(lView[index]);\n const context = createLContext(lView, index, native);\n attachPatchData(native, context);\n mpValue = context;\n break;\n }\n }\n }\n }\n return mpValue || null;\n}\n/**\n * Creates an empty instance of a `LContext` context\n */\nfunction createLContext(lView, nodeIndex, native) {\n return new LContext(lView[ID], nodeIndex, native);\n}\n/**\n * Takes a component instance and returns the view for that component.\n *\n * @param componentInstance\n * @returns The component's view\n */\nfunction getComponentViewByInstance(componentInstance) {\n let patchedData = readPatchedData(componentInstance);\n let lView;\n if (isLView(patchedData)) {\n const contextLView = patchedData;\n const nodeIndex = findViaComponent(contextLView, componentInstance);\n lView = getComponentLViewByIndex(nodeIndex, contextLView);\n const context = createLContext(contextLView, nodeIndex, lView[HOST]);\n context.component = componentInstance;\n attachPatchData(componentInstance, context);\n attachPatchData(context.native, context);\n }\n else {\n const context = patchedData;\n const contextLView = context.lView;\n ngDevMode && assertLView(contextLView);\n lView = getComponentLViewByIndex(context.nodeIndex, contextLView);\n }\n return lView;\n}\n/**\n * This property will be monkey-patched on elements, components and directives.\n */\nconst MONKEY_PATCH_KEY_NAME = '__ngContext__';\n/**\n * Assigns the given data to the given target (which could be a component,\n * directive or DOM node instance) using monkey-patching.\n */\nfunction attachPatchData(target, data) {\n ngDevMode && assertDefined(target, 'Target expected');\n // Only attach the ID of the view in order to avoid memory leaks (see #41047). We only do this\n // for `LView`, because we have control over when an `LView` is created and destroyed, whereas\n // we can't know when to remove an `LContext`.\n if (isLView(data)) {\n target[MONKEY_PATCH_KEY_NAME] = data[ID];\n registerLView(data);\n }\n else {\n target[MONKEY_PATCH_KEY_NAME] = data;\n }\n}\n/**\n * Returns the monkey-patch value data present on the target (which could be\n * a component, directive or a DOM node).\n */\nfunction readPatchedData(target) {\n ngDevMode && assertDefined(target, 'Target expected');\n const data = target[MONKEY_PATCH_KEY_NAME];\n return (typeof data === 'number') ? getLViewById(data) : data || null;\n}\nfunction readPatchedLView(target) {\n const value = readPatchedData(target);\n if (value) {\n return (isLView(value) ? value : value.lView);\n }\n return null;\n}\nfunction isComponentInstance(instance) {\n return instance && instance.constructor && instance.constructor.ɵcmp;\n}\nfunction isDirectiveInstance(instance) {\n return instance && instance.constructor && instance.constructor.ɵdir;\n}\n/**\n * Locates the element within the given LView and returns the matching index\n */\nfunction findViaNativeElement(lView, target) {\n const tView = lView[TVIEW];\n for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {\n if (unwrapRNode(lView[i]) === target) {\n return i;\n }\n }\n return -1;\n}\n/**\n * Locates the next tNode (child, sibling or parent).\n */\nfunction traverseNextElement(tNode) {\n if (tNode.child) {\n return tNode.child;\n }\n else if (tNode.next) {\n return tNode.next;\n }\n else {\n // Let's take the following template: text
\n // After checking the text node, we need to find the next parent that has a \"next\" TNode,\n // in this case the parent `div`, so that we can find the component.\n while (tNode.parent && !tNode.parent.next) {\n tNode = tNode.parent;\n }\n return tNode.parent && tNode.parent.next;\n }\n}\n/**\n * Locates the component within the given LView and returns the matching index\n */\nfunction findViaComponent(lView, componentInstance) {\n const componentIndices = lView[TVIEW].components;\n if (componentIndices) {\n for (let i = 0; i < componentIndices.length; i++) {\n const elementComponentIndex = componentIndices[i];\n const componentView = getComponentLViewByIndex(elementComponentIndex, lView);\n if (componentView[CONTEXT] === componentInstance) {\n return elementComponentIndex;\n }\n }\n }\n else {\n const rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView);\n const rootComponent = rootComponentView[CONTEXT];\n if (rootComponent === componentInstance) {\n // we are dealing with the root element here therefore we know that the\n // element is the very first element after the HEADER data in the lView\n return HEADER_OFFSET;\n }\n }\n return -1;\n}\n/**\n * Locates the directive within the given LView and returns the matching index\n */\nfunction findViaDirective(lView, directiveInstance) {\n // if a directive is monkey patched then it will (by default)\n // have a reference to the LView of the current view. The\n // element bound to the directive being search lives somewhere\n // in the view data. We loop through the nodes and check their\n // list of directives for the instance.\n let tNode = lView[TVIEW].firstChild;\n while (tNode) {\n const directiveIndexStart = tNode.directiveStart;\n const directiveIndexEnd = tNode.directiveEnd;\n for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {\n if (lView[i] === directiveInstance) {\n return tNode.index;\n }\n }\n tNode = traverseNextElement(tNode);\n }\n return -1;\n}\n/**\n * Returns a list of directives applied to a node at a specific index. The list includes\n * directives matched by selector and any host directives, but it excludes components.\n * Use `getComponentAtNodeIndex` to find the component applied to a node.\n *\n * @param nodeIndex The node index\n * @param lView The target view data\n */\nfunction getDirectivesAtNodeIndex(nodeIndex, lView) {\n const tNode = lView[TVIEW].data[nodeIndex];\n if (tNode.directiveStart === 0)\n return EMPTY_ARRAY;\n const results = [];\n for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) {\n const directiveInstance = lView[i];\n if (!isComponentInstance(directiveInstance)) {\n results.push(directiveInstance);\n }\n }\n return results;\n}\nfunction getComponentAtNodeIndex(nodeIndex, lView) {\n const tNode = lView[TVIEW].data[nodeIndex];\n const { directiveStart, componentOffset } = tNode;\n return componentOffset > -1 ? lView[directiveStart + componentOffset] : null;\n}\n/**\n * Returns a map of local references (local reference name => element or directive instance) that\n * exist on a given element.\n */\nfunction discoverLocalRefs(lView, nodeIndex) {\n const tNode = lView[TVIEW].data[nodeIndex];\n if (tNode && tNode.localNames) {\n const result = {};\n let localIndex = tNode.index + 1;\n for (let i = 0; i < tNode.localNames.length; i += 2) {\n result[tNode.localNames[i]] = lView[localIndex];\n localIndex++;\n }\n return result;\n }\n return null;\n}\n\nlet _icuContainerIterate;\n/**\n * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.\n */\nfunction icuContainerIterate(tIcuContainerNode, lView) {\n return _icuContainerIterate(tIcuContainerNode, lView);\n}\n/**\n * Ensures that `IcuContainerVisitor`'s implementation is present.\n *\n * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the\n * bundler to tree shake ICU logic and only load it if ICU instruction is executed.\n */\nfunction ensureIcuContainerVisitorLoaded(loader) {\n if (_icuContainerIterate === undefined) {\n // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it\n // can be inlined into call-site.\n _icuContainerIterate = loader();\n }\n}\n\n/**\n * Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of\n * that LContainer, which is an LView\n * @param lView the lView whose parent to get\n */\nfunction getLViewParent(lView) {\n ngDevMode && assertLView(lView);\n const parent = lView[PARENT];\n return isLContainer(parent) ? parent[PARENT] : parent;\n}\n/**\n * Retrieve the root view from any component or `LView` by walking the parent `LView` until\n * reaching the root `LView`.\n *\n * @param componentOrLView any component or `LView`\n */\nfunction getRootView(componentOrLView) {\n ngDevMode && assertDefined(componentOrLView, 'component');\n let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView);\n while (lView && !(lView[FLAGS] & 512 /* LViewFlags.IsRoot */)) {\n lView = getLViewParent(lView);\n }\n ngDevMode && assertLView(lView);\n return lView;\n}\n/**\n * Returns the context information associated with the application where the target is situated. It\n * does this by walking the parent views until it gets to the root view, then getting the context\n * off of that.\n *\n * @param viewOrComponent the `LView` or component to get the root context for.\n */\nfunction getRootContext(viewOrComponent) {\n const rootView = getRootView(viewOrComponent);\n ngDevMode &&\n assertDefined(rootView[CONTEXT], 'Root view has no context. Perhaps it is disconnected?');\n return rootView[CONTEXT];\n}\n/**\n * Gets the first `LContainer` in the LView or `null` if none exists.\n */\nfunction getFirstLContainer(lView) {\n return getNearestLContainer(lView[CHILD_HEAD]);\n}\n/**\n * Gets the next `LContainer` that is a sibling of the given container.\n */\nfunction getNextLContainer(container) {\n return getNearestLContainer(container[NEXT]);\n}\nfunction getNearestLContainer(viewOrContainer) {\n while (viewOrContainer !== null && !isLContainer(viewOrContainer)) {\n viewOrContainer = viewOrContainer[NEXT];\n }\n return viewOrContainer;\n}\n\n/**\n * NOTE: for performance reasons, the possible actions are inlined within the function instead of\n * being passed as an argument.\n */\nfunction applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) {\n // If this slot was allocated for a text node dynamically created by i18n, the text node itself\n // won't be created until i18nApply() in the update block, so this node should be skipped.\n // For more info, see \"ICU expressions should work inside an ngTemplateOutlet inside an ngFor\"\n // in `i18n_spec.ts`.\n if (lNodeToHandle != null) {\n let lContainer;\n let isComponent = false;\n // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is\n // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if\n // it has LContainer so that we can process all of those cases appropriately.\n if (isLContainer(lNodeToHandle)) {\n lContainer = lNodeToHandle;\n }\n else if (isLView(lNodeToHandle)) {\n isComponent = true;\n ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');\n lNodeToHandle = lNodeToHandle[HOST];\n }\n const rNode = unwrapRNode(lNodeToHandle);\n if (action === 0 /* WalkTNodeTreeAction.Create */ && parent !== null) {\n if (beforeNode == null) {\n nativeAppendChild(renderer, parent, rNode);\n }\n else {\n nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);\n }\n }\n else if (action === 1 /* WalkTNodeTreeAction.Insert */ && parent !== null) {\n nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);\n }\n else if (action === 2 /* WalkTNodeTreeAction.Detach */) {\n nativeRemoveNode(renderer, rNode, isComponent);\n }\n else if (action === 3 /* WalkTNodeTreeAction.Destroy */) {\n ngDevMode && ngDevMode.rendererDestroyNode++;\n renderer.destroyNode(rNode);\n }\n if (lContainer != null) {\n applyContainer(renderer, action, lContainer, parent, beforeNode);\n }\n }\n}\nfunction createTextNode(renderer, value) {\n ngDevMode && ngDevMode.rendererCreateTextNode++;\n ngDevMode && ngDevMode.rendererSetText++;\n return renderer.createText(value);\n}\nfunction updateTextNode(renderer, rNode, value) {\n ngDevMode && ngDevMode.rendererSetText++;\n renderer.setValue(rNode, value);\n}\nfunction createCommentNode(renderer, value) {\n ngDevMode && ngDevMode.rendererCreateComment++;\n return renderer.createComment(escapeCommentText(value));\n}\n/**\n * Creates a native element from a tag name, using a renderer.\n * @param renderer A renderer to use\n * @param name the tag name\n * @param namespace Optional namespace for element.\n * @returns the element created\n */\nfunction createElementNode(renderer, name, namespace) {\n ngDevMode && ngDevMode.rendererCreateElement++;\n return renderer.createElement(name, namespace);\n}\n/**\n * Removes all DOM elements associated with a view.\n *\n * Because some root nodes of the view may be containers, we sometimes need\n * to propagate deeply into the nested containers to remove all elements in the\n * views beneath it.\n *\n * @param tView The `TView' of the `LView` from which elements should be added or removed\n * @param lView The view from which elements should be added or removed\n */\nfunction removeViewFromDOM(tView, lView) {\n const renderer = lView[RENDERER];\n applyView(tView, lView, renderer, 2 /* WalkTNodeTreeAction.Detach */, null, null);\n lView[HOST] = null;\n lView[T_HOST] = null;\n}\n/**\n * Adds all DOM elements associated with a view.\n *\n * Because some root nodes of the view may be containers, we sometimes need\n * to propagate deeply into the nested containers to add all elements in the\n * views beneath it.\n *\n * @param tView The `TView' of the `LView` from which elements should be added or removed\n * @param parentTNode The `TNode` where the `LView` should be attached to.\n * @param renderer Current renderer to use for DOM manipulations.\n * @param lView The view from which elements should be added or removed\n * @param parentNativeNode The parent `RElement` where it should be inserted into.\n * @param beforeNode The node before which elements should be added, if insert mode\n */\nfunction addViewToDOM(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {\n lView[HOST] = parentNativeNode;\n lView[T_HOST] = parentTNode;\n applyView(tView, lView, renderer, 1 /* WalkTNodeTreeAction.Insert */, parentNativeNode, beforeNode);\n}\n/**\n * Detach a `LView` from the DOM by detaching its nodes.\n *\n * @param tView The `TView' of the `LView` to be detached\n * @param lView the `LView` to be detached.\n */\nfunction detachViewFromDOM(tView, lView) {\n applyView(tView, lView, lView[RENDERER], 2 /* WalkTNodeTreeAction.Detach */, null, null);\n}\n/**\n * Traverses down and up the tree of views and containers to remove listeners and\n * call onDestroy callbacks.\n *\n * Notes:\n * - Because it's used for onDestroy calls, it needs to be bottom-up.\n * - Must process containers instead of their views to avoid splicing\n * when views are destroyed and re-added.\n * - Using a while loop because it's faster than recursion\n * - Destroy only called on movement to sibling or movement to parent (laterally or up)\n *\n * @param rootView The view to destroy\n */\nfunction destroyViewTree(rootView) {\n // If the view has no children, we can clean it up and return early.\n let lViewOrLContainer = rootView[CHILD_HEAD];\n if (!lViewOrLContainer) {\n return cleanUpView(rootView[TVIEW], rootView);\n }\n while (lViewOrLContainer) {\n let next = null;\n if (isLView(lViewOrLContainer)) {\n // If LView, traverse down to child.\n next = lViewOrLContainer[CHILD_HEAD];\n }\n else {\n ngDevMode && assertLContainer(lViewOrLContainer);\n // If container, traverse down to its first LView.\n const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];\n if (firstView)\n next = firstView;\n }\n if (!next) {\n // Only clean up view when moving to the side or up, as destroy hooks\n // should be called in order from the bottom up.\n while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) {\n if (isLView(lViewOrLContainer)) {\n cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);\n }\n lViewOrLContainer = lViewOrLContainer[PARENT];\n }\n if (lViewOrLContainer === null)\n lViewOrLContainer = rootView;\n if (isLView(lViewOrLContainer)) {\n cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);\n }\n next = lViewOrLContainer && lViewOrLContainer[NEXT];\n }\n lViewOrLContainer = next;\n }\n}\n/**\n * Inserts a view into a container.\n *\n * This adds the view to the container's array of active views in the correct\n * position. It also adds the view's elements to the DOM if the container isn't a\n * root node of another view (in that case, the view's elements will be added when\n * the container's parent view is added later).\n *\n * @param tView The `TView' of the `LView` to insert\n * @param lView The view to insert\n * @param lContainer The container into which the view should be inserted\n * @param index Which index in the container to insert the child view into\n */\nfunction insertView(tView, lView, lContainer, index) {\n ngDevMode && assertLView(lView);\n ngDevMode && assertLContainer(lContainer);\n const indexInContainer = CONTAINER_HEADER_OFFSET + index;\n const containerLength = lContainer.length;\n if (index > 0) {\n // This is a new view, we need to add it to the children.\n lContainer[indexInContainer - 1][NEXT] = lView;\n }\n if (index < containerLength - CONTAINER_HEADER_OFFSET) {\n lView[NEXT] = lContainer[indexInContainer];\n addToArray(lContainer, CONTAINER_HEADER_OFFSET + index, lView);\n }\n else {\n lContainer.push(lView);\n lView[NEXT] = null;\n }\n lView[PARENT] = lContainer;\n // track views where declaration and insertion points are different\n const declarationLContainer = lView[DECLARATION_LCONTAINER];\n if (declarationLContainer !== null && lContainer !== declarationLContainer) {\n trackMovedView(declarationLContainer, lView);\n }\n // notify query that a new view has been added\n const lQueries = lView[QUERIES];\n if (lQueries !== null) {\n lQueries.insertView(tView);\n }\n // Sets the attached flag\n lView[FLAGS] |= 128 /* LViewFlags.Attached */;\n}\n/**\n * Track views created from the declaration container (TemplateRef) and inserted into a\n * different LContainer.\n */\nfunction trackMovedView(declarationContainer, lView) {\n ngDevMode && assertDefined(lView, 'LView required');\n ngDevMode && assertLContainer(declarationContainer);\n const movedViews = declarationContainer[MOVED_VIEWS];\n const insertedLContainer = lView[PARENT];\n ngDevMode && assertLContainer(insertedLContainer);\n const insertedComponentLView = insertedLContainer[PARENT][DECLARATION_COMPONENT_VIEW];\n ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView');\n const declaredComponentLView = lView[DECLARATION_COMPONENT_VIEW];\n ngDevMode && assertDefined(declaredComponentLView, 'Missing declaredComponentLView');\n if (declaredComponentLView !== insertedComponentLView) {\n // At this point the declaration-component is not same as insertion-component; this means that\n // this is a transplanted view. Mark the declared lView as having transplanted views so that\n // those views can participate in CD.\n declarationContainer[HAS_TRANSPLANTED_VIEWS] = true;\n }\n if (movedViews === null) {\n declarationContainer[MOVED_VIEWS] = [lView];\n }\n else {\n movedViews.push(lView);\n }\n}\nfunction detachMovedView(declarationContainer, lView) {\n ngDevMode && assertLContainer(declarationContainer);\n ngDevMode &&\n assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');\n const movedViews = declarationContainer[MOVED_VIEWS];\n const declarationViewIndex = movedViews.indexOf(lView);\n const insertionLContainer = lView[PARENT];\n ngDevMode && assertLContainer(insertionLContainer);\n // If the view was marked for refresh but then detached before it was checked (where the flag\n // would be cleared and the counter decremented), we need to update the status here.\n clearViewRefreshFlag(lView);\n movedViews.splice(declarationViewIndex, 1);\n}\n/**\n * Detaches a view from a container.\n *\n * This method removes the view from the container's array of active views. It also\n * removes the view's elements from the DOM.\n *\n * @param lContainer The container from which to detach a view\n * @param removeIndex The index of the view to detach\n * @returns Detached LView instance.\n */\nfunction detachView(lContainer, removeIndex) {\n if (lContainer.length <= CONTAINER_HEADER_OFFSET)\n return;\n const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;\n const viewToDetach = lContainer[indexInContainer];\n if (viewToDetach) {\n const declarationLContainer = viewToDetach[DECLARATION_LCONTAINER];\n if (declarationLContainer !== null && declarationLContainer !== lContainer) {\n detachMovedView(declarationLContainer, viewToDetach);\n }\n if (removeIndex > 0) {\n lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT];\n }\n const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);\n removeViewFromDOM(viewToDetach[TVIEW], viewToDetach);\n // notify query that a view has been removed\n const lQueries = removedLView[QUERIES];\n if (lQueries !== null) {\n lQueries.detachView(removedLView[TVIEW]);\n }\n viewToDetach[PARENT] = null;\n viewToDetach[NEXT] = null;\n // Unsets the attached flag\n viewToDetach[FLAGS] &= ~128 /* LViewFlags.Attached */;\n }\n return viewToDetach;\n}\n/**\n * A standalone function which destroys an LView,\n * conducting clean up (e.g. removing listeners, calling onDestroys).\n *\n * @param tView The `TView' of the `LView` to be destroyed\n * @param lView The view to be destroyed.\n */\nfunction destroyLView(tView, lView) {\n if (!(lView[FLAGS] & 256 /* LViewFlags.Destroyed */)) {\n const renderer = lView[RENDERER];\n lView[REACTIVE_TEMPLATE_CONSUMER]?.destroy();\n lView[REACTIVE_HOST_BINDING_CONSUMER]?.destroy();\n if (renderer.destroyNode) {\n applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);\n }\n destroyViewTree(lView);\n }\n}\n/**\n * Calls onDestroys hooks for all directives and pipes in a given view and then removes all\n * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks\n * can be propagated to @Output listeners.\n *\n * @param tView `TView` for the `LView` to clean up.\n * @param lView The LView to clean up\n */\nfunction cleanUpView(tView, lView) {\n if (!(lView[FLAGS] & 256 /* LViewFlags.Destroyed */)) {\n // Usually the Attached flag is removed when the view is detached from its parent, however\n // if it's a root view, the flag won't be unset hence why we're also removing on destroy.\n lView[FLAGS] &= ~128 /* LViewFlags.Attached */;\n // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook\n // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If\n // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.\n // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is\n // really more of an \"afterDestroy\" hook if you think about it.\n lView[FLAGS] |= 256 /* LViewFlags.Destroyed */;\n executeOnDestroys(tView, lView);\n processCleanups(tView, lView);\n // For component views only, the local renderer is destroyed at clean up time.\n if (lView[TVIEW].type === 1 /* TViewType.Component */) {\n ngDevMode && ngDevMode.rendererDestroy++;\n lView[RENDERER].destroy();\n }\n const declarationContainer = lView[DECLARATION_LCONTAINER];\n // we are dealing with an embedded view that is still inserted into a container\n if (declarationContainer !== null && isLContainer(lView[PARENT])) {\n // and this is a projected view\n if (declarationContainer !== lView[PARENT]) {\n detachMovedView(declarationContainer, lView);\n }\n // For embedded views still attached to a container: remove query result from this view.\n const lQueries = lView[QUERIES];\n if (lQueries !== null) {\n lQueries.detachView(tView);\n }\n }\n // Unregister the view once everything else has been cleaned up.\n unregisterLView(lView);\n }\n}\n/** Removes listeners and unsubscribes from output subscriptions */\nfunction processCleanups(tView, lView) {\n const tCleanup = tView.cleanup;\n const lCleanup = lView[CLEANUP];\n if (tCleanup !== null) {\n for (let i = 0; i < tCleanup.length - 1; i += 2) {\n if (typeof tCleanup[i] === 'string') {\n // This is a native DOM listener. It will occupy 4 entries in the TCleanup array (hence i +=\n // 2 at the end of this block).\n const targetIdx = tCleanup[i + 3];\n ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');\n if (targetIdx >= 0) {\n // unregister\n lCleanup[targetIdx]();\n }\n else {\n // Subscription\n lCleanup[-targetIdx].unsubscribe();\n }\n i += 2;\n }\n else {\n // This is a cleanup function that is grouped with the index of its context\n const context = lCleanup[tCleanup[i + 1]];\n tCleanup[i].call(context);\n }\n }\n }\n if (lCleanup !== null) {\n lView[CLEANUP] = null;\n }\n const destroyHooks = lView[ON_DESTROY_HOOKS];\n if (destroyHooks !== null) {\n // Reset the ON_DESTROY_HOOKS array before iterating over it to prevent hooks that unregister\n // themselves from mutating the array during iteration.\n lView[ON_DESTROY_HOOKS] = null;\n for (let i = 0; i < destroyHooks.length; i++) {\n const destroyHooksFn = destroyHooks[i];\n ngDevMode && assertFunction(destroyHooksFn, 'Expecting destroy hook to be a function.');\n destroyHooksFn();\n }\n }\n}\n/** Calls onDestroy hooks for this view */\nfunction executeOnDestroys(tView, lView) {\n let destroyHooks;\n if (tView != null && (destroyHooks = tView.destroyHooks) != null) {\n for (let i = 0; i < destroyHooks.length; i += 2) {\n const context = lView[destroyHooks[i]];\n // Only call the destroy hook if the context has been requested.\n if (!(context instanceof NodeInjectorFactory)) {\n const toCall = destroyHooks[i + 1];\n if (Array.isArray(toCall)) {\n for (let j = 0; j < toCall.length; j += 2) {\n const callContext = context[toCall[j]];\n const hook = toCall[j + 1];\n profiler(4 /* ProfilerEvent.LifecycleHookStart */, callContext, hook);\n try {\n hook.call(callContext);\n }\n finally {\n profiler(5 /* ProfilerEvent.LifecycleHookEnd */, callContext, hook);\n }\n }\n }\n else {\n profiler(4 /* ProfilerEvent.LifecycleHookStart */, context, toCall);\n try {\n toCall.call(context);\n }\n finally {\n profiler(5 /* ProfilerEvent.LifecycleHookEnd */, context, toCall);\n }\n }\n }\n }\n }\n}\n/**\n * Returns a native element if a node can be inserted into the given parent.\n *\n * There are two reasons why we may not be able to insert a element immediately.\n * - Projection: When creating a child content element of a component, we have to skip the\n * insertion because the content of a component will be projected.\n * `delayed due to projection`\n * - Parent container is disconnected: This can happen when we are inserting a view into\n * parent container, which itself is disconnected. For example the parent container is part\n * of a View which has not be inserted or is made for projection but has not been inserted\n * into destination.\n *\n * @param tView: Current `TView`.\n * @param tNode: `TNode` for which we wish to retrieve render parent.\n * @param lView: Current `LView`.\n */\nfunction getParentRElement(tView, tNode, lView) {\n return getClosestRElement(tView, tNode.parent, lView);\n}\n/**\n * Get closest `RElement` or `null` if it can't be found.\n *\n * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.\n * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).\n * If `TNode` is `null` then return host `RElement`:\n * - return `null` if projection\n * - return `null` if parent container is disconnected (we have no parent.)\n *\n * @param tView: Current `TView`.\n * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is\n * needed).\n * @param lView: Current `LView`.\n * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)\n */\nfunction getClosestRElement(tView, tNode, lView) {\n let parentTNode = tNode;\n // Skip over element and ICU containers as those are represented by a comment node and\n // can't be used as a render parent.\n while (parentTNode !== null &&\n (parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */))) {\n tNode = parentTNode;\n parentTNode = tNode.parent;\n }\n // If the parent tNode is null, then we are inserting across views: either into an embedded view\n // or a component view.\n if (parentTNode === null) {\n // We are inserting a root element of the component view into the component host element and\n // it should always be eager.\n return lView[HOST];\n }\n else {\n ngDevMode && assertTNodeType(parentTNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);\n const { componentOffset } = parentTNode;\n if (componentOffset > -1) {\n ngDevMode && assertTNodeForLView(parentTNode, lView);\n const { encapsulation } = tView.data[parentTNode.directiveStart + componentOffset];\n // We've got a parent which is an element in the current view. We just need to verify if the\n // parent element is not a component. Component's content nodes are not inserted immediately\n // because they will be projected, and so doing insert at this point would be wasteful.\n // Since the projection would then move it to its final destination. Note that we can't\n // make this assumption when using the Shadow DOM, because the native projection placeholders\n // ( or ) have to be in place as elements are being inserted.\n if (encapsulation === ViewEncapsulation$1.None ||\n encapsulation === ViewEncapsulation$1.Emulated) {\n return null;\n }\n }\n return getNativeByTNode(parentTNode, lView);\n }\n}\n/**\n * Inserts a native node before another native node for a given parent.\n * This is a utility function that can be used when native nodes were determined.\n */\nfunction nativeInsertBefore(renderer, parent, child, beforeNode, isMove) {\n ngDevMode && ngDevMode.rendererInsertBefore++;\n renderer.insertBefore(parent, child, beforeNode, isMove);\n}\nfunction nativeAppendChild(renderer, parent, child) {\n ngDevMode && ngDevMode.rendererAppendChild++;\n ngDevMode && assertDefined(parent, 'parent node must be defined');\n renderer.appendChild(parent, child);\n}\nfunction nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove) {\n if (beforeNode !== null) {\n nativeInsertBefore(renderer, parent, child, beforeNode, isMove);\n }\n else {\n nativeAppendChild(renderer, parent, child);\n }\n}\n/** Removes a node from the DOM given its native parent. */\nfunction nativeRemoveChild(renderer, parent, child, isHostElement) {\n renderer.removeChild(parent, child, isHostElement);\n}\n/** Checks if an element is a `` node. */\nfunction isTemplateNode(node) {\n return node.tagName === 'TEMPLATE' && node.content !== undefined;\n}\n/**\n * Returns a native parent of a given native node.\n */\nfunction nativeParentNode(renderer, node) {\n return renderer.parentNode(node);\n}\n/**\n * Returns a native sibling of a given native node.\n */\nfunction nativeNextSibling(renderer, node) {\n return renderer.nextSibling(node);\n}\n/**\n * Find a node in front of which `currentTNode` should be inserted.\n *\n * This method determines the `RNode` in front of which we should insert the `currentRNode`. This\n * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.\n *\n * @param parentTNode parent `TNode`\n * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)\n * @param lView current `LView`\n */\nfunction getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {\n return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);\n}\n/**\n * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into\n * account)\n *\n * This method determines the `RNode` in front of which we should insert the `currentRNode`. This\n * does not take `TNode.insertBeforeIndex` into account.\n *\n * @param parentTNode parent `TNode`\n * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)\n * @param lView current `LView`\n */\nfunction getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {\n if (parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */)) {\n return getNativeByTNode(parentTNode, lView);\n }\n return null;\n}\n/**\n * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.\n *\n * This function will only be set if i18n code runs.\n */\nlet _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;\n/**\n * Tree shakable boundary for `processI18nInsertBefore` function.\n *\n * This function will only be set if i18n code runs.\n */\nlet _processI18nInsertBefore;\nfunction setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {\n _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;\n _processI18nInsertBefore = processI18nInsertBefore;\n}\n/**\n * Appends the `child` native node (or a collection of nodes) to the `parent`.\n *\n * @param tView The `TView' to be appended\n * @param lView The current LView\n * @param childRNode The native child (or children) that should be appended\n * @param childTNode The TNode of the child element\n */\nfunction appendChild(tView, lView, childRNode, childTNode) {\n const parentRNode = getParentRElement(tView, childTNode, lView);\n const renderer = lView[RENDERER];\n const parentTNode = childTNode.parent || lView[T_HOST];\n const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);\n if (parentRNode != null) {\n if (Array.isArray(childRNode)) {\n for (let i = 0; i < childRNode.length; i++) {\n nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);\n }\n }\n else {\n nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);\n }\n }\n _processI18nInsertBefore !== undefined &&\n _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);\n}\n/**\n * Returns the first native node for a given LView, starting from the provided TNode.\n *\n * Native nodes are returned in the order in which those appear in the native tree (DOM).\n */\nfunction getFirstNativeNode(lView, tNode) {\n if (tNode !== null) {\n ngDevMode &&\n assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */ | 32 /* TNodeType.Icu */ | 16 /* TNodeType.Projection */);\n const tNodeType = tNode.type;\n if (tNodeType & 3 /* TNodeType.AnyRNode */) {\n return getNativeByTNode(tNode, lView);\n }\n else if (tNodeType & 4 /* TNodeType.Container */) {\n return getBeforeNodeForView(-1, lView[tNode.index]);\n }\n else if (tNodeType & 8 /* TNodeType.ElementContainer */) {\n const elIcuContainerChild = tNode.child;\n if (elIcuContainerChild !== null) {\n return getFirstNativeNode(lView, elIcuContainerChild);\n }\n else {\n const rNodeOrLContainer = lView[tNode.index];\n if (isLContainer(rNodeOrLContainer)) {\n return getBeforeNodeForView(-1, rNodeOrLContainer);\n }\n else {\n return unwrapRNode(rNodeOrLContainer);\n }\n }\n }\n else if (tNodeType & 32 /* TNodeType.Icu */) {\n let nextRNode = icuContainerIterate(tNode, lView);\n let rNode = nextRNode();\n // If the ICU container has no nodes, than we use the ICU anchor as the node.\n return rNode || unwrapRNode(lView[tNode.index]);\n }\n else {\n const projectionNodes = getProjectionNodes(lView, tNode);\n if (projectionNodes !== null) {\n if (Array.isArray(projectionNodes)) {\n return projectionNodes[0];\n }\n const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);\n ngDevMode && assertParentView(parentView);\n return getFirstNativeNode(parentView, projectionNodes);\n }\n else {\n return getFirstNativeNode(lView, tNode.next);\n }\n }\n }\n return null;\n}\nfunction getProjectionNodes(lView, tNode) {\n if (tNode !== null) {\n const componentView = lView[DECLARATION_COMPONENT_VIEW];\n const componentHost = componentView[T_HOST];\n const slotIdx = tNode.projection;\n ngDevMode && assertProjectionSlots(lView);\n return componentHost.projection[slotIdx];\n }\n return null;\n}\nfunction getBeforeNodeForView(viewIndexInContainer, lContainer) {\n const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;\n if (nextViewIndex < lContainer.length) {\n const lView = lContainer[nextViewIndex];\n const firstTNodeOfView = lView[TVIEW].firstChild;\n if (firstTNodeOfView !== null) {\n return getFirstNativeNode(lView, firstTNodeOfView);\n }\n }\n return lContainer[NATIVE];\n}\n/**\n * Removes a native node itself using a given renderer. To remove the node we are looking up its\n * parent from the native tree as not all platforms / browsers support the equivalent of\n * node.remove().\n *\n * @param renderer A renderer to be used\n * @param rNode The native node that should be removed\n * @param isHostElement A flag indicating if a node to be removed is a host of a component.\n */\nfunction nativeRemoveNode(renderer, rNode, isHostElement) {\n ngDevMode && ngDevMode.rendererRemoveNode++;\n const nativeParent = nativeParentNode(renderer, rNode);\n if (nativeParent) {\n nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);\n }\n}\n/**\n * Clears the contents of a given RElement.\n *\n * @param rElement the native RElement to be cleared\n */\nfunction clearElementContents(rElement) {\n rElement.textContent = '';\n}\n/**\n * Performs the operation of `action` on the node. Typically this involves inserting or removing\n * nodes on the LView or projection boundary.\n */\nfunction applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {\n while (tNode != null) {\n ngDevMode && assertTNodeForLView(tNode, lView);\n ngDevMode &&\n assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */ | 16 /* TNodeType.Projection */ | 32 /* TNodeType.Icu */);\n const rawSlotValue = lView[tNode.index];\n const tNodeType = tNode.type;\n if (isProjection) {\n if (action === 0 /* WalkTNodeTreeAction.Create */) {\n rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);\n tNode.flags |= 2 /* TNodeFlags.isProjected */;\n }\n }\n if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {\n if (tNodeType & 8 /* TNodeType.ElementContainer */) {\n applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);\n applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);\n }\n else if (tNodeType & 32 /* TNodeType.Icu */) {\n const nextRNode = icuContainerIterate(tNode, lView);\n let rNode;\n while (rNode = nextRNode()) {\n applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);\n }\n applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);\n }\n else if (tNodeType & 16 /* TNodeType.Projection */) {\n applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);\n }\n else {\n ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);\n applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);\n }\n }\n tNode = isProjection ? tNode.projectionNext : tNode.next;\n }\n}\nfunction applyView(tView, lView, renderer, action, parentRElement, beforeNode) {\n applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);\n}\n/**\n * `applyProjection` performs operation on the projection.\n *\n * Inserting a projection requires us to locate the projected nodes from the parent component. The\n * complication is that those nodes themselves could be re-projected from their parent component.\n *\n * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed\n * @param lView The `LView` which needs to be inserted, detached, destroyed.\n * @param tProjectionNode node to project\n */\nfunction applyProjection(tView, lView, tProjectionNode) {\n const renderer = lView[RENDERER];\n const parentRNode = getParentRElement(tView, tProjectionNode, lView);\n const parentTNode = tProjectionNode.parent || lView[T_HOST];\n let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);\n applyProjectionRecursive(renderer, 0 /* WalkTNodeTreeAction.Create */, lView, tProjectionNode, parentRNode, beforeNode);\n}\n/**\n * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,\n * detach, destroy)\n *\n * Inserting a projection requires us to locate the projected nodes from the parent component. The\n * complication is that those nodes themselves could be re-projected from their parent component.\n *\n * @param renderer Render to use\n * @param action action to perform (insert, detach, destroy)\n * @param lView The LView which needs to be inserted, detached, destroyed.\n * @param tProjectionNode node to project\n * @param parentRElement parent DOM element for insertion/removal.\n * @param beforeNode Before which node the insertions should happen.\n */\nfunction applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) {\n const componentLView = lView[DECLARATION_COMPONENT_VIEW];\n const componentNode = componentLView[T_HOST];\n ngDevMode &&\n assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');\n const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection];\n if (Array.isArray(nodeToProjectOrRNodes)) {\n // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we\n // need to support passing projectable nodes, so we cheat and put them in the TNode\n // of the Host TView. (Yes we put instance info at the T Level). We can get away with it\n // because we know that that TView is not shared and therefore it will not be a problem.\n // This should be refactored and cleaned up.\n for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {\n const rNode = nodeToProjectOrRNodes[i];\n applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);\n }\n }\n else {\n let nodeToProject = nodeToProjectOrRNodes;\n const projectedComponentLView = componentLView[PARENT];\n // If a parent is located within a skip hydration block,\n // annotate an actual node that is being projected with the same flag too.\n if (hasInSkipHydrationBlockFlag(tProjectionNode)) {\n nodeToProject.flags |= 128 /* TNodeFlags.inSkipHydrationBlock */;\n }\n applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);\n }\n}\n/**\n * `applyContainer` performs an operation on the container and its views as specified by\n * `action` (insert, detach, destroy)\n *\n * Inserting a Container is complicated by the fact that the container may have Views which\n * themselves have containers or projections.\n *\n * @param renderer Renderer to use\n * @param action action to perform (insert, detach, destroy)\n * @param lContainer The LContainer which needs to be inserted, detached, destroyed.\n * @param parentRElement parent DOM element for insertion/removal.\n * @param beforeNode Before which node the insertions should happen.\n */\nfunction applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {\n ngDevMode && assertLContainer(lContainer);\n const anchor = lContainer[NATIVE]; // LContainer has its own before node.\n const native = unwrapRNode(lContainer);\n // An LContainer can be created dynamically on any node by injecting ViewContainerRef.\n // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor\n // node (comment in the DOM) that will be different from the LContainer's host node. In this\n // particular case we need to execute action on 2 nodes:\n // - container's host node (this is done in the executeActionOnElementOrContainer)\n // - container's host node (this is done here)\n if (anchor !== native) {\n // This is very strange to me (Misko). I would expect that the native is same as anchor. I\n // don't see a reason why they should be different, but they are.\n //\n // If they are we need to process the second anchor as well.\n applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);\n }\n for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {\n const lView = lContainer[i];\n applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);\n }\n}\n/**\n * Writes class/style to element.\n *\n * @param renderer Renderer to use.\n * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)\n * @param rNode The Node to write to.\n * @param prop Property to write to. This would be the class/style name.\n * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add\n * otherwise).\n */\nfunction applyStyling(renderer, isClassBased, rNode, prop, value) {\n if (isClassBased) {\n // We actually want JS true/false here because any truthy value should add the class\n if (!value) {\n ngDevMode && ngDevMode.rendererRemoveClass++;\n renderer.removeClass(rNode, prop);\n }\n else {\n ngDevMode && ngDevMode.rendererAddClass++;\n renderer.addClass(rNode, prop);\n }\n }\n else {\n let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;\n if (value == null /** || value === undefined */) {\n ngDevMode && ngDevMode.rendererRemoveStyle++;\n renderer.removeStyle(rNode, prop, flags);\n }\n else {\n // A value is important if it ends with `!important`. The style\n // parser strips any semicolons at the end of the value.\n const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;\n if (isImportant) {\n // !important has to be stripped from the value for it to be valid.\n value = value.slice(0, -10);\n flags |= RendererStyleFlags2.Important;\n }\n ngDevMode && ngDevMode.rendererSetStyle++;\n renderer.setStyle(rNode, prop, value, flags);\n }\n }\n}\n/**\n * Write `cssText` to `RElement`.\n *\n * This function does direct write without any reconciliation. Used for writing initial values, so\n * that static styling values do not pull in the style parser.\n *\n * @param renderer Renderer to use\n * @param element The element which needs to be updated.\n * @param newValue The new class list to write.\n */\nfunction writeDirectStyle(renderer, element, newValue) {\n ngDevMode && assertString(newValue, '\\'newValue\\' should be a string');\n renderer.setAttribute(element, 'style', newValue);\n ngDevMode && ngDevMode.rendererSetStyle++;\n}\n/**\n * Write `className` to `RElement`.\n *\n * This function does direct write without any reconciliation. Used for writing initial values, so\n * that static styling values do not pull in the style parser.\n *\n * @param renderer Renderer to use\n * @param element The element which needs to be updated.\n * @param newValue The new class list to write.\n */\nfunction writeDirectClass(renderer, element, newValue) {\n ngDevMode && assertString(newValue, '\\'newValue\\' should be a string');\n if (newValue === '') {\n // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.\n renderer.removeAttribute(element, 'class');\n }\n else {\n renderer.setAttribute(element, 'class', newValue);\n }\n ngDevMode && ngDevMode.rendererSetClassName++;\n}\n/** Sets up the static DOM attributes on an `RNode`. */\nfunction setupStaticAttributes(renderer, element, tNode) {\n const { mergedAttrs, classes, styles } = tNode;\n if (mergedAttrs !== null) {\n setUpAttributes(renderer, element, mergedAttrs);\n }\n if (classes !== null) {\n writeDirectClass(renderer, element, classes);\n }\n if (styles !== null) {\n writeDirectStyle(renderer, element, styles);\n }\n}\n\n/**\n * @fileoverview\n * A module to facilitate use of a Trusted Types policy internally within\n * Angular. It lazily constructs the Trusted Types policy, providing helper\n * utilities for promoting strings to Trusted Types. When Trusted Types are not\n * available, strings are used as a fallback.\n * @security All use of this module is security-sensitive and should go through\n * security review.\n */\n/**\n * The Trusted Types policy, or null if Trusted Types are not\n * enabled/supported, or undefined if the policy has not been created yet.\n */\nlet policy$1;\n/**\n * Returns the Trusted Types policy, or null if Trusted Types are not\n * enabled/supported. The first call to this function will create the policy.\n */\nfunction getPolicy$1() {\n if (policy$1 === undefined) {\n policy$1 = null;\n if (_global.trustedTypes) {\n try {\n policy$1 = _global.trustedTypes.createPolicy('angular', {\n createHTML: (s) => s,\n createScript: (s) => s,\n createScriptURL: (s) => s,\n });\n }\n catch {\n // trustedTypes.createPolicy throws if called with a name that is\n // already registered, even in report-only mode. Until the API changes,\n // catch the error not to break the applications functionally. In such\n // cases, the code will fall back to using strings.\n }\n }\n }\n return policy$1;\n}\n/**\n * Unsafely promote a string to a TrustedHTML, falling back to strings when\n * Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that the\n * provided string will never cause an XSS vulnerability if used in a context\n * that will be interpreted as HTML by a browser, e.g. when assigning to\n * element.innerHTML.\n */\nfunction trustedHTMLFromString(html) {\n return getPolicy$1()?.createHTML(html) || html;\n}\n/**\n * Unsafely promote a string to a TrustedScript, falling back to strings when\n * Trusted Types are not available.\n * @security In particular, it must be assured that the provided string will\n * never cause an XSS vulnerability if used in a context that will be\n * interpreted and executed as a script by a browser, e.g. when calling eval.\n */\nfunction trustedScriptFromString(script) {\n return getPolicy$1()?.createScript(script) || script;\n}\n/**\n * Unsafely promote a string to a TrustedScriptURL, falling back to strings\n * when Trusted Types are not available.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that the\n * provided string will never cause an XSS vulnerability if used in a context\n * that will cause a browser to load and execute a resource, e.g. when\n * assigning to script.src.\n */\nfunction trustedScriptURLFromString(url) {\n return getPolicy$1()?.createScriptURL(url) || url;\n}\n/**\n * Unsafely call the Function constructor with the given string arguments. It\n * is only available in development mode, and should be stripped out of\n * production code.\n * @security This is a security-sensitive function; any use of this function\n * must go through security review. In particular, it must be assured that it\n * is only called from development code, as use in production code can lead to\n * XSS vulnerabilities.\n */\nfunction newTrustedFunctionForDev(...args) {\n if (typeof ngDevMode === 'undefined') {\n throw new Error('newTrustedFunctionForDev should never be called in production');\n }\n if (!_global.trustedTypes) {\n // In environments that don't support Trusted Types, fall back to the most\n // straightforward implementation:\n return new Function(...args);\n }\n // Chrome currently does not support passing TrustedScript to the Function\n // constructor. The following implements the workaround proposed on the page\n // below, where the Chromium bug is also referenced:\n // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor\n const fnArgs = args.slice(0, -1).join(',');\n const fnBody = args[args.length - 1];\n const body = `(function anonymous(${fnArgs}\n) { ${fnBody}\n})`;\n // Using eval directly confuses the compiler and prevents this module from\n // being stripped out of JS binaries even if not used. The global['eval']\n // indirection fixes that.\n const fn = _global['eval'](trustedScriptFromString(body));\n if (fn.bind === undefined) {\n // Workaround for a browser bug that only exists in Chrome 83, where passing\n // a TrustedScript to eval just returns the TrustedScript back without\n // evaluating it. In that case, fall back to the most straightforward\n // implementation:\n return new Function(...args);\n }\n // To completely mimic the behavior of calling \"new Function\", two more\n // things need to happen:\n // 1. Stringifying the resulting function should return its source code\n fn.toString = () => body;\n // 2. When calling the resulting function, `this` should refer to `global`\n return fn.bind(_global);\n // When Trusted Types support in Function constructors is widely available,\n // the implementation of this function can be simplified to:\n // return new Function(...args.map(a => trustedScriptFromString(a)));\n}\n\n/**\n * Validation function invoked at runtime for each binding that might potentially\n * represent a security-sensitive attribute of an