UNPKG

1.33 MBJavaScriptView Raw
1/**
2 * @license Angular v13.0.2
3 * (c) 2010-2021 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import { Subject, Subscription, Observable, merge as merge$1 } from 'rxjs';
8import { share } from 'rxjs/operators';
9
10/**
11 * @license
12 * Copyright Google LLC All Rights Reserved.
13 *
14 * Use of this source code is governed by an MIT-style license that can be
15 * found in the LICENSE file at https://angular.io/license
16 */
17function getClosureSafeProperty(objWithPropertyToExtract) {
18 for (let key in objWithPropertyToExtract) {
19 if (objWithPropertyToExtract[key] === getClosureSafeProperty) {
20 return key;
21 }
22 }
23 throw Error('Could not find renamed property on target object.');
24}
25/**
26 * Sets properties on a target object from a source object, but only if
27 * the property doesn't already exist on the target object.
28 * @param target The target to set properties on
29 * @param source The source of the property keys and values to set
30 */
31function fillProperties(target, source) {
32 for (const key in source) {
33 if (source.hasOwnProperty(key) && !target.hasOwnProperty(key)) {
34 target[key] = source[key];
35 }
36 }
37}
38
39/**
40 * @license
41 * Copyright Google LLC All Rights Reserved.
42 *
43 * Use of this source code is governed by an MIT-style license that can be
44 * found in the LICENSE file at https://angular.io/license
45 */
46function stringify(token) {
47 if (typeof token === 'string') {
48 return token;
49 }
50 if (Array.isArray(token)) {
51 return '[' + token.map(stringify).join(', ') + ']';
52 }
53 if (token == null) {
54 return '' + token;
55 }
56 if (token.overriddenName) {
57 return `${token.overriddenName}`;
58 }
59 if (token.name) {
60 return `${token.name}`;
61 }
62 const res = token.toString();
63 if (res == null) {
64 return '' + res;
65 }
66 const newLineIndex = res.indexOf('\n');
67 return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
68}
69/**
70 * Concatenates two strings with separator, allocating new strings only when necessary.
71 *
72 * @param before before string.
73 * @param separator separator string.
74 * @param after after string.
75 * @returns concatenated string.
76 */
77function concatStringsWithSpace(before, after) {
78 return (before == null || before === '') ?
79 (after === null ? '' : after) :
80 ((after == null || after === '') ? before : before + ' ' + after);
81}
82
83/**
84 * @license
85 * Copyright Google LLC All Rights Reserved.
86 *
87 * Use of this source code is governed by an MIT-style license that can be
88 * found in the LICENSE file at https://angular.io/license
89 */
90const __forward_ref__ = getClosureSafeProperty({ __forward_ref__: getClosureSafeProperty });
91/**
92 * Allows to refer to references which are not yet defined.
93 *
94 * For instance, `forwardRef` is used when the `token` which we need to refer to for the purposes of
95 * DI is declared, but not yet defined. It is also used when the `token` which we use when creating
96 * a query is not yet defined.
97 *
98 * @usageNotes
99 * ### Example
100 * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref'}
101 * @publicApi
102 */
103function forwardRef(forwardRefFn) {
104 forwardRefFn.__forward_ref__ = forwardRef;
105 forwardRefFn.toString = function () {
106 return stringify(this());
107 };
108 return forwardRefFn;
109}
110/**
111 * Lazily retrieves the reference value from a forwardRef.
112 *
113 * Acts as the identity function when given a non-forward-ref value.
114 *
115 * @usageNotes
116 * ### Example
117 *
118 * {@example core/di/ts/forward_ref/forward_ref_spec.ts region='resolve_forward_ref'}
119 *
120 * @see `forwardRef`
121 * @publicApi
122 */
123function resolveForwardRef(type) {
124 return isForwardRef(type) ? type() : type;
125}
126/** Checks whether a function is wrapped by a `forwardRef`. */
127function isForwardRef(fn) {
128 return typeof fn === 'function' && fn.hasOwnProperty(__forward_ref__) &&
129 fn.__forward_ref__ === forwardRef;
130}
131
132/**
133 * @license
134 * Copyright Google LLC All Rights Reserved.
135 *
136 * Use of this source code is governed by an MIT-style license that can be
137 * found in the LICENSE file at https://angular.io/license
138 */
139/**
140 * Base URL for the error details page.
141 *
142 * Keep the files below in full sync:
143 * - packages/compiler-cli/src/ngtsc/diagnostics/src/error_details_base_url.ts
144 * - packages/core/src/render3/error_details_base_url.ts
145 */
146const ERROR_DETAILS_PAGE_BASE_URL = 'https://angular.io/errors';
147
148/**
149 * @license
150 * Copyright Google LLC All Rights Reserved.
151 *
152 * Use of this source code is governed by an MIT-style license that can be
153 * found in the LICENSE file at https://angular.io/license
154 */
155class RuntimeError extends Error {
156 constructor(code, message) {
157 super(formatRuntimeError(code, message));
158 this.code = code;
159 }
160}
161// Contains a set of error messages that have details guides at angular.io.
162// Full list of available error guides can be found at https://angular.io/errors
163/* tslint:disable:no-toplevel-property-access */
164const RUNTIME_ERRORS_WITH_GUIDES = new Set([
165 "100" /* EXPRESSION_CHANGED_AFTER_CHECKED */,
166 "200" /* CYCLIC_DI_DEPENDENCY */,
167 "201" /* PROVIDER_NOT_FOUND */,
168 "300" /* MULTIPLE_COMPONENTS_MATCH */,
169 "301" /* EXPORT_NOT_FOUND */,
170 "302" /* PIPE_NOT_FOUND */,
171]);
172/* tslint:enable:no-toplevel-property-access */
173/** Called to format a runtime error */
174function formatRuntimeError(code, message) {
175 const fullCode = code ? `NG0${code}: ` : '';
176 let errorMessage = `${fullCode}${message}`;
177 // Some runtime errors are still thrown without `ngDevMode` (for example
178 // `throwProviderNotFoundError`), so we add `ngDevMode` check here to avoid pulling
179 // `RUNTIME_ERRORS_WITH_GUIDES` symbol into prod bundles.
180 // TODO: revisit all instances where `RuntimeError` is thrown and see if `ngDevMode` can be added
181 // there instead to tree-shake more devmode-only code (and eventually remove `ngDevMode` check
182 // from this code).
183 if (ngDevMode && RUNTIME_ERRORS_WITH_GUIDES.has(code)) {
184 errorMessage = `${errorMessage}. Find more at ${ERROR_DETAILS_PAGE_BASE_URL}/NG0${code}`;
185 }
186 return errorMessage;
187}
188
189/**
190 * @license
191 * Copyright Google LLC All Rights Reserved.
192 *
193 * Use of this source code is governed by an MIT-style license that can be
194 * found in the LICENSE file at https://angular.io/license
195 */
196/**
197 * Used for stringify render output in Ivy.
198 * Important! This function is very performance-sensitive and we should
199 * be extra careful not to introduce megamorphic reads in it.
200 * Check `core/test/render3/perf/render_stringify` for benchmarks and alternate implementations.
201 */
202function renderStringify(value) {
203 if (typeof value === 'string')
204 return value;
205 if (value == null)
206 return '';
207 // Use `String` so that it invokes the `toString` method of the value. Note that this
208 // appears to be faster than calling `value.toString` (see `render_stringify` benchmark).
209 return String(value);
210}
211/**
212 * Used to stringify a value so that it can be displayed in an error message.
213 * Important! This function contains a megamorphic read and should only be
214 * used for error messages.
215 */
216function stringifyForError(value) {
217 if (typeof value === 'function')
218 return value.name || value.toString();
219 if (typeof value === 'object' && value != null && typeof value.type === 'function') {
220 return value.type.name || value.type.toString();
221 }
222 return renderStringify(value);
223}
224
225/** Called when directives inject each other (creating a circular dependency) */
226function throwCyclicDependencyError(token, path) {
227 const depPath = path ? `. Dependency path: ${path.join(' > ')} > ${token}` : '';
228 throw new RuntimeError("200" /* CYCLIC_DI_DEPENDENCY */, `Circular dependency in DI detected for ${token}${depPath}`);
229}
230function throwMixedMultiProviderError() {
231 throw new Error(`Cannot mix multi providers and regular providers`);
232}
233function throwInvalidProviderError(ngModuleType, providers, provider) {
234 let ngModuleDetail = '';
235 if (ngModuleType && providers) {
236 const providerDetail = providers.map(v => v == provider ? '?' + provider + '?' : '...');
237 ngModuleDetail =
238 ` - only instances of Provider and Type are allowed, got: [${providerDetail.join(', ')}]`;
239 }
240 throw new Error(`Invalid provider for the NgModule '${stringify(ngModuleType)}'` + ngModuleDetail);
241}
242/** Throws an error when a token is not found in DI. */
243function throwProviderNotFoundError(token, injectorName) {
244 const injectorDetails = injectorName ? ` in ${injectorName}` : '';
245 throw new RuntimeError("201" /* PROVIDER_NOT_FOUND */, `No provider for ${stringifyForError(token)} found${injectorDetails}`);
246}
247
248/**
249 * @license
250 * Copyright Google LLC All Rights Reserved.
251 *
252 * Use of this source code is governed by an MIT-style license that can be
253 * found in the LICENSE file at https://angular.io/license
254 */
255function assertNumber(actual, msg) {
256 if (!(typeof actual === 'number')) {
257 throwError(msg, typeof actual, 'number', '===');
258 }
259}
260function assertNumberInRange(actual, minInclusive, maxInclusive) {
261 assertNumber(actual, 'Expected a number');
262 assertLessThanOrEqual(actual, maxInclusive, 'Expected number to be less than or equal to');
263 assertGreaterThanOrEqual(actual, minInclusive, 'Expected number to be greater than or equal to');
264}
265function assertString(actual, msg) {
266 if (!(typeof actual === 'string')) {
267 throwError(msg, actual === null ? 'null' : typeof actual, 'string', '===');
268 }
269}
270function assertFunction(actual, msg) {
271 if (!(typeof actual === 'function')) {
272 throwError(msg, actual === null ? 'null' : typeof actual, 'function', '===');
273 }
274}
275function assertEqual(actual, expected, msg) {
276 if (!(actual == expected)) {
277 throwError(msg, actual, expected, '==');
278 }
279}
280function assertNotEqual(actual, expected, msg) {
281 if (!(actual != expected)) {
282 throwError(msg, actual, expected, '!=');
283 }
284}
285function assertSame(actual, expected, msg) {
286 if (!(actual === expected)) {
287 throwError(msg, actual, expected, '===');
288 }
289}
290function assertNotSame(actual, expected, msg) {
291 if (!(actual !== expected)) {
292 throwError(msg, actual, expected, '!==');
293 }
294}
295function assertLessThan(actual, expected, msg) {
296 if (!(actual < expected)) {
297 throwError(msg, actual, expected, '<');
298 }
299}
300function assertLessThanOrEqual(actual, expected, msg) {
301 if (!(actual <= expected)) {
302 throwError(msg, actual, expected, '<=');
303 }
304}
305function assertGreaterThan(actual, expected, msg) {
306 if (!(actual > expected)) {
307 throwError(msg, actual, expected, '>');
308 }
309}
310function assertGreaterThanOrEqual(actual, expected, msg) {
311 if (!(actual >= expected)) {
312 throwError(msg, actual, expected, '>=');
313 }
314}
315function assertNotDefined(actual, msg) {
316 if (actual != null) {
317 throwError(msg, actual, null, '==');
318 }
319}
320function assertDefined(actual, msg) {
321 if (actual == null) {
322 throwError(msg, actual, null, '!=');
323 }
324}
325function throwError(msg, actual, expected, comparison) {
326 throw new Error(`ASSERTION ERROR: ${msg}` +
327 (comparison == null ? '' : ` [Expected=> ${expected} ${comparison} ${actual} <=Actual]`));
328}
329function assertDomNode(node) {
330 // If we're in a worker, `Node` will not be defined.
331 if (!(typeof Node !== 'undefined' && node instanceof Node) &&
332 !(typeof node === 'object' && node != null &&
333 node.constructor.name === 'WebWorkerRenderNode')) {
334 throwError(`The provided value must be an instance of a DOM Node but got ${stringify(node)}`);
335 }
336}
337function assertIndexInRange(arr, index) {
338 assertDefined(arr, 'Array must be defined.');
339 const maxLen = arr.length;
340 if (index < 0 || index >= maxLen) {
341 throwError(`Index expected to be less than ${maxLen} but got ${index}`);
342 }
343}
344function assertOneOf(value, ...validValues) {
345 if (validValues.indexOf(value) !== -1)
346 return true;
347 throwError(`Expected value to be one of ${JSON.stringify(validValues)} but was ${JSON.stringify(value)}.`);
348}
349
350/**
351 * @license
352 * Copyright Google LLC All Rights Reserved.
353 *
354 * Use of this source code is governed by an MIT-style license that can be
355 * found in the LICENSE file at https://angular.io/license
356 */
357/**
358 * Construct an injectable definition which defines how a token will be constructed by the DI
359 * system, and in which injectors (if any) it will be available.
360 *
361 * This should be assigned to a static `ɵprov` field on a type, which will then be an
362 * `InjectableType`.
363 *
364 * Options:
365 * * `providedIn` determines which injectors will include the injectable, by either associating it
366 * with an `@NgModule` or other `InjectorType`, or by specifying that this injectable should be
367 * provided in the `'root'` injector, which will be the application-level injector in most apps.
368 * * `factory` gives the zero argument function which will create an instance of the injectable.
369 * The factory can call `inject` to access the `Injector` and request injection of dependencies.
370 *
371 * @codeGenApi
372 * @publicApi This instruction has been emitted by ViewEngine for some time and is deployed to npm.
373 */
374function ɵɵdefineInjectable(opts) {
375 return {
376 token: opts.token,
377 providedIn: opts.providedIn || null,
378 factory: opts.factory,
379 value: undefined,
380 };
381}
382/**
383 * @deprecated in v8, delete after v10. This API should be used only by generated code, and that
384 * code should now use ɵɵdefineInjectable instead.
385 * @publicApi
386 */
387const defineInjectable = ɵɵdefineInjectable;
388/**
389 * Construct an `InjectorDef` which configures an injector.
390 *
391 * This should be assigned to a static injector def (`ɵinj`) field on a type, which will then be an
392 * `InjectorType`.
393 *
394 * Options:
395 *
396 * * `providers`: an optional array of providers to add to the injector. Each provider must
397 * either have a factory or point to a type which has a `ɵprov` static property (the
398 * type must be an `InjectableType`).
399 * * `imports`: an optional array of imports of other `InjectorType`s or `InjectorTypeWithModule`s
400 * whose providers will also be added to the injector. Locally provided types will override
401 * providers from imports.
402 *
403 * @codeGenApi
404 */
405function ɵɵdefineInjector(options) {
406 return { providers: options.providers || [], imports: options.imports || [] };
407}
408/**
409 * Read the injectable def (`ɵprov`) for `type` in a way which is immune to accidentally reading
410 * inherited value.
411 *
412 * @param type A type which may have its own (non-inherited) `ɵprov`.
413 */
414function getInjectableDef(type) {
415 return getOwnDefinition(type, NG_PROV_DEF) || getOwnDefinition(type, NG_INJECTABLE_DEF);
416}
417/**
418 * Return definition only if it is defined directly on `type` and is not inherited from a base
419 * class of `type`.
420 */
421function getOwnDefinition(type, field) {
422 return type.hasOwnProperty(field) ? type[field] : null;
423}
424/**
425 * Read the injectable def (`ɵprov`) for `type` or read the `ɵprov` from one of its ancestors.
426 *
427 * @param type A type which may have `ɵprov`, via inheritance.
428 *
429 * @deprecated Will be removed in a future version of Angular, where an error will occur in the
430 * scenario if we find the `ɵprov` on an ancestor only.
431 */
432function getInheritedInjectableDef(type) {
433 const def = type && (type[NG_PROV_DEF] || type[NG_INJECTABLE_DEF]);
434 if (def) {
435 const typeName = getTypeName(type);
436 // TODO(FW-1307): Re-add ngDevMode when closure can handle it
437 // ngDevMode &&
438 console.warn(`DEPRECATED: DI is instantiating a token "${typeName}" that inherits its @Injectable decorator but does not provide one itself.\n` +
439 `This will become an error in a future version of Angular. Please add @Injectable() to the "${typeName}" class.`);
440 return def;
441 }
442 else {
443 return null;
444 }
445}
446/** Gets the name of a type, accounting for some cross-browser differences. */
447function getTypeName(type) {
448 // `Function.prototype.name` behaves differently between IE and other browsers. In most browsers
449 // it'll always return the name of the function itself, no matter how many other functions it
450 // inherits from. On IE the function doesn't have its own `name` property, but it takes it from
451 // the lowest level in the prototype chain. E.g. if we have `class Foo extends Parent` most
452 // browsers will evaluate `Foo.name` to `Foo` while IE will return `Parent`. We work around
453 // the issue by converting the function to a string and parsing its name out that way via a regex.
454 if (type.hasOwnProperty('name')) {
455 return type.name;
456 }
457 const match = ('' + type).match(/^function\s*([^\s(]+)/);
458 return match === null ? '' : match[1];
459}
460/**
461 * Read the injector def type in a way which is immune to accidentally reading inherited value.
462 *
463 * @param type type which may have an injector def (`ɵinj`)
464 */
465function getInjectorDef(type) {
466 return type && (type.hasOwnProperty(NG_INJ_DEF) || type.hasOwnProperty(NG_INJECTOR_DEF)) ?
467 type[NG_INJ_DEF] :
468 null;
469}
470const NG_PROV_DEF = getClosureSafeProperty({ ɵprov: getClosureSafeProperty });
471const NG_INJ_DEF = getClosureSafeProperty({ ɵinj: getClosureSafeProperty });
472// We need to keep these around so we can read off old defs if new defs are unavailable
473const NG_INJECTABLE_DEF = getClosureSafeProperty({ ngInjectableDef: getClosureSafeProperty });
474const NG_INJECTOR_DEF = getClosureSafeProperty({ ngInjectorDef: getClosureSafeProperty });
475
476/**
477 * @license
478 * Copyright Google LLC All Rights Reserved.
479 *
480 * Use of this source code is governed by an MIT-style license that can be
481 * found in the LICENSE file at https://angular.io/license
482 */
483/**
484 * Injection flags for DI.
485 *
486 * @publicApi
487 */
488var InjectFlags;
489(function (InjectFlags) {
490 // TODO(alxhub): make this 'const' (and remove `InternalInjectFlags` enum) when ngc no longer
491 // writes exports of it into ngfactory files.
492 /** Check self and check parent injector if needed */
493 InjectFlags[InjectFlags["Default"] = 0] = "Default";
494 /**
495 * Specifies that an injector should retrieve a dependency from any injector until reaching the
496 * host element of the current component. (Only used with Element Injector)
497 */
498 InjectFlags[InjectFlags["Host"] = 1] = "Host";
499 /** Don't ascend to ancestors of the node requesting injection. */
500 InjectFlags[InjectFlags["Self"] = 2] = "Self";
501 /** Skip the node that is requesting injection. */
502 InjectFlags[InjectFlags["SkipSelf"] = 4] = "SkipSelf";
503 /** Inject `defaultValue` instead if token not found. */
504 InjectFlags[InjectFlags["Optional"] = 8] = "Optional";
505})(InjectFlags || (InjectFlags = {}));
506
507/**
508 * @license
509 * Copyright Google LLC All Rights Reserved.
510 *
511 * Use of this source code is governed by an MIT-style license that can be
512 * found in the LICENSE file at https://angular.io/license
513 */
514/**
515 * Current implementation of inject.
516 *
517 * By default, it is `injectInjectorOnly`, which makes it `Injector`-only aware. It can be changed
518 * to `directiveInject`, which brings in the `NodeInjector` system of ivy. It is designed this
519 * way for two reasons:
520 * 1. `Injector` should not depend on ivy logic.
521 * 2. To maintain tree shake-ability we don't want to bring in unnecessary code.
522 */
523let _injectImplementation;
524function getInjectImplementation() {
525 return _injectImplementation;
526}
527/**
528 * Sets the current inject implementation.
529 */
530function setInjectImplementation(impl) {
531 const previous = _injectImplementation;
532 _injectImplementation = impl;
533 return previous;
534}
535/**
536 * Injects `root` tokens in limp mode.
537 *
538 * If no injector exists, we can still inject tree-shakable providers which have `providedIn` set to
539 * `"root"`. This is known as the limp mode injection. In such case the value is stored in the
540 * injectable definition.
541 */
542function injectRootLimpMode(token, notFoundValue, flags) {
543 const injectableDef = getInjectableDef(token);
544 if (injectableDef && injectableDef.providedIn == 'root') {
545 return injectableDef.value === undefined ? injectableDef.value = injectableDef.factory() :
546 injectableDef.value;
547 }
548 if (flags & InjectFlags.Optional)
549 return null;
550 if (notFoundValue !== undefined)
551 return notFoundValue;
552 throwProviderNotFoundError(stringify(token), 'Injector');
553}
554/**
555 * Assert that `_injectImplementation` is not `fn`.
556 *
557 * This is useful, to prevent infinite recursion.
558 *
559 * @param fn Function which it should not equal to
560 */
561function assertInjectImplementationNotEqual(fn) {
562 ngDevMode &&
563 assertNotEqual(_injectImplementation, fn, 'Calling ɵɵinject would cause infinite recursion');
564}
565
566/**
567 * @license
568 * Copyright Google LLC All Rights Reserved.
569 *
570 * Use of this source code is governed by an MIT-style license that can be
571 * found in the LICENSE file at https://angular.io/license
572 */
573/**
574 * Convince closure compiler that the wrapped function has no side-effects.
575 *
576 * Closure compiler always assumes that `toString` has no side-effects. We use this quirk to
577 * allow us to execute a function but have closure compiler mark the call as no-side-effects.
578 * It is important that the return value for the `noSideEffects` function be assigned
579 * to something which is retained otherwise the call to `noSideEffects` will be removed by closure
580 * compiler.
581 */
582function noSideEffects(fn) {
583 return { toString: fn }.toString();
584}
585
586/**
587 * @license
588 * Copyright Google LLC All Rights Reserved.
589 *
590 * Use of this source code is governed by an MIT-style license that can be
591 * found in the LICENSE file at https://angular.io/license
592 */
593/**
594 * The strategy that the default change detector uses to detect changes.
595 * When set, takes effect the next time change detection is triggered.
596 *
597 * @see {@link ChangeDetectorRef#usage-notes Change detection usage}
598 *
599 * @publicApi
600 */
601var ChangeDetectionStrategy;
602(function (ChangeDetectionStrategy) {
603 /**
604 * Use the `CheckOnce` strategy, meaning that automatic change detection is deactivated
605 * until reactivated by setting the strategy to `Default` (`CheckAlways`).
606 * Change detection can still be explicitly invoked.
607 * This strategy applies to all child directives and cannot be overridden.
608 */
609 ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
610 /**
611 * Use the default `CheckAlways` strategy, in which change detection is automatic until
612 * explicitly deactivated.
613 */
614 ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
615})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
616/**
617 * Defines the possible states of the default change detector.
618 * @see `ChangeDetectorRef`
619 */
620var ChangeDetectorStatus;
621(function (ChangeDetectorStatus) {
622 /**
623 * A state in which, after calling `detectChanges()`, the change detector
624 * state becomes `Checked`, and must be explicitly invoked or reactivated.
625 */
626 ChangeDetectorStatus[ChangeDetectorStatus["CheckOnce"] = 0] = "CheckOnce";
627 /**
628 * A state in which change detection is skipped until the change detector mode
629 * becomes `CheckOnce`.
630 */
631 ChangeDetectorStatus[ChangeDetectorStatus["Checked"] = 1] = "Checked";
632 /**
633 * A state in which change detection continues automatically until explicitly
634 * deactivated.
635 */
636 ChangeDetectorStatus[ChangeDetectorStatus["CheckAlways"] = 2] = "CheckAlways";
637 /**
638 * A state in which a change detector sub tree is not a part of the main tree and
639 * should be skipped.
640 */
641 ChangeDetectorStatus[ChangeDetectorStatus["Detached"] = 3] = "Detached";
642 /**
643 * Indicates that the change detector encountered an error checking a binding
644 * or calling a directive lifecycle method and is now in an inconsistent state. Change
645 * detectors in this state do not detect changes.
646 */
647 ChangeDetectorStatus[ChangeDetectorStatus["Errored"] = 4] = "Errored";
648 /**
649 * Indicates that the change detector has been destroyed.
650 */
651 ChangeDetectorStatus[ChangeDetectorStatus["Destroyed"] = 5] = "Destroyed";
652})(ChangeDetectorStatus || (ChangeDetectorStatus = {}));
653/**
654 * Reports whether a given strategy is currently the default for change detection.
655 * @param changeDetectionStrategy The strategy to check.
656 * @returns True if the given strategy is the current default, false otherwise.
657 * @see `ChangeDetectorStatus`
658 * @see `ChangeDetectorRef`
659 */
660function isDefaultChangeDetectionStrategy(changeDetectionStrategy) {
661 return changeDetectionStrategy == null ||
662 changeDetectionStrategy === ChangeDetectionStrategy.Default;
663}
664
665/**
666 * @license
667 * Copyright Google LLC All Rights Reserved.
668 *
669 * Use of this source code is governed by an MIT-style license that can be
670 * found in the LICENSE file at https://angular.io/license
671 */
672/**
673 * Defines template and style encapsulation options available for Component's {@link Component}.
674 *
675 * See {@link Component#encapsulation encapsulation}.
676 *
677 * @usageNotes
678 * ### Example
679 *
680 * {@example core/ts/metadata/encapsulation.ts region='longform'}
681 *
682 * @publicApi
683 */
684var ViewEncapsulation$1;
685(function (ViewEncapsulation) {
686 // TODO: consider making `ViewEncapsulation` a `const enum` instead. See
687 // https://github.com/angular/angular/issues/44119 for additional information.
688 /**
689 * Emulate `Native` scoping of styles by adding an attribute containing surrogate id to the Host
690 * Element and pre-processing the style rules provided via {@link Component#styles styles} or
691 * {@link Component#styleUrls styleUrls}, and adding the new Host Element attribute to all
692 * selectors.
693 *
694 * This is the default option.
695 */
696 ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
697 // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.
698 /**
699 * Don't provide any template or style encapsulation.
700 */
701 ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
702 /**
703 * Use Shadow DOM to encapsulate styles.
704 *
705 * For the DOM this means using modern [Shadow
706 * DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM) and
707 * creating a ShadowRoot for Component's Host Element.
708 */
709 ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
710})(ViewEncapsulation$1 || (ViewEncapsulation$1 = {}));
711
712/**
713 * @license
714 * Copyright Google LLC All Rights Reserved.
715 *
716 * Use of this source code is governed by an MIT-style license that can be
717 * found in the LICENSE file at https://angular.io/license
718 */
719const __globalThis = typeof globalThis !== 'undefined' && globalThis;
720const __window = typeof window !== 'undefined' && window;
721const __self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' &&
722 self instanceof WorkerGlobalScope && self;
723const __global = typeof global !== 'undefined' && global;
724// Always use __globalThis if available, which is the spec-defined global variable across all
725// environments, then fallback to __global first, because in Node tests both __global and
726// __window may be defined and _global should be __global in that case.
727const _global = __globalThis || __global || __window || __self;
728
729/**
730 * @license
731 * Copyright Google LLC All Rights Reserved.
732 *
733 * Use of this source code is governed by an MIT-style license that can be
734 * found in the LICENSE file at https://angular.io/license
735 */
736function ngDevModeResetPerfCounters() {
737 const locationString = typeof location !== 'undefined' ? location.toString() : '';
738 const newCounters = {
739 namedConstructors: locationString.indexOf('ngDevMode=namedConstructors') != -1,
740 firstCreatePass: 0,
741 tNode: 0,
742 tView: 0,
743 rendererCreateTextNode: 0,
744 rendererSetText: 0,
745 rendererCreateElement: 0,
746 rendererAddEventListener: 0,
747 rendererSetAttribute: 0,
748 rendererRemoveAttribute: 0,
749 rendererSetProperty: 0,
750 rendererSetClassName: 0,
751 rendererAddClass: 0,
752 rendererRemoveClass: 0,
753 rendererSetStyle: 0,
754 rendererRemoveStyle: 0,
755 rendererDestroy: 0,
756 rendererDestroyNode: 0,
757 rendererMoveNode: 0,
758 rendererRemoveNode: 0,
759 rendererAppendChild: 0,
760 rendererInsertBefore: 0,
761 rendererCreateComment: 0,
762 };
763 // Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
764 const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
765 _global['ngDevMode'] = allowNgDevModeTrue && newCounters;
766 return newCounters;
767}
768/**
769 * This function checks to see if the `ngDevMode` has been set. If yes,
770 * then we honor it, otherwise we default to dev mode with additional checks.
771 *
772 * The idea is that unless we are doing production build where we explicitly
773 * set `ngDevMode == false` we should be helping the developer by providing
774 * as much early warning and errors as possible.
775 *
776 * `ɵɵdefineComponent` is guaranteed to have been called before any component template functions
777 * (and thus Ivy instructions), so a single initialization there is sufficient to ensure ngDevMode
778 * is defined for the entire instruction set.
779 *
780 * When checking `ngDevMode` on toplevel, always init it before referencing it
781 * (e.g. `((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode())`), otherwise you can
782 * get a `ReferenceError` like in https://github.com/angular/angular/issues/31595.
783 *
784 * Details on possible values for `ngDevMode` can be found on its docstring.
785 *
786 * NOTE:
787 * - changes to the `ngDevMode` name must be synced with `compiler-cli/src/tooling.ts`.
788 */
789function initNgDevMode() {
790 // The below checks are to ensure that calling `initNgDevMode` multiple times does not
791 // reset the counters.
792 // If the `ngDevMode` is not an object, then it means we have not created the perf counters
793 // yet.
794 if (typeof ngDevMode === 'undefined' || ngDevMode) {
795 if (typeof ngDevMode !== 'object') {
796 ngDevModeResetPerfCounters();
797 }
798 return typeof ngDevMode !== 'undefined' && !!ngDevMode;
799 }
800 return false;
801}
802
803/**
804 * @license
805 * Copyright Google LLC All Rights Reserved.
806 *
807 * Use of this source code is governed by an MIT-style license that can be
808 * found in the LICENSE file at https://angular.io/license
809 */
810/**
811 * This file contains reuseable "empty" symbols that can be used as default return values
812 * in different parts of the rendering code. Because the same symbols are returned, this
813 * allows for identity checks against these values to be consistently used by the framework
814 * code.
815 */
816const EMPTY_OBJ = {};
817const EMPTY_ARRAY = [];
818// freezing the values prevents any code from accidentally inserting new values in
819if ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) {
820 // These property accesses can be ignored because ngDevMode will be set to false
821 // when optimizing code and the whole if statement will be dropped.
822 // tslint:disable-next-line:no-toplevel-property-access
823 Object.freeze(EMPTY_OBJ);
824 // tslint:disable-next-line:no-toplevel-property-access
825 Object.freeze(EMPTY_ARRAY);
826}
827
828/**
829 * @license
830 * Copyright Google LLC All Rights Reserved.
831 *
832 * Use of this source code is governed by an MIT-style license that can be
833 * found in the LICENSE file at https://angular.io/license
834 */
835const NG_COMP_DEF = getClosureSafeProperty({ ɵcmp: getClosureSafeProperty });
836const NG_DIR_DEF = getClosureSafeProperty({ ɵdir: getClosureSafeProperty });
837const NG_PIPE_DEF = getClosureSafeProperty({ ɵpipe: getClosureSafeProperty });
838const NG_MOD_DEF = getClosureSafeProperty({ ɵmod: getClosureSafeProperty });
839const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty });
840/**
841 * If a directive is diPublic, bloomAdd sets a property on the type with this constant as
842 * the key and the directive's unique ID as the value. This allows us to map directives to their
843 * bloom filter bit for DI.
844 */
845// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
846const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
847
848/**
849 * @license
850 * Copyright Google LLC All Rights Reserved.
851 *
852 * Use of this source code is governed by an MIT-style license that can be
853 * found in the LICENSE file at https://angular.io/license
854 */
855let _renderCompCount$1 = 0;
856/**
857 * Create a component definition object.
858 *
859 *
860 * # Example
861 * ```
862 * class MyDirective {
863 * // Generated by Angular Template Compiler
864 * // [Symbol] syntax will not be supported by TypeScript until v2.7
865 * static ɵcmp = defineComponent({
866 * ...
867 * });
868 * }
869 * ```
870 * @codeGenApi
871 */
872function ɵɵdefineComponent(componentDefinition) {
873 return noSideEffects(() => {
874 // Initialize ngDevMode. This must be the first statement in ɵɵdefineComponent.
875 // See the `initNgDevMode` docstring for more information.
876 (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
877 const type = componentDefinition.type;
878 const declaredInputs = {};
879 const def = {
880 type: type,
881 providersResolver: null,
882 decls: componentDefinition.decls,
883 vars: componentDefinition.vars,
884 factory: null,
885 template: componentDefinition.template || null,
886 consts: componentDefinition.consts || null,
887 ngContentSelectors: componentDefinition.ngContentSelectors,
888 hostBindings: componentDefinition.hostBindings || null,
889 hostVars: componentDefinition.hostVars || 0,
890 hostAttrs: componentDefinition.hostAttrs || null,
891 contentQueries: componentDefinition.contentQueries || null,
892 declaredInputs: declaredInputs,
893 inputs: null,
894 outputs: null,
895 exportAs: componentDefinition.exportAs || null,
896 onPush: componentDefinition.changeDetection === ChangeDetectionStrategy.OnPush,
897 directiveDefs: null,
898 pipeDefs: null,
899 selectors: componentDefinition.selectors || EMPTY_ARRAY,
900 viewQuery: componentDefinition.viewQuery || null,
901 features: componentDefinition.features || null,
902 data: componentDefinition.data || {},
903 encapsulation: componentDefinition.encapsulation || ViewEncapsulation$1.Emulated,
904 id: 'c',
905 styles: componentDefinition.styles || EMPTY_ARRAY,
906 _: null,
907 setInput: null,
908 schemas: componentDefinition.schemas || null,
909 tView: null,
910 };
911 const directiveTypes = componentDefinition.directives;
912 const feature = componentDefinition.features;
913 const pipeTypes = componentDefinition.pipes;
914 def.id += _renderCompCount$1++;
915 def.inputs = invertObject(componentDefinition.inputs, declaredInputs),
916 def.outputs = invertObject(componentDefinition.outputs),
917 feature && feature.forEach((fn) => fn(def));
918 def.directiveDefs = directiveTypes ?
919 () => (typeof directiveTypes === 'function' ? directiveTypes() : directiveTypes)
920 .map(extractDirectiveDef) :
921 null;
922 def.pipeDefs = pipeTypes ?
923 () => (typeof pipeTypes === 'function' ? pipeTypes() : pipeTypes).map(extractPipeDef) :
924 null;
925 return def;
926 });
927}
928/**
929 * Generated next to NgModules to monkey-patch directive and pipe references onto a component's
930 * definition, when generating a direct reference in the component file would otherwise create an
931 * import cycle.
932 *
933 * See [this explanation](https://hackmd.io/Odw80D0pR6yfsOjg_7XCJg?view) for more details.
934 *
935 * @codeGenApi
936 */
937function ɵɵsetComponentScope(type, directives, pipes) {
938 const def = type.ɵcmp;
939 def.directiveDefs = () => directives.map(extractDirectiveDef);
940 def.pipeDefs = () => pipes.map(extractPipeDef);
941}
942function extractDirectiveDef(type) {
943 const def = getComponentDef(type) || getDirectiveDef(type);
944 if (ngDevMode && !def) {
945 throw new Error(`'${type.name}' is neither 'ComponentType' or 'DirectiveType'.`);
946 }
947 return def;
948}
949function extractPipeDef(type) {
950 const def = getPipeDef$1(type);
951 if (ngDevMode && !def) {
952 throw new Error(`'${type.name}' is not a 'PipeType'.`);
953 }
954 return def;
955}
956const autoRegisterModuleById = {};
957/**
958 * @codeGenApi
959 */
960function ɵɵdefineNgModule(def) {
961 return noSideEffects(() => {
962 const res = {
963 type: def.type,
964 bootstrap: def.bootstrap || EMPTY_ARRAY,
965 declarations: def.declarations || EMPTY_ARRAY,
966 imports: def.imports || EMPTY_ARRAY,
967 exports: def.exports || EMPTY_ARRAY,
968 transitiveCompileScopes: null,
969 schemas: def.schemas || null,
970 id: def.id || null,
971 };
972 if (def.id != null) {
973 autoRegisterModuleById[def.id] = def.type;
974 }
975 return res;
976 });
977}
978/**
979 * Adds the module metadata that is necessary to compute the module's transitive scope to an
980 * existing module definition.
981 *
982 * Scope metadata of modules is not used in production builds, so calls to this function can be
983 * marked pure to tree-shake it from the bundle, allowing for all referenced declarations
984 * to become eligible for tree-shaking as well.
985 *
986 * @codeGenApi
987 */
988function ɵɵsetNgModuleScope(type, scope) {
989 return noSideEffects(() => {
990 const ngModuleDef = getNgModuleDef(type, true);
991 ngModuleDef.declarations = scope.declarations || EMPTY_ARRAY;
992 ngModuleDef.imports = scope.imports || EMPTY_ARRAY;
993 ngModuleDef.exports = scope.exports || EMPTY_ARRAY;
994 });
995}
996/**
997 * Inverts an inputs or outputs lookup such that the keys, which were the
998 * minified keys, are part of the values, and the values are parsed so that
999 * the publicName of the property is the new key
1000 *
1001 * e.g. for
1002 *
1003 * ```
1004 * class Comp {
1005 * @Input()
1006 * propName1: string;
1007 *
1008 * @Input('publicName2')
1009 * declaredPropName2: number;
1010 * }
1011 * ```
1012 *
1013 * will be serialized as
1014 *
1015 * ```
1016 * {
1017 * propName1: 'propName1',
1018 * declaredPropName2: ['publicName2', 'declaredPropName2'],
1019 * }
1020 * ```
1021 *
1022 * which is than translated by the minifier as:
1023 *
1024 * ```
1025 * {
1026 * minifiedPropName1: 'propName1',
1027 * minifiedPropName2: ['publicName2', 'declaredPropName2'],
1028 * }
1029 * ```
1030 *
1031 * becomes: (public name => minifiedName)
1032 *
1033 * ```
1034 * {
1035 * 'propName1': 'minifiedPropName1',
1036 * 'publicName2': 'minifiedPropName2',
1037 * }
1038 * ```
1039 *
1040 * Optionally the function can take `secondary` which will result in: (public name => declared name)
1041 *
1042 * ```
1043 * {
1044 * 'propName1': 'propName1',
1045 * 'publicName2': 'declaredPropName2',
1046 * }
1047 * ```
1048 *
1049
1050 */
1051function invertObject(obj, secondary) {
1052 if (obj == null)
1053 return EMPTY_OBJ;
1054 const newLookup = {};
1055 for (const minifiedKey in obj) {
1056 if (obj.hasOwnProperty(minifiedKey)) {
1057 let publicName = obj[minifiedKey];
1058 let declaredName = publicName;
1059 if (Array.isArray(publicName)) {
1060 declaredName = publicName[1];
1061 publicName = publicName[0];
1062 }
1063 newLookup[publicName] = minifiedKey;
1064 if (secondary) {
1065 (secondary[publicName] = declaredName);
1066 }
1067 }
1068 }
1069 return newLookup;
1070}
1071/**
1072 * Create a directive definition object.
1073 *
1074 * # Example
1075 * ```ts
1076 * class MyDirective {
1077 * // Generated by Angular Template Compiler
1078 * // [Symbol] syntax will not be supported by TypeScript until v2.7
1079 * static ɵdir = ɵɵdefineDirective({
1080 * ...
1081 * });
1082 * }
1083 * ```
1084 *
1085 * @codeGenApi
1086 */
1087const ɵɵdefineDirective = ɵɵdefineComponent;
1088/**
1089 * Create a pipe definition object.
1090 *
1091 * # Example
1092 * ```
1093 * class MyPipe implements PipeTransform {
1094 * // Generated by Angular Template Compiler
1095 * static ɵpipe = definePipe({
1096 * ...
1097 * });
1098 * }
1099 * ```
1100 * @param pipeDef Pipe definition generated by the compiler
1101 *
1102 * @codeGenApi
1103 */
1104function ɵɵdefinePipe(pipeDef) {
1105 return {
1106 type: pipeDef.type,
1107 name: pipeDef.name,
1108 factory: null,
1109 pure: pipeDef.pure !== false,
1110 onDestroy: pipeDef.type.prototype.ngOnDestroy || null
1111 };
1112}
1113/**
1114 * The following getter methods retrieve the definition from the type. Currently the retrieval
1115 * honors inheritance, but in the future we may change the rule to require that definitions are
1116 * explicit. This would require some sort of migration strategy.
1117 */
1118function getComponentDef(type) {
1119 return type[NG_COMP_DEF] || null;
1120}
1121function getDirectiveDef(type) {
1122 return type[NG_DIR_DEF] || null;
1123}
1124function getPipeDef$1(type) {
1125 return type[NG_PIPE_DEF] || null;
1126}
1127function getNgModuleDef(type, throwNotFound) {
1128 const ngModuleDef = type[NG_MOD_DEF] || null;
1129 if (!ngModuleDef && throwNotFound === true) {
1130 throw new Error(`Type ${stringify(type)} does not have 'ɵmod' property.`);
1131 }
1132 return ngModuleDef;
1133}
1134
1135/**
1136 * @license
1137 * Copyright Google LLC All Rights Reserved.
1138 *
1139 * Use of this source code is governed by an MIT-style license that can be
1140 * found in the LICENSE file at https://angular.io/license
1141 */
1142// Below are constants for LView indices to help us look up LView members
1143// without having to remember the specific indices.
1144// Uglify will inline these when minifying so there shouldn't be a cost.
1145const HOST = 0;
1146const TVIEW = 1;
1147const FLAGS = 2;
1148const PARENT = 3;
1149const NEXT = 4;
1150const TRANSPLANTED_VIEWS_TO_REFRESH = 5;
1151const T_HOST = 6;
1152const CLEANUP = 7;
1153const CONTEXT = 8;
1154const INJECTOR$1 = 9;
1155const RENDERER_FACTORY = 10;
1156const RENDERER = 11;
1157const SANITIZER = 12;
1158const CHILD_HEAD = 13;
1159const CHILD_TAIL = 14;
1160// FIXME(misko): Investigate if the three declarations aren't all same thing.
1161const DECLARATION_VIEW = 15;
1162const DECLARATION_COMPONENT_VIEW = 16;
1163const DECLARATION_LCONTAINER = 17;
1164const PREORDER_HOOK_FLAGS = 18;
1165const QUERIES = 19;
1166/**
1167 * Size of LView's header. Necessary to adjust for it when setting slots.
1168 *
1169 * IMPORTANT: `HEADER_OFFSET` should only be referred to the in the `ɵɵ*` instructions to translate
1170 * instruction index into `LView` index. All other indexes should be in the `LView` index space and
1171 * there should be no need to refer to `HEADER_OFFSET` anywhere else.
1172 */
1173const HEADER_OFFSET = 20;
1174/**
1175 * Converts `TViewType` into human readable text.
1176 * Make sure this matches with `TViewType`
1177 */
1178const TViewTypeAsString = [
1179 'Root',
1180 'Component',
1181 'Embedded', // 2
1182];
1183// Note: This hack is necessary so we don't erroneously get a circular dependency
1184// failure based on types.
1185const unusedValueExportToPlacateAjd$8 = 1;
1186
1187/**
1188 * @license
1189 * Copyright Google LLC All Rights Reserved.
1190 *
1191 * Use of this source code is governed by an MIT-style license that can be
1192 * found in the LICENSE file at https://angular.io/license
1193 */
1194/**
1195 * Special location which allows easy identification of type. If we have an array which was
1196 * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is
1197 * `LContainer`.
1198 */
1199const TYPE = 1;
1200/**
1201 * Below are constants for LContainer indices to help us look up LContainer members
1202 * without having to remember the specific indices.
1203 * Uglify will inline these when minifying so there shouldn't be a cost.
1204 */
1205/**
1206 * Flag to signify that this `LContainer` may have transplanted views which need to be change
1207 * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.
1208 *
1209 * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip
1210 * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify
1211 * that the `MOVED_VIEWS` are transplanted and on-push.
1212 */
1213const HAS_TRANSPLANTED_VIEWS = 2;
1214// PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5
1215// As we already have these constants in LView, we don't need to re-create them.
1216// T_HOST is index 6
1217// We already have this constants in LView, we don't need to re-create it.
1218const NATIVE = 7;
1219const VIEW_REFS = 8;
1220const MOVED_VIEWS = 9;
1221/**
1222 * Size of LContainer's header. Represents the index after which all views in the
1223 * container will be inserted. We need to keep a record of current views so we know
1224 * which views are already in the DOM (and don't need to be re-added) and so we can
1225 * remove views from the DOM when they are no longer required.
1226 */
1227const CONTAINER_HEADER_OFFSET = 10;
1228// Note: This hack is necessary so we don't erroneously get a circular dependency
1229// failure based on types.
1230const unusedValueExportToPlacateAjd$7 = 1;
1231
1232/**
1233 * @license
1234 * Copyright Google LLC All Rights Reserved.
1235 *
1236 * Use of this source code is governed by an MIT-style license that can be
1237 * found in the LICENSE file at https://angular.io/license
1238 */
1239/**
1240 * True if `value` is `LView`.
1241 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1242 */
1243function isLView(value) {
1244 return Array.isArray(value) && typeof value[TYPE] === 'object';
1245}
1246/**
1247 * True if `value` is `LContainer`.
1248 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1249 */
1250function isLContainer(value) {
1251 return Array.isArray(value) && value[TYPE] === true;
1252}
1253function isContentQueryHost(tNode) {
1254 return (tNode.flags & 8 /* hasContentQuery */) !== 0;
1255}
1256function isComponentHost(tNode) {
1257 return (tNode.flags & 2 /* isComponentHost */) === 2 /* isComponentHost */;
1258}
1259function isDirectiveHost(tNode) {
1260 return (tNode.flags & 1 /* isDirectiveHost */) === 1 /* isDirectiveHost */;
1261}
1262function isComponentDef(def) {
1263 return def.template !== null;
1264}
1265function isRootView(target) {
1266 return (target[FLAGS] & 512 /* IsRoot */) !== 0;
1267}
1268
1269/**
1270 * @license
1271 * Copyright Google LLC All Rights Reserved.
1272 *
1273 * Use of this source code is governed by an MIT-style license that can be
1274 * found in the LICENSE file at https://angular.io/license
1275 */
1276// [Assert functions do not constraint type when they are guarded by a truthy
1277// expression.](https://github.com/microsoft/TypeScript/issues/37295)
1278function assertTNodeForLView(tNode, lView) {
1279 assertTNodeForTView(tNode, lView[TVIEW]);
1280}
1281function assertTNodeForTView(tNode, tView) {
1282 assertTNode(tNode);
1283 tNode.hasOwnProperty('tView_') &&
1284 assertEqual(tNode.tView_, tView, 'This TNode does not belong to this TView.');
1285}
1286function assertTNode(tNode) {
1287 assertDefined(tNode, 'TNode must be defined');
1288 if (!(tNode && typeof tNode === 'object' && tNode.hasOwnProperty('directiveStylingLast'))) {
1289 throwError('Not of type TNode, got: ' + tNode);
1290 }
1291}
1292function assertTIcu(tIcu) {
1293 assertDefined(tIcu, 'Expected TIcu to be defined');
1294 if (!(typeof tIcu.currentCaseLViewIndex === 'number')) {
1295 throwError('Object is not of TIcu type.');
1296 }
1297}
1298function assertComponentType(actual, msg = 'Type passed in is not ComponentType, it does not have \'ɵcmp\' property.') {
1299 if (!getComponentDef(actual)) {
1300 throwError(msg);
1301 }
1302}
1303function assertNgModuleType(actual, msg = 'Type passed in is not NgModuleType, it does not have \'ɵmod\' property.') {
1304 if (!getNgModuleDef(actual)) {
1305 throwError(msg);
1306 }
1307}
1308function assertCurrentTNodeIsParent(isParent) {
1309 assertEqual(isParent, true, 'currentTNode should be a parent');
1310}
1311function assertHasParent(tNode) {
1312 assertDefined(tNode, 'currentTNode should exist!');
1313 assertDefined(tNode.parent, 'currentTNode should have a parent');
1314}
1315function assertDataNext(lView, index, arr) {
1316 if (arr == null)
1317 arr = lView;
1318 assertEqual(arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
1319}
1320function assertLContainer(value) {
1321 assertDefined(value, 'LContainer must be defined');
1322 assertEqual(isLContainer(value), true, 'Expecting LContainer');
1323}
1324function assertLViewOrUndefined(value) {
1325 value && assertEqual(isLView(value), true, 'Expecting LView or undefined or null');
1326}
1327function assertLView(value) {
1328 assertDefined(value, 'LView must be defined');
1329 assertEqual(isLView(value), true, 'Expecting LView');
1330}
1331function assertFirstCreatePass(tView, errMessage) {
1332 assertEqual(tView.firstCreatePass, true, errMessage || 'Should only be called in first create pass.');
1333}
1334function assertFirstUpdatePass(tView, errMessage) {
1335 assertEqual(tView.firstUpdatePass, true, errMessage || 'Should only be called in first update pass.');
1336}
1337/**
1338 * This is a basic sanity check that an object is probably a directive def. DirectiveDef is
1339 * an interface, so we can't do a direct instanceof check.
1340 */
1341function assertDirectiveDef(obj) {
1342 if (obj.type === undefined || obj.selectors == undefined || obj.inputs === undefined) {
1343 throwError(`Expected a DirectiveDef/ComponentDef and this object does not seem to have the expected shape.`);
1344 }
1345}
1346function assertIndexInDeclRange(lView, index) {
1347 const tView = lView[1];
1348 assertBetween(HEADER_OFFSET, tView.bindingStartIndex, index);
1349}
1350function assertIndexInVarsRange(lView, index) {
1351 const tView = lView[1];
1352 assertBetween(tView.bindingStartIndex, tView.expandoStartIndex, index);
1353}
1354function assertIndexInExpandoRange(lView, index) {
1355 const tView = lView[1];
1356 assertBetween(tView.expandoStartIndex, lView.length, index);
1357}
1358function assertBetween(lower, upper, index) {
1359 if (!(lower <= index && index < upper)) {
1360 throwError(`Index out of range (expecting ${lower} <= ${index} < ${upper})`);
1361 }
1362}
1363function assertProjectionSlots(lView, errMessage) {
1364 assertDefined(lView[DECLARATION_COMPONENT_VIEW], 'Component views should exist.');
1365 assertDefined(lView[DECLARATION_COMPONENT_VIEW][T_HOST].projection, errMessage ||
1366 'Components with projection nodes (<ng-content>) must have projection slots defined.');
1367}
1368function assertParentView(lView, errMessage) {
1369 assertDefined(lView, errMessage || 'Component views should always have a parent view (component\'s host view)');
1370}
1371/**
1372 * This is a basic sanity check that the `injectorIndex` seems to point to what looks like a
1373 * NodeInjector data structure.
1374 *
1375 * @param lView `LView` which should be checked.
1376 * @param injectorIndex index into the `LView` where the `NodeInjector` is expected.
1377 */
1378function assertNodeInjector(lView, injectorIndex) {
1379 assertIndexInExpandoRange(lView, injectorIndex);
1380 assertIndexInExpandoRange(lView, injectorIndex + 8 /* PARENT */);
1381 assertNumber(lView[injectorIndex + 0], 'injectorIndex should point to a bloom filter');
1382 assertNumber(lView[injectorIndex + 1], 'injectorIndex should point to a bloom filter');
1383 assertNumber(lView[injectorIndex + 2], 'injectorIndex should point to a bloom filter');
1384 assertNumber(lView[injectorIndex + 3], 'injectorIndex should point to a bloom filter');
1385 assertNumber(lView[injectorIndex + 4], 'injectorIndex should point to a bloom filter');
1386 assertNumber(lView[injectorIndex + 5], 'injectorIndex should point to a bloom filter');
1387 assertNumber(lView[injectorIndex + 6], 'injectorIndex should point to a bloom filter');
1388 assertNumber(lView[injectorIndex + 7], 'injectorIndex should point to a bloom filter');
1389 assertNumber(lView[injectorIndex + 8 /* PARENT */], 'injectorIndex should point to parent injector');
1390}
1391
1392/**
1393 * @license
1394 * Copyright Google LLC All Rights Reserved.
1395 *
1396 * Use of this source code is governed by an MIT-style license that can be
1397 * found in the LICENSE file at https://angular.io/license
1398 */
1399function getFactoryDef(type, throwNotFound) {
1400 const hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF);
1401 if (!hasFactoryDef && throwNotFound === true && ngDevMode) {
1402 throw new Error(`Type ${stringify(type)} does not have 'ɵfac' property.`);
1403 }
1404 return hasFactoryDef ? type[NG_FACTORY_DEF] : null;
1405}
1406
1407/**
1408 * @license
1409 * Copyright Google LLC All Rights Reserved.
1410 *
1411 * Use of this source code is governed by an MIT-style license that can be
1412 * found in the LICENSE file at https://angular.io/license
1413 */
1414/**
1415 * Represents a basic change from a previous to a new value for a single
1416 * property on a directive instance. Passed as a value in a
1417 * {@link SimpleChanges} object to the `ngOnChanges` hook.
1418 *
1419 * @see `OnChanges`
1420 *
1421 * @publicApi
1422 */
1423class SimpleChange {
1424 constructor(previousValue, currentValue, firstChange) {
1425 this.previousValue = previousValue;
1426 this.currentValue = currentValue;
1427 this.firstChange = firstChange;
1428 }
1429 /**
1430 * Check whether the new value is the first value assigned.
1431 */
1432 isFirstChange() {
1433 return this.firstChange;
1434 }
1435}
1436
1437/**
1438 * @license
1439 * Copyright Google LLC All Rights Reserved.
1440 *
1441 * Use of this source code is governed by an MIT-style license that can be
1442 * found in the LICENSE file at https://angular.io/license
1443 */
1444/**
1445 * The NgOnChangesFeature decorates a component with support for the ngOnChanges
1446 * lifecycle hook, so it should be included in any component that implements
1447 * that hook.
1448 *
1449 * If the component or directive uses inheritance, the NgOnChangesFeature MUST
1450 * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
1451 * inherited properties will not be propagated to the ngOnChanges lifecycle
1452 * hook.
1453 *
1454 * Example usage:
1455 *
1456 * ```
1457 * static ɵcmp = defineComponent({
1458 * ...
1459 * inputs: {name: 'publicName'},
1460 * features: [NgOnChangesFeature]
1461 * });
1462 * ```
1463 *
1464 * @codeGenApi
1465 */
1466function ɵɵNgOnChangesFeature() {
1467 return NgOnChangesFeatureImpl;
1468}
1469function NgOnChangesFeatureImpl(definition) {
1470 if (definition.type.prototype.ngOnChanges) {
1471 definition.setInput = ngOnChangesSetInput;
1472 }
1473 return rememberChangeHistoryAndInvokeOnChangesHook;
1474}
1475// This option ensures that the ngOnChanges lifecycle hook will be inherited
1476// from superclasses (in InheritDefinitionFeature).
1477/** @nocollapse */
1478// tslint:disable-next-line:no-toplevel-property-access
1479ɵɵNgOnChangesFeature.ngInherit = true;
1480/**
1481 * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
1482 * `ngOnChanges`.
1483 *
1484 * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
1485 * found it invokes `ngOnChanges` on the component instance.
1486 *
1487 * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
1488 * it is guaranteed to be called with component instance.
1489 */
1490function rememberChangeHistoryAndInvokeOnChangesHook() {
1491 const simpleChangesStore = getSimpleChangesStore(this);
1492 const current = simpleChangesStore?.current;
1493 if (current) {
1494 const previous = simpleChangesStore.previous;
1495 if (previous === EMPTY_OBJ) {
1496 simpleChangesStore.previous = current;
1497 }
1498 else {
1499 // New changes are copied to the previous store, so that we don't lose history for inputs
1500 // which were not changed this time
1501 for (let key in current) {
1502 previous[key] = current[key];
1503 }
1504 }
1505 simpleChangesStore.current = null;
1506 this.ngOnChanges(current);
1507 }
1508}
1509function ngOnChangesSetInput(instance, value, publicName, privateName) {
1510 const simpleChangesStore = getSimpleChangesStore(instance) ||
1511 setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
1512 const current = simpleChangesStore.current || (simpleChangesStore.current = {});
1513 const previous = simpleChangesStore.previous;
1514 const declaredName = this.declaredInputs[publicName];
1515 const previousChange = previous[declaredName];
1516 current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
1517 instance[privateName] = value;
1518}
1519const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';
1520function getSimpleChangesStore(instance) {
1521 return instance[SIMPLE_CHANGES_STORE] || null;
1522}
1523function setSimpleChangesStore(instance, store) {
1524 return instance[SIMPLE_CHANGES_STORE] = store;
1525}
1526
1527/**
1528 * @license
1529 * Copyright Google LLC All Rights Reserved.
1530 *
1531 * Use of this source code is governed by an MIT-style license that can be
1532 * found in the LICENSE file at https://angular.io/license
1533 */
1534let profilerCallback = null;
1535/**
1536 * Sets the callback function which will be invoked before and after performing certain actions at
1537 * runtime (for example, before and after running change detection).
1538 *
1539 * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
1540 * The contract of the function might be changed in any release and/or the function can be removed
1541 * completely.
1542 *
1543 * @param profiler function provided by the caller or null value to disable profiling.
1544 */
1545const setProfiler = (profiler) => {
1546 profilerCallback = profiler;
1547};
1548/**
1549 * Profiler function which wraps user code executed by the runtime.
1550 *
1551 * @param event ProfilerEvent corresponding to the execution context
1552 * @param instance component instance
1553 * @param hookOrListener lifecycle hook function or output listener. The value depends on the
1554 * execution context
1555 * @returns
1556 */
1557const profiler = function (event, instance, hookOrListener) {
1558 if (profilerCallback != null /* both `null` and `undefined` */) {
1559 profilerCallback(event, instance, hookOrListener);
1560 }
1561};
1562
1563/**
1564 * @license
1565 * Copyright Google LLC All Rights Reserved.
1566 *
1567 * Use of this source code is governed by an MIT-style license that can be
1568 * found in the LICENSE file at https://angular.io/license
1569 */
1570const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
1571const MATH_ML_NAMESPACE = 'http://www.w3.org/1998/MathML/';
1572
1573/**
1574 * @license
1575 * Copyright Google LLC All Rights Reserved.
1576 *
1577 * Use of this source code is governed by an MIT-style license that can be
1578 * found in the LICENSE file at https://angular.io/license
1579 */
1580/**
1581 * Most of the use of `document` in Angular is from within the DI system so it is possible to simply
1582 * inject the `DOCUMENT` token and are done.
1583 *
1584 * Ivy is special because it does not rely upon the DI and must get hold of the document some other
1585 * way.
1586 *
1587 * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy.
1588 * Wherever ivy needs the global document, it calls `getDocument()` instead.
1589 *
1590 * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to
1591 * tell ivy what the global `document` is.
1592 *
1593 * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)
1594 * by calling `setDocument()` when providing the `DOCUMENT` token.
1595 */
1596let DOCUMENT = undefined;
1597/**
1598 * Tell ivy what the `document` is for this platform.
1599 *
1600 * It is only necessary to call this if the current platform is not a browser.
1601 *
1602 * @param document The object representing the global `document` in this environment.
1603 */
1604function setDocument(document) {
1605 DOCUMENT = document;
1606}
1607/**
1608 * Access the object that represents the `document` for this platform.
1609 *
1610 * Ivy calls this whenever it needs to access the `document` object.
1611 * For example to create the renderer or to do sanitization.
1612 */
1613function getDocument() {
1614 if (DOCUMENT !== undefined) {
1615 return DOCUMENT;
1616 }
1617 else if (typeof document !== 'undefined') {
1618 return document;
1619 }
1620 // No "document" can be found. This should only happen if we are running ivy outside Angular and
1621 // the current platform is not a browser. Since this is not a supported scenario at the moment
1622 // this should not happen in Angular apps.
1623 // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a
1624 // public API. Meanwhile we just return `undefined` and let the application fail.
1625 return undefined;
1626}
1627
1628/**
1629 * @license
1630 * Copyright Google LLC All Rights Reserved.
1631 *
1632 * Use of this source code is governed by an MIT-style license that can be
1633 * found in the LICENSE file at https://angular.io/license
1634 */
1635// TODO: cleanup once the code is merged in angular/angular
1636var RendererStyleFlags3;
1637(function (RendererStyleFlags3) {
1638 RendererStyleFlags3[RendererStyleFlags3["Important"] = 1] = "Important";
1639 RendererStyleFlags3[RendererStyleFlags3["DashCase"] = 2] = "DashCase";
1640})(RendererStyleFlags3 || (RendererStyleFlags3 = {}));
1641/** Returns whether the `renderer` is a `ProceduralRenderer3` */
1642function isProceduralRenderer(renderer) {
1643 return !!(renderer.listen);
1644}
1645const domRendererFactory3 = {
1646 createRenderer: (hostElement, rendererType) => {
1647 return getDocument();
1648 }
1649};
1650// Note: This hack is necessary so we don't erroneously get a circular dependency
1651// failure based on types.
1652const unusedValueExportToPlacateAjd$6 = 1;
1653
1654/**
1655 * @license
1656 * Copyright Google LLC All Rights Reserved.
1657 *
1658 * Use of this source code is governed by an MIT-style license that can be
1659 * found in the LICENSE file at https://angular.io/license
1660 */
1661/**
1662 * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
1663 * in same location in `LView`. This is because we don't want to pre-allocate space for it
1664 * because the storage is sparse. This file contains utilities for dealing with such data types.
1665 *
1666 * How do we know what is stored at a given location in `LView`.
1667 * - `Array.isArray(value) === false` => `RNode` (The normal storage value)
1668 * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
1669 * - `typeof value[TYPE] === 'object'` => `LView`
1670 * - This happens when we have a component at a given location
1671 * - `typeof value[TYPE] === true` => `LContainer`
1672 * - This happens when we have `LContainer` binding at a given location.
1673 *
1674 *
1675 * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
1676 */
1677/**
1678 * Returns `RNode`.
1679 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1680 */
1681function unwrapRNode(value) {
1682 while (Array.isArray(value)) {
1683 value = value[HOST];
1684 }
1685 return value;
1686}
1687/**
1688 * Returns `LView` or `null` if not found.
1689 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1690 */
1691function unwrapLView(value) {
1692 while (Array.isArray(value)) {
1693 // This check is same as `isLView()` but we don't call at as we don't want to call
1694 // `Array.isArray()` twice and give JITer more work for inlining.
1695 if (typeof value[TYPE] === 'object')
1696 return value;
1697 value = value[HOST];
1698 }
1699 return null;
1700}
1701/**
1702 * Returns `LContainer` or `null` if not found.
1703 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1704 */
1705function unwrapLContainer(value) {
1706 while (Array.isArray(value)) {
1707 // This check is same as `isLContainer()` but we don't call at as we don't want to call
1708 // `Array.isArray()` twice and give JITer more work for inlining.
1709 if (value[TYPE] === true)
1710 return value;
1711 value = value[HOST];
1712 }
1713 return null;
1714}
1715/**
1716 * Retrieves an element value from the provided `viewData`, by unwrapping
1717 * from any containers, component views, or style contexts.
1718 */
1719function getNativeByIndex(index, lView) {
1720 ngDevMode && assertIndexInRange(lView, index);
1721 ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
1722 return unwrapRNode(lView[index]);
1723}
1724/**
1725 * Retrieve an `RNode` for a given `TNode` and `LView`.
1726 *
1727 * This function guarantees in dev mode to retrieve a non-null `RNode`.
1728 *
1729 * @param tNode
1730 * @param lView
1731 */
1732function getNativeByTNode(tNode, lView) {
1733 ngDevMode && assertTNodeForLView(tNode, lView);
1734 ngDevMode && assertIndexInRange(lView, tNode.index);
1735 const node = unwrapRNode(lView[tNode.index]);
1736 ngDevMode && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
1737 return node;
1738}
1739/**
1740 * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
1741 *
1742 * Some `TNode`s don't have associated `RNode`s. For example `Projection`
1743 *
1744 * @param tNode
1745 * @param lView
1746 */
1747function getNativeByTNodeOrNull(tNode, lView) {
1748 const index = tNode === null ? -1 : tNode.index;
1749 if (index !== -1) {
1750 ngDevMode && assertTNodeForLView(tNode, lView);
1751 const node = unwrapRNode(lView[index]);
1752 ngDevMode && node !== null && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
1753 return node;
1754 }
1755 return null;
1756}
1757// fixme(misko): The return Type should be `TNode|null`
1758function getTNode(tView, index) {
1759 ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
1760 ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
1761 const tNode = tView.data[index];
1762 ngDevMode && tNode !== null && assertTNode(tNode);
1763 return tNode;
1764}
1765/** Retrieves a value from any `LView` or `TData`. */
1766function load(view, index) {
1767 ngDevMode && assertIndexInRange(view, index);
1768 return view[index];
1769}
1770function getComponentLViewByIndex(nodeIndex, hostView) {
1771 // Could be an LView or an LContainer. If LContainer, unwrap to find LView.
1772 ngDevMode && assertIndexInRange(hostView, nodeIndex);
1773 const slotValue = hostView[nodeIndex];
1774 const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
1775 return lView;
1776}
1777/** Checks whether a given view is in creation mode */
1778function isCreationMode(view) {
1779 return (view[FLAGS] & 4 /* CreationMode */) === 4 /* CreationMode */;
1780}
1781/**
1782 * Returns a boolean for whether the view is attached to the change detection tree.
1783 *
1784 * Note: This determines whether a view should be checked, not whether it's inserted
1785 * into a container. For that, you'll want `viewAttachedToContainer` below.
1786 */
1787function viewAttachedToChangeDetector(view) {
1788 return (view[FLAGS] & 128 /* Attached */) === 128 /* Attached */;
1789}
1790/** Returns a boolean for whether the view is attached to a container. */
1791function viewAttachedToContainer(view) {
1792 return isLContainer(view[PARENT]);
1793}
1794function getConstant(consts, index) {
1795 if (index === null || index === undefined)
1796 return null;
1797 ngDevMode && assertIndexInRange(consts, index);
1798 return consts[index];
1799}
1800/**
1801 * Resets the pre-order hook flags of the view.
1802 * @param lView the LView on which the flags are reset
1803 */
1804function resetPreOrderHookFlags(lView) {
1805 lView[PREORDER_HOOK_FLAGS] = 0;
1806}
1807/**
1808 * Updates the `TRANSPLANTED_VIEWS_TO_REFRESH` counter on the `LContainer` as well as the parents
1809 * whose
1810 * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
1811 * or
1812 * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
1813 */
1814function updateTransplantedViewCount(lContainer, amount) {
1815 lContainer[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;
1816 let viewOrContainer = lContainer;
1817 let parent = lContainer[PARENT];
1818 while (parent !== null &&
1819 ((amount === 1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 1) ||
1820 (amount === -1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 0))) {
1821 parent[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;
1822 viewOrContainer = parent;
1823 parent = parent[PARENT];
1824 }
1825}
1826
1827/**
1828 * @license
1829 * Copyright Google LLC All Rights Reserved.
1830 *
1831 * Use of this source code is governed by an MIT-style license that can be
1832 * found in the LICENSE file at https://angular.io/license
1833 */
1834const instructionState = {
1835 lFrame: createLFrame(null),
1836 bindingsEnabled: true,
1837 isInCheckNoChangesMode: false,
1838};
1839/**
1840 * Returns true if the instruction state stack is empty.
1841 *
1842 * Intended to be called from tests only (tree shaken otherwise).
1843 */
1844function specOnlyIsInstructionStateEmpty() {
1845 return instructionState.lFrame.parent === null;
1846}
1847function getElementDepthCount() {
1848 return instructionState.lFrame.elementDepthCount;
1849}
1850function increaseElementDepthCount() {
1851 instructionState.lFrame.elementDepthCount++;
1852}
1853function decreaseElementDepthCount() {
1854 instructionState.lFrame.elementDepthCount--;
1855}
1856function getBindingsEnabled() {
1857 return instructionState.bindingsEnabled;
1858}
1859/**
1860 * Enables directive matching on elements.
1861 *
1862 * * Example:
1863 * ```
1864 * <my-comp my-directive>
1865 * Should match component / directive.
1866 * </my-comp>
1867 * <div ngNonBindable>
1868 * <!-- ɵɵdisableBindings() -->
1869 * <my-comp my-directive>
1870 * Should not match component / directive because we are in ngNonBindable.
1871 * </my-comp>
1872 * <!-- ɵɵenableBindings() -->
1873 * </div>
1874 * ```
1875 *
1876 * @codeGenApi
1877 */
1878function ɵɵenableBindings() {
1879 instructionState.bindingsEnabled = true;
1880}
1881/**
1882 * Disables directive matching on element.
1883 *
1884 * * Example:
1885 * ```
1886 * <my-comp my-directive>
1887 * Should match component / directive.
1888 * </my-comp>
1889 * <div ngNonBindable>
1890 * <!-- ɵɵdisableBindings() -->
1891 * <my-comp my-directive>
1892 * Should not match component / directive because we are in ngNonBindable.
1893 * </my-comp>
1894 * <!-- ɵɵenableBindings() -->
1895 * </div>
1896 * ```
1897 *
1898 * @codeGenApi
1899 */
1900function ɵɵdisableBindings() {
1901 instructionState.bindingsEnabled = false;
1902}
1903/**
1904 * Return the current `LView`.
1905 */
1906function getLView() {
1907 return instructionState.lFrame.lView;
1908}
1909/**
1910 * Return the current `TView`.
1911 */
1912function getTView() {
1913 return instructionState.lFrame.tView;
1914}
1915/**
1916 * Restores `contextViewData` to the given OpaqueViewState instance.
1917 *
1918 * Used in conjunction with the getCurrentView() instruction to save a snapshot
1919 * of the current view and restore it when listeners are invoked. This allows
1920 * walking the declaration view tree in listeners to get vars from parent views.
1921 *
1922 * @param viewToRestore The OpaqueViewState instance to restore.
1923 * @returns Context of the restored OpaqueViewState instance.
1924 *
1925 * @codeGenApi
1926 */
1927function ɵɵrestoreView(viewToRestore) {
1928 instructionState.lFrame.contextLView = viewToRestore;
1929 return viewToRestore[CONTEXT];
1930}
1931function getCurrentTNode() {
1932 let currentTNode = getCurrentTNodePlaceholderOk();
1933 while (currentTNode !== null && currentTNode.type === 64 /* Placeholder */) {
1934 currentTNode = currentTNode.parent;
1935 }
1936 return currentTNode;
1937}
1938function getCurrentTNodePlaceholderOk() {
1939 return instructionState.lFrame.currentTNode;
1940}
1941function getCurrentParentTNode() {
1942 const lFrame = instructionState.lFrame;
1943 const currentTNode = lFrame.currentTNode;
1944 return lFrame.isParent ? currentTNode : currentTNode.parent;
1945}
1946function setCurrentTNode(tNode, isParent) {
1947 ngDevMode && tNode && assertTNodeForTView(tNode, instructionState.lFrame.tView);
1948 const lFrame = instructionState.lFrame;
1949 lFrame.currentTNode = tNode;
1950 lFrame.isParent = isParent;
1951}
1952function isCurrentTNodeParent() {
1953 return instructionState.lFrame.isParent;
1954}
1955function setCurrentTNodeAsNotParent() {
1956 instructionState.lFrame.isParent = false;
1957}
1958function setCurrentTNodeAsParent() {
1959 instructionState.lFrame.isParent = true;
1960}
1961function getContextLView() {
1962 return instructionState.lFrame.contextLView;
1963}
1964function isInCheckNoChangesMode() {
1965 // TODO(misko): remove this from the LView since it is ngDevMode=true mode only.
1966 return instructionState.isInCheckNoChangesMode;
1967}
1968function setIsInCheckNoChangesMode(mode) {
1969 instructionState.isInCheckNoChangesMode = mode;
1970}
1971// top level variables should not be exported for performance reasons (PERF_NOTES.md)
1972function getBindingRoot() {
1973 const lFrame = instructionState.lFrame;
1974 let index = lFrame.bindingRootIndex;
1975 if (index === -1) {
1976 index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex;
1977 }
1978 return index;
1979}
1980function getBindingIndex() {
1981 return instructionState.lFrame.bindingIndex;
1982}
1983function setBindingIndex(value) {
1984 return instructionState.lFrame.bindingIndex = value;
1985}
1986function nextBindingIndex() {
1987 return instructionState.lFrame.bindingIndex++;
1988}
1989function incrementBindingIndex(count) {
1990 const lFrame = instructionState.lFrame;
1991 const index = lFrame.bindingIndex;
1992 lFrame.bindingIndex = lFrame.bindingIndex + count;
1993 return index;
1994}
1995function isInI18nBlock() {
1996 return instructionState.lFrame.inI18n;
1997}
1998function setInI18nBlock(isInI18nBlock) {
1999 instructionState.lFrame.inI18n = isInI18nBlock;
2000}
2001/**
2002 * Set a new binding root index so that host template functions can execute.
2003 *
2004 * Bindings inside the host template are 0 index. But because we don't know ahead of time
2005 * how many host bindings we have we can't pre-compute them. For this reason they are all
2006 * 0 index and we just shift the root so that they match next available location in the LView.
2007 *
2008 * @param bindingRootIndex Root index for `hostBindings`
2009 * @param currentDirectiveIndex `TData[currentDirectiveIndex]` will point to the current directive
2010 * whose `hostBindings` are being processed.
2011 */
2012function setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex) {
2013 const lFrame = instructionState.lFrame;
2014 lFrame.bindingIndex = lFrame.bindingRootIndex = bindingRootIndex;
2015 setCurrentDirectiveIndex(currentDirectiveIndex);
2016}
2017/**
2018 * When host binding is executing this points to the directive index.
2019 * `TView.data[getCurrentDirectiveIndex()]` is `DirectiveDef`
2020 * `LView[getCurrentDirectiveIndex()]` is directive instance.
2021 */
2022function getCurrentDirectiveIndex() {
2023 return instructionState.lFrame.currentDirectiveIndex;
2024}
2025/**
2026 * Sets an index of a directive whose `hostBindings` are being processed.
2027 *
2028 * @param currentDirectiveIndex `TData` index where current directive instance can be found.
2029 */
2030function setCurrentDirectiveIndex(currentDirectiveIndex) {
2031 instructionState.lFrame.currentDirectiveIndex = currentDirectiveIndex;
2032}
2033/**
2034 * Retrieve the current `DirectiveDef` which is active when `hostBindings` instruction is being
2035 * executed.
2036 *
2037 * @param tData Current `TData` where the `DirectiveDef` will be looked up at.
2038 */
2039function getCurrentDirectiveDef(tData) {
2040 const currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex;
2041 return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex];
2042}
2043function getCurrentQueryIndex() {
2044 return instructionState.lFrame.currentQueryIndex;
2045}
2046function setCurrentQueryIndex(value) {
2047 instructionState.lFrame.currentQueryIndex = value;
2048}
2049/**
2050 * Returns a `TNode` of the location where the current `LView` is declared at.
2051 *
2052 * @param lView an `LView` that we want to find parent `TNode` for.
2053 */
2054function getDeclarationTNode(lView) {
2055 const tView = lView[TVIEW];
2056 // Return the declaration parent for embedded views
2057 if (tView.type === 2 /* Embedded */) {
2058 ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');
2059 return tView.declTNode;
2060 }
2061 // Components don't have `TView.declTNode` because each instance of component could be
2062 // inserted in different location, hence `TView.declTNode` is meaningless.
2063 // Falling back to `T_HOST` in case we cross component boundary.
2064 if (tView.type === 1 /* Component */) {
2065 return lView[T_HOST];
2066 }
2067 // Remaining TNode type is `TViewType.Root` which doesn't have a parent TNode.
2068 return null;
2069}
2070/**
2071 * This is a light weight version of the `enterView` which is needed by the DI system.
2072 *
2073 * @param lView `LView` location of the DI context.
2074 * @param tNode `TNode` for DI context
2075 * @param flags DI context flags. if `SkipSelf` flag is set than we walk up the declaration
2076 * tree from `tNode` until we find parent declared `TElementNode`.
2077 * @returns `true` if we have successfully entered DI associated with `tNode` (or with declared
2078 * `TNode` if `flags` has `SkipSelf`). Failing to enter DI implies that no associated
2079 * `NodeInjector` can be found and we should instead use `ModuleInjector`.
2080 * - If `true` than this call must be fallowed by `leaveDI`
2081 * - If `false` than this call failed and we should NOT call `leaveDI`
2082 */
2083function enterDI(lView, tNode, flags) {
2084 ngDevMode && assertLViewOrUndefined(lView);
2085 if (flags & InjectFlags.SkipSelf) {
2086 ngDevMode && assertTNodeForTView(tNode, lView[TVIEW]);
2087 let parentTNode = tNode;
2088 let parentLView = lView;
2089 while (true) {
2090 ngDevMode && assertDefined(parentTNode, 'Parent TNode should be defined');
2091 parentTNode = parentTNode.parent;
2092 if (parentTNode === null && !(flags & InjectFlags.Host)) {
2093 parentTNode = getDeclarationTNode(parentLView);
2094 if (parentTNode === null)
2095 break;
2096 // In this case, a parent exists and is definitely an element. So it will definitely
2097 // have an existing lView as the declaration view, which is why we can assume it's defined.
2098 ngDevMode && assertDefined(parentLView, 'Parent LView should be defined');
2099 parentLView = parentLView[DECLARATION_VIEW];
2100 // In Ivy there are Comment nodes that correspond to ngIf and NgFor embedded directives
2101 // We want to skip those and look only at Elements and ElementContainers to ensure
2102 // we're looking at true parent nodes, and not content or other types.
2103 if (parentTNode.type & (2 /* Element */ | 8 /* ElementContainer */)) {
2104 break;
2105 }
2106 }
2107 else {
2108 break;
2109 }
2110 }
2111 if (parentTNode === null) {
2112 // If we failed to find a parent TNode this means that we should use module injector.
2113 return false;
2114 }
2115 else {
2116 tNode = parentTNode;
2117 lView = parentLView;
2118 }
2119 }
2120 ngDevMode && assertTNodeForLView(tNode, lView);
2121 const lFrame = instructionState.lFrame = allocLFrame();
2122 lFrame.currentTNode = tNode;
2123 lFrame.lView = lView;
2124 return true;
2125}
2126/**
2127 * Swap the current lView with a new lView.
2128 *
2129 * For performance reasons we store the lView in the top level of the module.
2130 * This way we minimize the number of properties to read. Whenever a new view
2131 * is entered we have to store the lView for later, and when the view is
2132 * exited the state has to be restored
2133 *
2134 * @param newView New lView to become active
2135 * @returns the previously active lView;
2136 */
2137function enterView(newView) {
2138 ngDevMode && assertNotEqual(newView[0], newView[1], '????');
2139 ngDevMode && assertLViewOrUndefined(newView);
2140 const newLFrame = allocLFrame();
2141 if (ngDevMode) {
2142 assertEqual(newLFrame.isParent, true, 'Expected clean LFrame');
2143 assertEqual(newLFrame.lView, null, 'Expected clean LFrame');
2144 assertEqual(newLFrame.tView, null, 'Expected clean LFrame');
2145 assertEqual(newLFrame.selectedIndex, -1, 'Expected clean LFrame');
2146 assertEqual(newLFrame.elementDepthCount, 0, 'Expected clean LFrame');
2147 assertEqual(newLFrame.currentDirectiveIndex, -1, 'Expected clean LFrame');
2148 assertEqual(newLFrame.currentNamespace, null, 'Expected clean LFrame');
2149 assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame');
2150 assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame');
2151 }
2152 const tView = newView[TVIEW];
2153 instructionState.lFrame = newLFrame;
2154 ngDevMode && tView.firstChild && assertTNodeForTView(tView.firstChild, tView);
2155 newLFrame.currentTNode = tView.firstChild;
2156 newLFrame.lView = newView;
2157 newLFrame.tView = tView;
2158 newLFrame.contextLView = newView;
2159 newLFrame.bindingIndex = tView.bindingStartIndex;
2160 newLFrame.inI18n = false;
2161}
2162/**
2163 * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.
2164 */
2165function allocLFrame() {
2166 const currentLFrame = instructionState.lFrame;
2167 const childLFrame = currentLFrame === null ? null : currentLFrame.child;
2168 const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;
2169 return newLFrame;
2170}
2171function createLFrame(parent) {
2172 const lFrame = {
2173 currentTNode: null,
2174 isParent: true,
2175 lView: null,
2176 tView: null,
2177 selectedIndex: -1,
2178 contextLView: null,
2179 elementDepthCount: 0,
2180 currentNamespace: null,
2181 currentDirectiveIndex: -1,
2182 bindingRootIndex: -1,
2183 bindingIndex: -1,
2184 currentQueryIndex: 0,
2185 parent: parent,
2186 child: null,
2187 inI18n: false,
2188 };
2189 parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.
2190 return lFrame;
2191}
2192/**
2193 * A lightweight version of leave which is used with DI.
2194 *
2195 * This function only resets `currentTNode` and `LView` as those are the only properties
2196 * used with DI (`enterDI()`).
2197 *
2198 * NOTE: This function is reexported as `leaveDI`. However `leaveDI` has return type of `void` where
2199 * as `leaveViewLight` has `LFrame`. This is so that `leaveViewLight` can be used in `leaveView`.
2200 */
2201function leaveViewLight() {
2202 const oldLFrame = instructionState.lFrame;
2203 instructionState.lFrame = oldLFrame.parent;
2204 oldLFrame.currentTNode = null;
2205 oldLFrame.lView = null;
2206 return oldLFrame;
2207}
2208/**
2209 * This is a lightweight version of the `leaveView` which is needed by the DI system.
2210 *
2211 * NOTE: this function is an alias so that we can change the type of the function to have `void`
2212 * return type.
2213 */
2214const leaveDI = leaveViewLight;
2215/**
2216 * Leave the current `LView`
2217 *
2218 * This pops the `LFrame` with the associated `LView` from the stack.
2219 *
2220 * IMPORTANT: We must zero out the `LFrame` values here otherwise they will be retained. This is
2221 * because for performance reasons we don't release `LFrame` but rather keep it for next use.
2222 */
2223function leaveView() {
2224 const oldLFrame = leaveViewLight();
2225 oldLFrame.isParent = true;
2226 oldLFrame.tView = null;
2227 oldLFrame.selectedIndex = -1;
2228 oldLFrame.contextLView = null;
2229 oldLFrame.elementDepthCount = 0;
2230 oldLFrame.currentDirectiveIndex = -1;
2231 oldLFrame.currentNamespace = null;
2232 oldLFrame.bindingRootIndex = -1;
2233 oldLFrame.bindingIndex = -1;
2234 oldLFrame.currentQueryIndex = 0;
2235}
2236function nextContextImpl(level) {
2237 const contextLView = instructionState.lFrame.contextLView =
2238 walkUpViews(level, instructionState.lFrame.contextLView);
2239 return contextLView[CONTEXT];
2240}
2241function walkUpViews(nestingLevel, currentView) {
2242 while (nestingLevel > 0) {
2243 ngDevMode &&
2244 assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
2245 currentView = currentView[DECLARATION_VIEW];
2246 nestingLevel--;
2247 }
2248 return currentView;
2249}
2250/**
2251 * Gets the currently selected element index.
2252 *
2253 * Used with {@link property} instruction (and more in the future) to identify the index in the
2254 * current `LView` to act on.
2255 */
2256function getSelectedIndex() {
2257 return instructionState.lFrame.selectedIndex;
2258}
2259/**
2260 * Sets the most recent index passed to {@link select}
2261 *
2262 * Used with {@link property} instruction (and more in the future) to identify the index in the
2263 * current `LView` to act on.
2264 *
2265 * (Note that if an "exit function" was set earlier (via `setElementExitFn()`) then that will be
2266 * run if and when the provided `index` value is different from the current selected index value.)
2267 */
2268function setSelectedIndex(index) {
2269 ngDevMode && index !== -1 &&
2270 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Index must be past HEADER_OFFSET (or -1).');
2271 ngDevMode &&
2272 assertLessThan(index, instructionState.lFrame.lView.length, 'Can\'t set index passed end of LView');
2273 instructionState.lFrame.selectedIndex = index;
2274}
2275/**
2276 * Gets the `tNode` that represents currently selected element.
2277 */
2278function getSelectedTNode() {
2279 const lFrame = instructionState.lFrame;
2280 return getTNode(lFrame.tView, lFrame.selectedIndex);
2281}
2282/**
2283 * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.
2284 *
2285 * @codeGenApi
2286 */
2287function ɵɵnamespaceSVG() {
2288 instructionState.lFrame.currentNamespace = SVG_NAMESPACE;
2289}
2290/**
2291 * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state.
2292 *
2293 * @codeGenApi
2294 */
2295function ɵɵnamespaceMathML() {
2296 instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;
2297}
2298/**
2299 * Sets the namespace used to create elements to `null`, which forces element creation to use
2300 * `createElement` rather than `createElementNS`.
2301 *
2302 * @codeGenApi
2303 */
2304function ɵɵnamespaceHTML() {
2305 namespaceHTMLInternal();
2306}
2307/**
2308 * Sets the namespace used to create elements to `null`, which forces element creation to use
2309 * `createElement` rather than `createElementNS`.
2310 */
2311function namespaceHTMLInternal() {
2312 instructionState.lFrame.currentNamespace = null;
2313}
2314function getNamespace$1() {
2315 return instructionState.lFrame.currentNamespace;
2316}
2317
2318/**
2319 * @license
2320 * Copyright Google LLC All Rights Reserved.
2321 *
2322 * Use of this source code is governed by an MIT-style license that can be
2323 * found in the LICENSE file at https://angular.io/license
2324 */
2325/**
2326 * Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.
2327 *
2328 * Must be run *only* on the first template pass.
2329 *
2330 * Sets up the pre-order hooks on the provided `tView`,
2331 * see {@link HookData} for details about the data structure.
2332 *
2333 * @param directiveIndex The index of the directive in LView
2334 * @param directiveDef The definition containing the hooks to setup in tView
2335 * @param tView The current TView
2336 */
2337function registerPreOrderHooks(directiveIndex, directiveDef, tView) {
2338 ngDevMode && assertFirstCreatePass(tView);
2339 const { ngOnChanges, ngOnInit, ngDoCheck } = directiveDef.type.prototype;
2340 if (ngOnChanges) {
2341 const wrappedOnChanges = NgOnChangesFeatureImpl(directiveDef);
2342 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, wrappedOnChanges);
2343 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = []))
2344 .push(directiveIndex, wrappedOnChanges);
2345 }
2346 if (ngOnInit) {
2347 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(0 - directiveIndex, ngOnInit);
2348 }
2349 if (ngDoCheck) {
2350 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, ngDoCheck);
2351 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, ngDoCheck);
2352 }
2353}
2354/**
2355 *
2356 * Loops through the directives on the provided `tNode` and queues hooks to be
2357 * run that are not initialization hooks.
2358 *
2359 * Should be executed during `elementEnd()` and similar to
2360 * preserve hook execution order. Content, view, and destroy hooks for projected
2361 * components and directives must be called *before* their hosts.
2362 *
2363 * Sets up the content, view, and destroy hooks on the provided `tView`,
2364 * see {@link HookData} for details about the data structure.
2365 *
2366 * NOTE: This does not set up `onChanges`, `onInit` or `doCheck`, those are set up
2367 * separately at `elementStart`.
2368 *
2369 * @param tView The current TView
2370 * @param tNode The TNode whose directives are to be searched for hooks to queue
2371 */
2372function registerPostOrderHooks(tView, tNode) {
2373 ngDevMode && assertFirstCreatePass(tView);
2374 // It's necessary to loop through the directives at elementEnd() (rather than processing in
2375 // directiveCreate) so we can preserve the current hook order. Content, view, and destroy
2376 // hooks for projected components and directives must be called *before* their hosts.
2377 for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) {
2378 const directiveDef = tView.data[i];
2379 ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef');
2380 const lifecycleHooks = directiveDef.type.prototype;
2381 const { ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, ngAfterViewChecked, ngOnDestroy } = lifecycleHooks;
2382 if (ngAfterContentInit) {
2383 (tView.contentHooks || (tView.contentHooks = [])).push(-i, ngAfterContentInit);
2384 }
2385 if (ngAfterContentChecked) {
2386 (tView.contentHooks || (tView.contentHooks = [])).push(i, ngAfterContentChecked);
2387 (tView.contentCheckHooks || (tView.contentCheckHooks = [])).push(i, ngAfterContentChecked);
2388 }
2389 if (ngAfterViewInit) {
2390 (tView.viewHooks || (tView.viewHooks = [])).push(-i, ngAfterViewInit);
2391 }
2392 if (ngAfterViewChecked) {
2393 (tView.viewHooks || (tView.viewHooks = [])).push(i, ngAfterViewChecked);
2394 (tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, ngAfterViewChecked);
2395 }
2396 if (ngOnDestroy != null) {
2397 (tView.destroyHooks || (tView.destroyHooks = [])).push(i, ngOnDestroy);
2398 }
2399 }
2400}
2401/**
2402 * Executing hooks requires complex logic as we need to deal with 2 constraints.
2403 *
2404 * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only
2405 * once, across many change detection cycles. This must be true even if some hooks throw, or if
2406 * some recursively trigger a change detection cycle.
2407 * To solve that, it is required to track the state of the execution of these init hooks.
2408 * This is done by storing and maintaining flags in the view: the {@link InitPhaseState},
2409 * and the index within that phase. They can be seen as a cursor in the following structure:
2410 * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]]
2411 * They are are stored as flags in LView[FLAGS].
2412 *
2413 * 2. Pre-order hooks can be executed in batches, because of the select instruction.
2414 * To be able to pause and resume their execution, we also need some state about the hook's array
2415 * that is being processed:
2416 * - the index of the next hook to be executed
2417 * - the number of init hooks already found in the processed part of the array
2418 * They are are stored as flags in LView[PREORDER_HOOK_FLAGS].
2419 */
2420/**
2421 * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were
2422 * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read
2423 * / write of the init-hooks related flags.
2424 * @param lView The LView where hooks are defined
2425 * @param hooks Hooks to be run
2426 * @param nodeIndex 3 cases depending on the value:
2427 * - undefined: all hooks from the array should be executed (post-order case)
2428 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
2429 * flushing the remaining hooks)
2430 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
2431 * case, when executing select(number))
2432 */
2433function executeCheckHooks(lView, hooks, nodeIndex) {
2434 callHooks(lView, hooks, 3 /* InitPhaseCompleted */, nodeIndex);
2435}
2436/**
2437 * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked,
2438 * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed.
2439 * @param lView The LView where hooks are defined
2440 * @param hooks Hooks to be run
2441 * @param initPhase A phase for which hooks should be run
2442 * @param nodeIndex 3 cases depending on the value:
2443 * - undefined: all hooks from the array should be executed (post-order case)
2444 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
2445 * flushing the remaining hooks)
2446 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
2447 * case, when executing select(number))
2448 */
2449function executeInitAndCheckHooks(lView, hooks, initPhase, nodeIndex) {
2450 ngDevMode &&
2451 assertNotEqual(initPhase, 3 /* InitPhaseCompleted */, 'Init pre-order hooks should not be called more than once');
2452 if ((lView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
2453 callHooks(lView, hooks, initPhase, nodeIndex);
2454 }
2455}
2456function incrementInitPhaseFlags(lView, initPhase) {
2457 ngDevMode &&
2458 assertNotEqual(initPhase, 3 /* InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');
2459 let flags = lView[FLAGS];
2460 if ((flags & 3 /* InitPhaseStateMask */) === initPhase) {
2461 flags &= 2047 /* IndexWithinInitPhaseReset */;
2462 flags += 1 /* InitPhaseStateIncrementer */;
2463 lView[FLAGS] = flags;
2464 }
2465}
2466/**
2467 * Calls lifecycle hooks with their contexts, skipping init hooks if it's not
2468 * the first LView pass
2469 *
2470 * @param currentView The current view
2471 * @param arr The array in which the hooks are found
2472 * @param initPhaseState the current state of the init phase
2473 * @param currentNodeIndex 3 cases depending on the value:
2474 * - undefined: all hooks from the array should be executed (post-order case)
2475 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
2476 * flushing the remaining hooks)
2477 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
2478 * case, when executing select(number))
2479 */
2480function callHooks(currentView, arr, initPhase, currentNodeIndex) {
2481 ngDevMode &&
2482 assertEqual(isInCheckNoChangesMode(), false, 'Hooks should never be run when in check no changes mode.');
2483 const startIndex = currentNodeIndex !== undefined ?
2484 (currentView[PREORDER_HOOK_FLAGS] & 65535 /* IndexOfTheNextPreOrderHookMaskMask */) :
2485 0;
2486 const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;
2487 const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1
2488 let lastNodeIndexFound = 0;
2489 for (let i = startIndex; i < max; i++) {
2490 const hook = arr[i + 1];
2491 if (typeof hook === 'number') {
2492 lastNodeIndexFound = arr[i];
2493 if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) {
2494 break;
2495 }
2496 }
2497 else {
2498 const isInitHook = arr[i] < 0;
2499 if (isInitHook)
2500 currentView[PREORDER_HOOK_FLAGS] += 65536 /* NumberOfInitHooksCalledIncrementer */;
2501 if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {
2502 callHook(currentView, initPhase, arr, i);
2503 currentView[PREORDER_HOOK_FLAGS] =
2504 (currentView[PREORDER_HOOK_FLAGS] & 4294901760 /* NumberOfInitHooksCalledMask */) + i +
2505 2;
2506 }
2507 i++;
2508 }
2509 }
2510}
2511/**
2512 * Execute one hook against the current `LView`.
2513 *
2514 * @param currentView The current view
2515 * @param initPhaseState the current state of the init phase
2516 * @param arr The array in which the hooks are found
2517 * @param i The current index within the hook data array
2518 */
2519function callHook(currentView, initPhase, arr, i) {
2520 const isInitHook = arr[i] < 0;
2521 const hook = arr[i + 1];
2522 const directiveIndex = isInitHook ? -arr[i] : arr[i];
2523 const directive = currentView[directiveIndex];
2524 if (isInitHook) {
2525 const indexWithintInitPhase = currentView[FLAGS] >> 11 /* IndexWithinInitPhaseShift */;
2526 // The init phase state must be always checked here as it may have been recursively updated.
2527 if (indexWithintInitPhase <
2528 (currentView[PREORDER_HOOK_FLAGS] >> 16 /* NumberOfInitHooksCalledShift */) &&
2529 (currentView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
2530 currentView[FLAGS] += 2048 /* IndexWithinInitPhaseIncrementer */;
2531 profiler(4 /* LifecycleHookStart */, directive, hook);
2532 try {
2533 hook.call(directive);
2534 }
2535 finally {
2536 profiler(5 /* LifecycleHookEnd */, directive, hook);
2537 }
2538 }
2539 }
2540 else {
2541 profiler(4 /* LifecycleHookStart */, directive, hook);
2542 try {
2543 hook.call(directive);
2544 }
2545 finally {
2546 profiler(5 /* LifecycleHookEnd */, directive, hook);
2547 }
2548 }
2549}
2550
2551/**
2552 * @license
2553 * Copyright Google LLC All Rights Reserved.
2554 *
2555 * Use of this source code is governed by an MIT-style license that can be
2556 * found in the LICENSE file at https://angular.io/license
2557 */
2558const NO_PARENT_INJECTOR = -1;
2559/**
2560 * Each injector is saved in 9 contiguous slots in `LView` and 9 contiguous slots in
2561 * `TView.data`. This allows us to store information about the current node's tokens (which
2562 * can be shared in `TView`) as well as the tokens of its ancestor nodes (which cannot be
2563 * shared, so they live in `LView`).
2564 *
2565 * Each of these slots (aside from the last slot) contains a bloom filter. This bloom filter
2566 * determines whether a directive is available on the associated node or not. This prevents us
2567 * from searching the directives array at this level unless it's probable the directive is in it.
2568 *
2569 * See: https://en.wikipedia.org/wiki/Bloom_filter for more about bloom filters.
2570 *
2571 * Because all injectors have been flattened into `LView` and `TViewData`, they cannot typed
2572 * using interfaces as they were previously. The start index of each `LInjector` and `TInjector`
2573 * will differ based on where it is flattened into the main array, so it's not possible to know
2574 * the indices ahead of time and save their types here. The interfaces are still included here
2575 * for documentation purposes.
2576 *
2577 * export interface LInjector extends Array<any> {
2578 *
2579 * // Cumulative bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)
2580 * [0]: number;
2581 *
2582 * // Cumulative bloom for directive IDs 32-63
2583 * [1]: number;
2584 *
2585 * // Cumulative bloom for directive IDs 64-95
2586 * [2]: number;
2587 *
2588 * // Cumulative bloom for directive IDs 96-127
2589 * [3]: number;
2590 *
2591 * // Cumulative bloom for directive IDs 128-159
2592 * [4]: number;
2593 *
2594 * // Cumulative bloom for directive IDs 160 - 191
2595 * [5]: number;
2596 *
2597 * // Cumulative bloom for directive IDs 192 - 223
2598 * [6]: number;
2599 *
2600 * // Cumulative bloom for directive IDs 224 - 255
2601 * [7]: number;
2602 *
2603 * // We need to store a reference to the injector's parent so DI can keep looking up
2604 * // the injector tree until it finds the dependency it's looking for.
2605 * [PARENT_INJECTOR]: number;
2606 * }
2607 *
2608 * export interface TInjector extends Array<any> {
2609 *
2610 * // Shared node bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)
2611 * [0]: number;
2612 *
2613 * // Shared node bloom for directive IDs 32-63
2614 * [1]: number;
2615 *
2616 * // Shared node bloom for directive IDs 64-95
2617 * [2]: number;
2618 *
2619 * // Shared node bloom for directive IDs 96-127
2620 * [3]: number;
2621 *
2622 * // Shared node bloom for directive IDs 128-159
2623 * [4]: number;
2624 *
2625 * // Shared node bloom for directive IDs 160 - 191
2626 * [5]: number;
2627 *
2628 * // Shared node bloom for directive IDs 192 - 223
2629 * [6]: number;
2630 *
2631 * // Shared node bloom for directive IDs 224 - 255
2632 * [7]: number;
2633 *
2634 * // Necessary to find directive indices for a particular node.
2635 * [TNODE]: TElementNode|TElementContainerNode|TContainerNode;
2636 * }
2637 */
2638/**
2639 * Factory for creating instances of injectors in the NodeInjector.
2640 *
2641 * This factory is complicated by the fact that it can resolve `multi` factories as well.
2642 *
2643 * NOTE: Some of the fields are optional which means that this class has two hidden classes.
2644 * - One without `multi` support (most common)
2645 * - One with `multi` values, (rare).
2646 *
2647 * Since VMs can cache up to 4 inline hidden classes this is OK.
2648 *
2649 * - Single factory: Only `resolving` and `factory` is defined.
2650 * - `providers` factory: `componentProviders` is a number and `index = -1`.
2651 * - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`.
2652 */
2653class NodeInjectorFactory {
2654 constructor(
2655 /**
2656 * Factory to invoke in order to create a new instance.
2657 */
2658 factory,
2659 /**
2660 * Set to `true` if the token is declared in `viewProviders` (or if it is component).
2661 */
2662 isViewProvider, injectImplementation) {
2663 this.factory = factory;
2664 /**
2665 * Marker set to true during factory invocation to see if we get into recursive loop.
2666 * Recursive loop causes an error to be displayed.
2667 */
2668 this.resolving = false;
2669 ngDevMode && assertDefined(factory, 'Factory not specified');
2670 ngDevMode && assertEqual(typeof factory, 'function', 'Expected factory function.');
2671 this.canSeeViewProviders = isViewProvider;
2672 this.injectImpl = injectImplementation;
2673 }
2674}
2675function isFactory(obj) {
2676 return obj instanceof NodeInjectorFactory;
2677}
2678// Note: This hack is necessary so we don't erroneously get a circular dependency
2679// failure based on types.
2680const unusedValueExportToPlacateAjd$5 = 1;
2681
2682/**
2683 * Converts `TNodeType` into human readable text.
2684 * Make sure this matches with `TNodeType`
2685 */
2686function toTNodeTypeAsString(tNodeType) {
2687 let text = '';
2688 (tNodeType & 1 /* Text */) && (text += '|Text');
2689 (tNodeType & 2 /* Element */) && (text += '|Element');
2690 (tNodeType & 4 /* Container */) && (text += '|Container');
2691 (tNodeType & 8 /* ElementContainer */) && (text += '|ElementContainer');
2692 (tNodeType & 16 /* Projection */) && (text += '|Projection');
2693 (tNodeType & 32 /* Icu */) && (text += '|IcuContainer');
2694 (tNodeType & 64 /* Placeholder */) && (text += '|Placeholder');
2695 return text.length > 0 ? text.substring(1) : text;
2696}
2697// Note: This hack is necessary so we don't erroneously get a circular dependency
2698// failure based on types.
2699const unusedValueExportToPlacateAjd$4 = 1;
2700/**
2701 * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.
2702 *
2703 * ```
2704 * <div my-dir [class]="exp"></div>
2705 * ```
2706 * and
2707 * ```
2708 * @Directive({
2709 * })
2710 * class MyDirective {
2711 * @Input()
2712 * class: string;
2713 * }
2714 * ```
2715 *
2716 * In the above case it is necessary to write the reconciled styling information into the
2717 * directive's input.
2718 *
2719 * @param tNode
2720 */
2721function hasClassInput(tNode) {
2722 return (tNode.flags & 16 /* hasClassInput */) !== 0;
2723}
2724/**
2725 * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.
2726 *
2727 * ```
2728 * <div my-dir [style]="exp"></div>
2729 * ```
2730 * and
2731 * ```
2732 * @Directive({
2733 * })
2734 * class MyDirective {
2735 * @Input()
2736 * class: string;
2737 * }
2738 * ```
2739 *
2740 * In the above case it is necessary to write the reconciled styling information into the
2741 * directive's input.
2742 *
2743 * @param tNode
2744 */
2745function hasStyleInput(tNode) {
2746 return (tNode.flags & 32 /* hasStyleInput */) !== 0;
2747}
2748
2749/**
2750 * @license
2751 * Copyright Google LLC All Rights Reserved.
2752 *
2753 * Use of this source code is governed by an MIT-style license that can be
2754 * found in the LICENSE file at https://angular.io/license
2755 */
2756function assertTNodeType(tNode, expectedTypes, message) {
2757 assertDefined(tNode, 'should be called with a TNode');
2758 if ((tNode.type & expectedTypes) === 0) {
2759 throwError(message ||
2760 `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`);
2761 }
2762}
2763function assertPureTNodeType(type) {
2764 if (!(type === 2 /* Element */ || //
2765 type === 1 /* Text */ || //
2766 type === 4 /* Container */ || //
2767 type === 8 /* ElementContainer */ || //
2768 type === 32 /* Icu */ || //
2769 type === 16 /* Projection */ || //
2770 type === 64 /* Placeholder */)) {
2771 throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`);
2772 }
2773}
2774
2775/**
2776 * Assigns all attribute values to the provided element via the inferred renderer.
2777 *
2778 * This function accepts two forms of attribute entries:
2779 *
2780 * default: (key, value):
2781 * attrs = [key1, value1, key2, value2]
2782 *
2783 * namespaced: (NAMESPACE_MARKER, uri, name, value)
2784 * attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value]
2785 *
2786 * The `attrs` array can contain a mix of both the default and namespaced entries.
2787 * The "default" values are set without a marker, but if the function comes across
2788 * a marker value then it will attempt to set a namespaced value. If the marker is
2789 * not of a namespaced value then the function will quit and return the index value
2790 * where it stopped during the iteration of the attrs array.
2791 *
2792 * See [AttributeMarker] to understand what the namespace marker value is.
2793 *
2794 * Note that this instruction does not support assigning style and class values to
2795 * an element. See `elementStart` and `elementHostAttrs` to learn how styling values
2796 * are applied to an element.
2797 * @param renderer The renderer to be used
2798 * @param native The element that the attributes will be assigned to
2799 * @param attrs The attribute array of values that will be assigned to the element
2800 * @returns the index value that was last accessed in the attributes array
2801 */
2802function setUpAttributes(renderer, native, attrs) {
2803 const isProc = isProceduralRenderer(renderer);
2804 let i = 0;
2805 while (i < attrs.length) {
2806 const value = attrs[i];
2807 if (typeof value === 'number') {
2808 // only namespaces are supported. Other value types (such as style/class
2809 // entries) are not supported in this function.
2810 if (value !== 0 /* NamespaceURI */) {
2811 break;
2812 }
2813 // we just landed on the marker value ... therefore
2814 // we should skip to the next entry
2815 i++;
2816 const namespaceURI = attrs[i++];
2817 const attrName = attrs[i++];
2818 const attrVal = attrs[i++];
2819 ngDevMode && ngDevMode.rendererSetAttribute++;
2820 isProc ?
2821 renderer.setAttribute(native, attrName, attrVal, namespaceURI) :
2822 native.setAttributeNS(namespaceURI, attrName, attrVal);
2823 }
2824 else {
2825 // attrName is string;
2826 const attrName = value;
2827 const attrVal = attrs[++i];
2828 // Standard attributes
2829 ngDevMode && ngDevMode.rendererSetAttribute++;
2830 if (isAnimationProp(attrName)) {
2831 if (isProc) {
2832 renderer.setProperty(native, attrName, attrVal);
2833 }
2834 }
2835 else {
2836 isProc ?
2837 renderer.setAttribute(native, attrName, attrVal) :
2838 native.setAttribute(attrName, attrVal);
2839 }
2840 i++;
2841 }
2842 }
2843 // another piece of code may iterate over the same attributes array. Therefore
2844 // it may be helpful to return the exact spot where the attributes array exited
2845 // whether by running into an unsupported marker or if all the static values were
2846 // iterated over.
2847 return i;
2848}
2849/**
2850 * Test whether the given value is a marker that indicates that the following
2851 * attribute values in a `TAttributes` array are only the names of attributes,
2852 * and not name-value pairs.
2853 * @param marker The attribute marker to test.
2854 * @returns true if the marker is a "name-only" marker (e.g. `Bindings`, `Template` or `I18n`).
2855 */
2856function isNameOnlyAttributeMarker(marker) {
2857 return marker === 3 /* Bindings */ || marker === 4 /* Template */ ||
2858 marker === 6 /* I18n */;
2859}
2860function isAnimationProp(name) {
2861 // Perf note: accessing charCodeAt to check for the first character of a string is faster as
2862 // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that
2863 // charCodeAt doesn't allocate memory to return a substring.
2864 return name.charCodeAt(0) === 64 /* AT_SIGN */;
2865}
2866/**
2867 * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process.
2868 *
2869 * This merge function keeps the order of attrs same.
2870 *
2871 * @param dst Location of where the merged `TAttributes` should end up.
2872 * @param src `TAttributes` which should be appended to `dst`
2873 */
2874function mergeHostAttrs(dst, src) {
2875 if (src === null || src.length === 0) {
2876 // do nothing
2877 }
2878 else if (dst === null || dst.length === 0) {
2879 // We have source, but dst is empty, just make a copy.
2880 dst = src.slice();
2881 }
2882 else {
2883 let srcMarker = -1 /* ImplicitAttributes */;
2884 for (let i = 0; i < src.length; i++) {
2885 const item = src[i];
2886 if (typeof item === 'number') {
2887 srcMarker = item;
2888 }
2889 else {
2890 if (srcMarker === 0 /* NamespaceURI */) {
2891 // Case where we need to consume `key1`, `key2`, `value` items.
2892 }
2893 else if (srcMarker === -1 /* ImplicitAttributes */ ||
2894 srcMarker === 2 /* Styles */) {
2895 // Case where we have to consume `key1` and `value` only.
2896 mergeHostAttribute(dst, srcMarker, item, null, src[++i]);
2897 }
2898 else {
2899 // Case where we have to consume `key1` only.
2900 mergeHostAttribute(dst, srcMarker, item, null, null);
2901 }
2902 }
2903 }
2904 }
2905 return dst;
2906}
2907/**
2908 * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account.
2909 *
2910 * @param dst `TAttributes` to append to.
2911 * @param marker Region where the `key`/`value` should be added.
2912 * @param key1 Key to add to `TAttributes`
2913 * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`)
2914 * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class.
2915 */
2916function mergeHostAttribute(dst, marker, key1, key2, value) {
2917 let i = 0;
2918 // Assume that new markers will be inserted at the end.
2919 let markerInsertPosition = dst.length;
2920 // scan until correct type.
2921 if (marker === -1 /* ImplicitAttributes */) {
2922 markerInsertPosition = -1;
2923 }
2924 else {
2925 while (i < dst.length) {
2926 const dstValue = dst[i++];
2927 if (typeof dstValue === 'number') {
2928 if (dstValue === marker) {
2929 markerInsertPosition = -1;
2930 break;
2931 }
2932 else if (dstValue > marker) {
2933 // We need to save this as we want the markers to be inserted in specific order.
2934 markerInsertPosition = i - 1;
2935 break;
2936 }
2937 }
2938 }
2939 }
2940 // search until you find place of insertion
2941 while (i < dst.length) {
2942 const item = dst[i];
2943 if (typeof item === 'number') {
2944 // since `i` started as the index after the marker, we did not find it if we are at the next
2945 // marker
2946 break;
2947 }
2948 else if (item === key1) {
2949 // We already have same token
2950 if (key2 === null) {
2951 if (value !== null) {
2952 dst[i + 1] = value;
2953 }
2954 return;
2955 }
2956 else if (key2 === dst[i + 1]) {
2957 dst[i + 2] = value;
2958 return;
2959 }
2960 }
2961 // Increment counter.
2962 i++;
2963 if (key2 !== null)
2964 i++;
2965 if (value !== null)
2966 i++;
2967 }
2968 // insert at location.
2969 if (markerInsertPosition !== -1) {
2970 dst.splice(markerInsertPosition, 0, marker);
2971 i = markerInsertPosition + 1;
2972 }
2973 dst.splice(i++, 0, key1);
2974 if (key2 !== null) {
2975 dst.splice(i++, 0, key2);
2976 }
2977 if (value !== null) {
2978 dst.splice(i++, 0, value);
2979 }
2980}
2981
2982/**
2983 * @license
2984 * Copyright Google LLC All Rights Reserved.
2985 *
2986 * Use of this source code is governed by an MIT-style license that can be
2987 * found in the LICENSE file at https://angular.io/license
2988 */
2989/// Parent Injector Utils ///////////////////////////////////////////////////////////////
2990function hasParentInjector(parentLocation) {
2991 return parentLocation !== NO_PARENT_INJECTOR;
2992}
2993function getParentInjectorIndex(parentLocation) {
2994 ngDevMode && assertNumber(parentLocation, 'Number expected');
2995 ngDevMode && assertNotEqual(parentLocation, -1, 'Not a valid state.');
2996 const parentInjectorIndex = parentLocation & 32767 /* InjectorIndexMask */;
2997 ngDevMode &&
2998 assertGreaterThan(parentInjectorIndex, HEADER_OFFSET, 'Parent injector must be pointing past HEADER_OFFSET.');
2999 return parentLocation & 32767 /* InjectorIndexMask */;
3000}
3001function getParentInjectorViewOffset(parentLocation) {
3002 return parentLocation >> 16 /* ViewOffsetShift */;
3003}
3004/**
3005 * Unwraps a parent injector location number to find the view offset from the current injector,
3006 * then walks up the declaration view tree until the view is found that contains the parent
3007 * injector.
3008 *
3009 * @param location The location of the parent injector, which contains the view offset
3010 * @param startView The LView instance from which to start walking up the view tree
3011 * @returns The LView instance that contains the parent injector
3012 */
3013function getParentInjectorView(location, startView) {
3014 let viewOffset = getParentInjectorViewOffset(location);
3015 let parentView = startView;
3016 // For most cases, the parent injector can be found on the host node (e.g. for component
3017 // or container), but we must keep the loop here to support the rarer case of deeply nested
3018 // <ng-template> tags or inline views, where the parent injector might live many views
3019 // above the child injector.
3020 while (viewOffset > 0) {
3021 parentView = parentView[DECLARATION_VIEW];
3022 viewOffset--;
3023 }
3024 return parentView;
3025}
3026
3027/**
3028 * @license
3029 * Copyright Google LLC All Rights Reserved.
3030 *
3031 * Use of this source code is governed by an MIT-style license that can be
3032 * found in the LICENSE file at https://angular.io/license
3033 */
3034/**
3035 * Defines if the call to `inject` should include `viewProviders` in its resolution.
3036 *
3037 * This is set to true when we try to instantiate a component. This value is reset in
3038 * `getNodeInjectable` to a value which matches the declaration location of the token about to be
3039 * instantiated. This is done so that if we are injecting a token which was declared outside of
3040 * `viewProviders` we don't accidentally pull `viewProviders` in.
3041 *
3042 * Example:
3043 *
3044 * ```
3045 * @Injectable()
3046 * class MyService {
3047 * constructor(public value: String) {}
3048 * }
3049 *
3050 * @Component({
3051 * providers: [
3052 * MyService,
3053 * {provide: String, value: 'providers' }
3054 * ]
3055 * viewProviders: [
3056 * {provide: String, value: 'viewProviders'}
3057 * ]
3058 * })
3059 * class MyComponent {
3060 * constructor(myService: MyService, value: String) {
3061 * // We expect that Component can see into `viewProviders`.
3062 * expect(value).toEqual('viewProviders');
3063 * // `MyService` was not declared in `viewProviders` hence it can't see it.
3064 * expect(myService.value).toEqual('providers');
3065 * }
3066 * }
3067 *
3068 * ```
3069 */
3070let includeViewProviders = true;
3071function setIncludeViewProviders(v) {
3072 const oldValue = includeViewProviders;
3073 includeViewProviders = v;
3074 return oldValue;
3075}
3076/**
3077 * The number of slots in each bloom filter (used by DI). The larger this number, the fewer
3078 * directives that will share slots, and thus, the fewer false positives when checking for
3079 * the existence of a directive.
3080 */
3081const BLOOM_SIZE = 256;
3082const BLOOM_MASK = BLOOM_SIZE - 1;
3083/**
3084 * The number of bits that is represented by a single bloom bucket. JS bit operations are 32 bits,
3085 * so each bucket represents 32 distinct tokens which accounts for log2(32) = 5 bits of a bloom hash
3086 * number.
3087 */
3088const BLOOM_BUCKET_BITS = 5;
3089/** Counter used to generate unique IDs for directives. */
3090let nextNgElementId = 0;
3091/**
3092 * Registers this directive as present in its node's injector by flipping the directive's
3093 * corresponding bit in the injector's bloom filter.
3094 *
3095 * @param injectorIndex The index of the node injector where this token should be registered
3096 * @param tView The TView for the injector's bloom filters
3097 * @param type The directive token to register
3098 */
3099function bloomAdd(injectorIndex, tView, type) {
3100 ngDevMode && assertEqual(tView.firstCreatePass, true, 'expected firstCreatePass to be true');
3101 let id;
3102 if (typeof type === 'string') {
3103 id = type.charCodeAt(0) || 0;
3104 }
3105 else if (type.hasOwnProperty(NG_ELEMENT_ID)) {
3106 id = type[NG_ELEMENT_ID];
3107 }
3108 // Set a unique ID on the directive type, so if something tries to inject the directive,
3109 // we can easily retrieve the ID and hash it into the bloom bit that should be checked.
3110 if (id == null) {
3111 id = type[NG_ELEMENT_ID] = nextNgElementId++;
3112 }
3113 // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),
3114 // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.
3115 const bloomHash = id & BLOOM_MASK;
3116 // Create a mask that targets the specific bit associated with the directive.
3117 // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
3118 // to bit positions 0 - 31 in a 32 bit integer.
3119 const mask = 1 << bloomHash;
3120 // Each bloom bucket in `tData` represents `BLOOM_BUCKET_BITS` number of bits of `bloomHash`.
3121 // Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset that the mask
3122 // should be written to.
3123 tView.data[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)] |= mask;
3124}
3125/**
3126 * Creates (or gets an existing) injector for a given element or container.
3127 *
3128 * @param tNode for which an injector should be retrieved / created.
3129 * @param lView View where the node is stored
3130 * @returns Node injector
3131 */
3132function getOrCreateNodeInjectorForNode(tNode, lView) {
3133 const existingInjectorIndex = getInjectorIndex(tNode, lView);
3134 if (existingInjectorIndex !== -1) {
3135 return existingInjectorIndex;
3136 }
3137 const tView = lView[TVIEW];
3138 if (tView.firstCreatePass) {
3139 tNode.injectorIndex = lView.length;
3140 insertBloom(tView.data, tNode); // foundation for node bloom
3141 insertBloom(lView, null); // foundation for cumulative bloom
3142 insertBloom(tView.blueprint, null);
3143 }
3144 const parentLoc = getParentInjectorLocation(tNode, lView);
3145 const injectorIndex = tNode.injectorIndex;
3146 // If a parent injector can't be found, its location is set to -1.
3147 // In that case, we don't need to set up a cumulative bloom
3148 if (hasParentInjector(parentLoc)) {
3149 const parentIndex = getParentInjectorIndex(parentLoc);
3150 const parentLView = getParentInjectorView(parentLoc, lView);
3151 const parentData = parentLView[TVIEW].data;
3152 // Creates a cumulative bloom filter that merges the parent's bloom filter
3153 // and its own cumulative bloom (which contains tokens for all ancestors)
3154 for (let i = 0; i < 8 /* BLOOM_SIZE */; i++) {
3155 lView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i];
3156 }
3157 }
3158 lView[injectorIndex + 8 /* PARENT */] = parentLoc;
3159 return injectorIndex;
3160}
3161function insertBloom(arr, footer) {
3162 arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);
3163}
3164function getInjectorIndex(tNode, lView) {
3165 if (tNode.injectorIndex === -1 ||
3166 // If the injector index is the same as its parent's injector index, then the index has been
3167 // copied down from the parent node. No injector has been created yet on this node.
3168 (tNode.parent && tNode.parent.injectorIndex === tNode.injectorIndex) ||
3169 // After the first template pass, the injector index might exist but the parent values
3170 // might not have been calculated yet for this instance
3171 lView[tNode.injectorIndex + 8 /* PARENT */] === null) {
3172 return -1;
3173 }
3174 else {
3175 ngDevMode && assertIndexInRange(lView, tNode.injectorIndex);
3176 return tNode.injectorIndex;
3177 }
3178}
3179/**
3180 * Finds the index of the parent injector, with a view offset if applicable. Used to set the
3181 * parent injector initially.
3182 *
3183 * @returns Returns a number that is the combination of the number of LViews that we have to go up
3184 * to find the LView containing the parent inject AND the index of the injector within that LView.
3185 */
3186function getParentInjectorLocation(tNode, lView) {
3187 if (tNode.parent && tNode.parent.injectorIndex !== -1) {
3188 // If we have a parent `TNode` and there is an injector associated with it we are done, because
3189 // the parent injector is within the current `LView`.
3190 return tNode.parent.injectorIndex; // ViewOffset is 0
3191 }
3192 // When parent injector location is computed it may be outside of the current view. (ie it could
3193 // be pointing to a declared parent location). This variable stores number of declaration parents
3194 // we need to walk up in order to find the parent injector location.
3195 let declarationViewOffset = 0;
3196 let parentTNode = null;
3197 let lViewCursor = lView;
3198 // The parent injector is not in the current `LView`. We will have to walk the declared parent
3199 // `LView` hierarchy and look for it. If we walk of the top, that means that there is no parent
3200 // `NodeInjector`.
3201 while (lViewCursor !== null) {
3202 // First determine the `parentTNode` location. The parent pointer differs based on `TView.type`.
3203 const tView = lViewCursor[TVIEW];
3204 const tViewType = tView.type;
3205 if (tViewType === 2 /* Embedded */) {
3206 ngDevMode &&
3207 assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');
3208 parentTNode = tView.declTNode;
3209 }
3210 else if (tViewType === 1 /* Component */) {
3211 // Components don't have `TView.declTNode` because each instance of component could be
3212 // inserted in different location, hence `TView.declTNode` is meaningless.
3213 parentTNode = lViewCursor[T_HOST];
3214 }
3215 else {
3216 ngDevMode && assertEqual(tView.type, 0 /* Root */, 'Root type expected');
3217 parentTNode = null;
3218 }
3219 if (parentTNode === null) {
3220 // If we have no parent, than we are done.
3221 return NO_PARENT_INJECTOR;
3222 }
3223 ngDevMode && parentTNode && assertTNodeForLView(parentTNode, lViewCursor[DECLARATION_VIEW]);
3224 // Every iteration of the loop requires that we go to the declared parent.
3225 declarationViewOffset++;
3226 lViewCursor = lViewCursor[DECLARATION_VIEW];
3227 if (parentTNode.injectorIndex !== -1) {
3228 // We found a NodeInjector which points to something.
3229 return (parentTNode.injectorIndex |
3230 (declarationViewOffset << 16 /* ViewOffsetShift */));
3231 }
3232 }
3233 return NO_PARENT_INJECTOR;
3234}
3235/**
3236 * Makes a type or an injection token public to the DI system by adding it to an
3237 * injector's bloom filter.
3238 *
3239 * @param di The node injector in which a directive will be added
3240 * @param token The type or the injection token to be made public
3241 */
3242function diPublicInInjector(injectorIndex, tView, token) {
3243 bloomAdd(injectorIndex, tView, token);
3244}
3245/**
3246 * Inject static attribute value into directive constructor.
3247 *
3248 * This method is used with `factory` functions which are generated as part of
3249 * `defineDirective` or `defineComponent`. The method retrieves the static value
3250 * of an attribute. (Dynamic attributes are not supported since they are not resolved
3251 * at the time of injection and can change over time.)
3252 *
3253 * # Example
3254 * Given:
3255 * ```
3256 * @Component(...)
3257 * class MyComponent {
3258 * constructor(@Attribute('title') title: string) { ... }
3259 * }
3260 * ```
3261 * When instantiated with
3262 * ```
3263 * <my-component title="Hello"></my-component>
3264 * ```
3265 *
3266 * Then factory method generated is:
3267 * ```
3268 * MyComponent.ɵcmp = defineComponent({
3269 * factory: () => new MyComponent(injectAttribute('title'))
3270 * ...
3271 * })
3272 * ```
3273 *
3274 * @publicApi
3275 */
3276function injectAttributeImpl(tNode, attrNameToInject) {
3277 ngDevMode && assertTNodeType(tNode, 12 /* AnyContainer */ | 3 /* AnyRNode */);
3278 ngDevMode && assertDefined(tNode, 'expecting tNode');
3279 if (attrNameToInject === 'class') {
3280 return tNode.classes;
3281 }
3282 if (attrNameToInject === 'style') {
3283 return tNode.styles;
3284 }
3285 const attrs = tNode.attrs;
3286 if (attrs) {
3287 const attrsLength = attrs.length;
3288 let i = 0;
3289 while (i < attrsLength) {
3290 const value = attrs[i];
3291 // If we hit a `Bindings` or `Template` marker then we are done.
3292 if (isNameOnlyAttributeMarker(value))
3293 break;
3294 // Skip namespaced attributes
3295 if (value === 0 /* NamespaceURI */) {
3296 // we skip the next two values
3297 // as namespaced attributes looks like
3298 // [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist',
3299 // 'existValue', ...]
3300 i = i + 2;
3301 }
3302 else if (typeof value === 'number') {
3303 // Skip to the first value of the marked attribute.
3304 i++;
3305 while (i < attrsLength && typeof attrs[i] === 'string') {
3306 i++;
3307 }
3308 }
3309 else if (value === attrNameToInject) {
3310 return attrs[i + 1];
3311 }
3312 else {
3313 i = i + 2;
3314 }
3315 }
3316 }
3317 return null;
3318}
3319function notFoundValueOrThrow(notFoundValue, token, flags) {
3320 if (flags & InjectFlags.Optional) {
3321 return notFoundValue;
3322 }
3323 else {
3324 throwProviderNotFoundError(token, 'NodeInjector');
3325 }
3326}
3327/**
3328 * Returns the value associated to the given token from the ModuleInjector or throws exception
3329 *
3330 * @param lView The `LView` that contains the `tNode`
3331 * @param token The token to look for
3332 * @param flags Injection flags
3333 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
3334 * @returns the value from the injector or throws an exception
3335 */
3336function lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue) {
3337 if (flags & InjectFlags.Optional && notFoundValue === undefined) {
3338 // This must be set or the NullInjector will throw for optional deps
3339 notFoundValue = null;
3340 }
3341 if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {
3342 const moduleInjector = lView[INJECTOR$1];
3343 // switch to `injectInjectorOnly` implementation for module injector, since module injector
3344 // should not have access to Component/Directive DI scope (that may happen through
3345 // `directiveInject` implementation)
3346 const previousInjectImplementation = setInjectImplementation(undefined);
3347 try {
3348 if (moduleInjector) {
3349 return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);
3350 }
3351 else {
3352 return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);
3353 }
3354 }
3355 finally {
3356 setInjectImplementation(previousInjectImplementation);
3357 }
3358 }
3359 return notFoundValueOrThrow(notFoundValue, token, flags);
3360}
3361/**
3362 * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.
3363 *
3364 * Look for the injector providing the token by walking up the node injector tree and then
3365 * the module injector tree.
3366 *
3367 * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom
3368 * filter. `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)
3369 *
3370 * @param tNode The Node where the search for the injector should start
3371 * @param lView The `LView` that contains the `tNode`
3372 * @param token The token to look for
3373 * @param flags Injection flags
3374 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
3375 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided
3376 */
3377function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default, notFoundValue) {
3378 if (tNode !== null) {
3379 const bloomHash = bloomHashBitOrFactory(token);
3380 // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef
3381 // so just call the factory function to create it.
3382 if (typeof bloomHash === 'function') {
3383 if (!enterDI(lView, tNode, flags)) {
3384 // Failed to enter DI, try module injector instead. If a token is injected with the @Host
3385 // flag, the module injector is not searched for that token in Ivy.
3386 return (flags & InjectFlags.Host) ?
3387 notFoundValueOrThrow(notFoundValue, token, flags) :
3388 lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);
3389 }
3390 try {
3391 const value = bloomHash(flags);
3392 if (value == null && !(flags & InjectFlags.Optional)) {
3393 throwProviderNotFoundError(token);
3394 }
3395 else {
3396 return value;
3397 }
3398 }
3399 finally {
3400 leaveDI();
3401 }
3402 }
3403 else if (typeof bloomHash === 'number') {
3404 // A reference to the previous injector TView that was found while climbing the element
3405 // injector tree. This is used to know if viewProviders can be accessed on the current
3406 // injector.
3407 let previousTView = null;
3408 let injectorIndex = getInjectorIndex(tNode, lView);
3409 let parentLocation = NO_PARENT_INJECTOR;
3410 let hostTElementNode = flags & InjectFlags.Host ? lView[DECLARATION_COMPONENT_VIEW][T_HOST] : null;
3411 // If we should skip this injector, or if there is no injector on this node, start by
3412 // searching the parent injector.
3413 if (injectorIndex === -1 || flags & InjectFlags.SkipSelf) {
3414 parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) :
3415 lView[injectorIndex + 8 /* PARENT */];
3416 if (parentLocation === NO_PARENT_INJECTOR || !shouldSearchParent(flags, false)) {
3417 injectorIndex = -1;
3418 }
3419 else {
3420 previousTView = lView[TVIEW];
3421 injectorIndex = getParentInjectorIndex(parentLocation);
3422 lView = getParentInjectorView(parentLocation, lView);
3423 }
3424 }
3425 // Traverse up the injector tree until we find a potential match or until we know there
3426 // *isn't* a match.
3427 while (injectorIndex !== -1) {
3428 ngDevMode && assertNodeInjector(lView, injectorIndex);
3429 // Check the current injector. If it matches, see if it contains token.
3430 const tView = lView[TVIEW];
3431 ngDevMode &&
3432 assertTNodeForLView(tView.data[injectorIndex + 8 /* TNODE */], lView);
3433 if (bloomHasToken(bloomHash, injectorIndex, tView.data)) {
3434 // At this point, we have an injector which *may* contain the token, so we step through
3435 // the providers and directives associated with the injector's corresponding node to get
3436 // the instance.
3437 const instance = searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode);
3438 if (instance !== NOT_FOUND) {
3439 return instance;
3440 }
3441 }
3442 parentLocation = lView[injectorIndex + 8 /* PARENT */];
3443 if (parentLocation !== NO_PARENT_INJECTOR &&
3444 shouldSearchParent(flags, lView[TVIEW].data[injectorIndex + 8 /* TNODE */] === hostTElementNode) &&
3445 bloomHasToken(bloomHash, injectorIndex, lView)) {
3446 // The def wasn't found anywhere on this node, so it was a false positive.
3447 // Traverse up the tree and continue searching.
3448 previousTView = tView;
3449 injectorIndex = getParentInjectorIndex(parentLocation);
3450 lView = getParentInjectorView(parentLocation, lView);
3451 }
3452 else {
3453 // If we should not search parent OR If the ancestor bloom filter value does not have the
3454 // bit corresponding to the directive we can give up on traversing up to find the specific
3455 // injector.
3456 injectorIndex = -1;
3457 }
3458 }
3459 }
3460 }
3461 return lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);
3462}
3463const NOT_FOUND = {};
3464function createNodeInjector() {
3465 return new NodeInjector(getCurrentTNode(), getLView());
3466}
3467function searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode) {
3468 const currentTView = lView[TVIEW];
3469 const tNode = currentTView.data[injectorIndex + 8 /* TNODE */];
3470 // First, we need to determine if view providers can be accessed by the starting element.
3471 // There are two possibilities
3472 const canAccessViewProviders = previousTView == null ?
3473 // 1) This is the first invocation `previousTView == null` which means that we are at the
3474 // `TNode` of where injector is starting to look. In such a case the only time we are allowed
3475 // to look into the ViewProviders is if:
3476 // - we are on a component
3477 // - AND the injector set `includeViewProviders` to true (implying that the token can see
3478 // ViewProviders because it is the Component or a Service which itself was declared in
3479 // ViewProviders)
3480 (isComponentHost(tNode) && includeViewProviders) :
3481 // 2) `previousTView != null` which means that we are now walking across the parent nodes.
3482 // In such a case we are only allowed to look into the ViewProviders if:
3483 // - We just crossed from child View to Parent View `previousTView != currentTView`
3484 // - AND the parent TNode is an Element.
3485 // This means that we just came from the Component's View and therefore are allowed to see
3486 // into the ViewProviders.
3487 (previousTView != currentTView && ((tNode.type & 3 /* AnyRNode */) !== 0));
3488 // This special case happens when there is a @host on the inject and when we are searching
3489 // on the host element node.
3490 const isHostSpecialCase = (flags & InjectFlags.Host) && hostTElementNode === tNode;
3491 const injectableIdx = locateDirectiveOrProvider(tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase);
3492 if (injectableIdx !== null) {
3493 return getNodeInjectable(lView, currentTView, injectableIdx, tNode);
3494 }
3495 else {
3496 return NOT_FOUND;
3497 }
3498}
3499/**
3500 * Searches for the given token among the node's directives and providers.
3501 *
3502 * @param tNode TNode on which directives are present.
3503 * @param tView The tView we are currently processing
3504 * @param token Provider token or type of a directive to look for.
3505 * @param canAccessViewProviders Whether view providers should be considered.
3506 * @param isHostSpecialCase Whether the host special case applies.
3507 * @returns Index of a found directive or provider, or null when none found.
3508 */
3509function locateDirectiveOrProvider(tNode, tView, token, canAccessViewProviders, isHostSpecialCase) {
3510 const nodeProviderIndexes = tNode.providerIndexes;
3511 const tInjectables = tView.data;
3512 const injectablesStart = nodeProviderIndexes & 1048575 /* ProvidersStartIndexMask */;
3513 const directivesStart = tNode.directiveStart;
3514 const directiveEnd = tNode.directiveEnd;
3515 const cptViewProvidersCount = nodeProviderIndexes >> 20 /* CptViewProvidersCountShift */;
3516 const startingIndex = canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount;
3517 // When the host special case applies, only the viewProviders and the component are visible
3518 const endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd;
3519 for (let i = startingIndex; i < endIndex; i++) {
3520 const providerTokenOrDef = tInjectables[i];
3521 if (i < directivesStart && token === providerTokenOrDef ||
3522 i >= directivesStart && providerTokenOrDef.type === token) {
3523 return i;
3524 }
3525 }
3526 if (isHostSpecialCase) {
3527 const dirDef = tInjectables[directivesStart];
3528 if (dirDef && isComponentDef(dirDef) && dirDef.type === token) {
3529 return directivesStart;
3530 }
3531 }
3532 return null;
3533}
3534/**
3535 * Retrieve or instantiate the injectable from the `LView` at particular `index`.
3536 *
3537 * This function checks to see if the value has already been instantiated and if so returns the
3538 * cached `injectable`. Otherwise if it detects that the value is still a factory it
3539 * instantiates the `injectable` and caches the value.
3540 */
3541function getNodeInjectable(lView, tView, index, tNode) {
3542 let value = lView[index];
3543 const tData = tView.data;
3544 if (isFactory(value)) {
3545 const factory = value;
3546 if (factory.resolving) {
3547 throwCyclicDependencyError(stringifyForError(tData[index]));
3548 }
3549 const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
3550 factory.resolving = true;
3551 const previousInjectImplementation = factory.injectImpl ? setInjectImplementation(factory.injectImpl) : null;
3552 const success = enterDI(lView, tNode, InjectFlags.Default);
3553 ngDevMode &&
3554 assertEqual(success, true, 'Because flags do not contain \`SkipSelf\' we expect this to always succeed.');
3555 try {
3556 value = lView[index] = factory.factory(undefined, tData, lView, tNode);
3557 // This code path is hit for both directives and providers.
3558 // For perf reasons, we want to avoid searching for hooks on providers.
3559 // It does no harm to try (the hooks just won't exist), but the extra
3560 // checks are unnecessary and this is a hot path. So we check to see
3561 // if the index of the dependency is in the directive range for this
3562 // tNode. If it's not, we know it's a provider and skip hook registration.
3563 if (tView.firstCreatePass && index >= tNode.directiveStart) {
3564 ngDevMode && assertDirectiveDef(tData[index]);
3565 registerPreOrderHooks(index, tData[index], tView);
3566 }
3567 }
3568 finally {
3569 previousInjectImplementation !== null &&
3570 setInjectImplementation(previousInjectImplementation);
3571 setIncludeViewProviders(previousIncludeViewProviders);
3572 factory.resolving = false;
3573 leaveDI();
3574 }
3575 }
3576 return value;
3577}
3578/**
3579 * Returns the bit in an injector's bloom filter that should be used to determine whether or not
3580 * the directive might be provided by the injector.
3581 *
3582 * When a directive is public, it is added to the bloom filter and given a unique ID that can be
3583 * retrieved on the Type. When the directive isn't public or the token is not a directive `null`
3584 * is returned as the node injector can not possibly provide that token.
3585 *
3586 * @param token the injection token
3587 * @returns the matching bit to check in the bloom filter or `null` if the token is not known.
3588 * When the returned value is negative then it represents special values such as `Injector`.
3589 */
3590function bloomHashBitOrFactory(token) {
3591 ngDevMode && assertDefined(token, 'token must be defined');
3592 if (typeof token === 'string') {
3593 return token.charCodeAt(0) || 0;
3594 }
3595 const tokenId =
3596 // First check with `hasOwnProperty` so we don't get an inherited ID.
3597 token.hasOwnProperty(NG_ELEMENT_ID) ? token[NG_ELEMENT_ID] : undefined;
3598 // Negative token IDs are used for special objects such as `Injector`
3599 if (typeof tokenId === 'number') {
3600 if (tokenId >= 0) {
3601 return tokenId & BLOOM_MASK;
3602 }
3603 else {
3604 ngDevMode &&
3605 assertEqual(tokenId, -1 /* Injector */, 'Expecting to get Special Injector Id');
3606 return createNodeInjector;
3607 }
3608 }
3609 else {
3610 return tokenId;
3611 }
3612}
3613function bloomHasToken(bloomHash, injectorIndex, injectorView) {
3614 // Create a mask that targets the specific bit associated with the directive we're looking for.
3615 // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
3616 // to bit positions 0 - 31 in a 32 bit integer.
3617 const mask = 1 << bloomHash;
3618 // Each bloom bucket in `injectorView` represents `BLOOM_BUCKET_BITS` number of bits of
3619 // `bloomHash`. Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset
3620 // that should be used.
3621 const value = injectorView[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)];
3622 // If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,
3623 // this injector is a potential match.
3624 return !!(value & mask);
3625}
3626/** Returns true if flags prevent parent injector from being searched for tokens */
3627function shouldSearchParent(flags, isFirstHostTNode) {
3628 return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode);
3629}
3630class NodeInjector {
3631 constructor(_tNode, _lView) {
3632 this._tNode = _tNode;
3633 this._lView = _lView;
3634 }
3635 get(token, notFoundValue, flags) {
3636 return getOrCreateInjectable(this._tNode, this._lView, token, flags, notFoundValue);
3637 }
3638}
3639/**
3640 * @codeGenApi
3641 */
3642function ɵɵgetInheritedFactory(type) {
3643 return noSideEffects(() => {
3644 const ownConstructor = type.prototype.constructor;
3645 const ownFactory = ownConstructor[NG_FACTORY_DEF] || getFactoryOf(ownConstructor);
3646 const objectPrototype = Object.prototype;
3647 let parent = Object.getPrototypeOf(type.prototype).constructor;
3648 // Go up the prototype until we hit `Object`.
3649 while (parent && parent !== objectPrototype) {
3650 const factory = parent[NG_FACTORY_DEF] || getFactoryOf(parent);
3651 // If we hit something that has a factory and the factory isn't the same as the type,
3652 // we've found the inherited factory. Note the check that the factory isn't the type's
3653 // own factory is redundant in most cases, but if the user has custom decorators on the
3654 // class, this lookup will start one level down in the prototype chain, causing us to
3655 // find the own factory first and potentially triggering an infinite loop downstream.
3656 if (factory && factory !== ownFactory) {
3657 return factory;
3658 }
3659 parent = Object.getPrototypeOf(parent);
3660 }
3661 // There is no factory defined. Either this was improper usage of inheritance
3662 // (no Angular decorator on the superclass) or there is no constructor at all
3663 // in the inheritance chain. Since the two cases cannot be distinguished, the
3664 // latter has to be assumed.
3665 return t => new t();
3666 });
3667}
3668function getFactoryOf(type) {
3669 if (isForwardRef(type)) {
3670 return () => {
3671 const factory = getFactoryOf(resolveForwardRef(type));
3672 return factory && factory();
3673 };
3674 }
3675 return getFactoryDef(type);
3676}
3677
3678/**
3679 * @license
3680 * Copyright Google LLC All Rights Reserved.
3681 *
3682 * Use of this source code is governed by an MIT-style license that can be
3683 * found in the LICENSE file at https://angular.io/license
3684 */
3685/**
3686 * Facade for the attribute injection from DI.
3687 *
3688 * @codeGenApi
3689 */
3690function ɵɵinjectAttribute(attrNameToInject) {
3691 return injectAttributeImpl(getCurrentTNode(), attrNameToInject);
3692}
3693
3694/**
3695 * @license
3696 * Copyright Google LLC All Rights Reserved.
3697 *
3698 * Use of this source code is governed by an MIT-style license that can be
3699 * found in the LICENSE file at https://angular.io/license
3700 */
3701const ANNOTATIONS = '__annotations__';
3702const PARAMETERS = '__parameters__';
3703const PROP_METADATA = '__prop__metadata__';
3704/**
3705 * @suppress {globalThis}
3706 */
3707function makeDecorator(name, props, parentClass, additionalProcessing, typeFn) {
3708 return noSideEffects(() => {
3709 const metaCtor = makeMetadataCtor(props);
3710 function DecoratorFactory(...args) {
3711 if (this instanceof DecoratorFactory) {
3712 metaCtor.call(this, ...args);
3713 return this;
3714 }
3715 const annotationInstance = new DecoratorFactory(...args);
3716 return function TypeDecorator(cls) {
3717 if (typeFn)
3718 typeFn(cls, ...args);
3719 // Use of Object.defineProperty is important since it creates non-enumerable property which
3720 // prevents the property is copied during subclassing.
3721 const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
3722 cls[ANNOTATIONS] :
3723 Object.defineProperty(cls, ANNOTATIONS, { value: [] })[ANNOTATIONS];
3724 annotations.push(annotationInstance);
3725 if (additionalProcessing)
3726 additionalProcessing(cls);
3727 return cls;
3728 };
3729 }
3730 if (parentClass) {
3731 DecoratorFactory.prototype = Object.create(parentClass.prototype);
3732 }
3733 DecoratorFactory.prototype.ngMetadataName = name;
3734 DecoratorFactory.annotationCls = DecoratorFactory;
3735 return DecoratorFactory;
3736 });
3737}
3738function makeMetadataCtor(props) {
3739 return function ctor(...args) {
3740 if (props) {
3741 const values = props(...args);
3742 for (const propName in values) {
3743 this[propName] = values[propName];
3744 }
3745 }
3746 };
3747}
3748function makeParamDecorator(name, props, parentClass) {
3749 return noSideEffects(() => {
3750 const metaCtor = makeMetadataCtor(props);
3751 function ParamDecoratorFactory(...args) {
3752 if (this instanceof ParamDecoratorFactory) {
3753 metaCtor.apply(this, args);
3754 return this;
3755 }
3756 const annotationInstance = new ParamDecoratorFactory(...args);
3757 ParamDecorator.annotation = annotationInstance;
3758 return ParamDecorator;
3759 function ParamDecorator(cls, unusedKey, index) {
3760 // Use of Object.defineProperty is important since it creates non-enumerable property which
3761 // prevents the property is copied during subclassing.
3762 const parameters = cls.hasOwnProperty(PARAMETERS) ?
3763 cls[PARAMETERS] :
3764 Object.defineProperty(cls, PARAMETERS, { value: [] })[PARAMETERS];
3765 // there might be gaps if some in between parameters do not have annotations.
3766 // we pad with nulls.
3767 while (parameters.length <= index) {
3768 parameters.push(null);
3769 }
3770 (parameters[index] = parameters[index] || []).push(annotationInstance);
3771 return cls;
3772 }
3773 }
3774 if (parentClass) {
3775 ParamDecoratorFactory.prototype = Object.create(parentClass.prototype);
3776 }
3777 ParamDecoratorFactory.prototype.ngMetadataName = name;
3778 ParamDecoratorFactory.annotationCls = ParamDecoratorFactory;
3779 return ParamDecoratorFactory;
3780 });
3781}
3782function makePropDecorator(name, props, parentClass, additionalProcessing) {
3783 return noSideEffects(() => {
3784 const metaCtor = makeMetadataCtor(props);
3785 function PropDecoratorFactory(...args) {
3786 if (this instanceof PropDecoratorFactory) {
3787 metaCtor.apply(this, args);
3788 return this;
3789 }
3790 const decoratorInstance = new PropDecoratorFactory(...args);
3791 function PropDecorator(target, name) {
3792 const constructor = target.constructor;
3793 // Use of Object.defineProperty is important because it creates a non-enumerable property
3794 // which prevents the property from being copied during subclassing.
3795 const meta = constructor.hasOwnProperty(PROP_METADATA) ?
3796 constructor[PROP_METADATA] :
3797 Object.defineProperty(constructor, PROP_METADATA, { value: {} })[PROP_METADATA];
3798 meta[name] = meta.hasOwnProperty(name) && meta[name] || [];
3799 meta[name].unshift(decoratorInstance);
3800 if (additionalProcessing)
3801 additionalProcessing(target, name, ...args);
3802 }
3803 return PropDecorator;
3804 }
3805 if (parentClass) {
3806 PropDecoratorFactory.prototype = Object.create(parentClass.prototype);
3807 }
3808 PropDecoratorFactory.prototype.ngMetadataName = name;
3809 PropDecoratorFactory.annotationCls = PropDecoratorFactory;
3810 return PropDecoratorFactory;
3811 });
3812}
3813
3814/**
3815 * @license
3816 * Copyright Google LLC All Rights Reserved.
3817 *
3818 * Use of this source code is governed by an MIT-style license that can be
3819 * found in the LICENSE file at https://angular.io/license
3820 */
3821function CREATE_ATTRIBUTE_DECORATOR__PRE_R3__() {
3822 return makeParamDecorator('Attribute', (attributeName) => ({ attributeName }));
3823}
3824function CREATE_ATTRIBUTE_DECORATOR__POST_R3__() {
3825 return makeParamDecorator('Attribute', (attributeName) => ({ attributeName, __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName) }));
3826}
3827const CREATE_ATTRIBUTE_DECORATOR_IMPL = CREATE_ATTRIBUTE_DECORATOR__POST_R3__;
3828/**
3829 * Attribute decorator and metadata.
3830 *
3831 * @Annotation
3832 * @publicApi
3833 */
3834const Attribute = CREATE_ATTRIBUTE_DECORATOR_IMPL();
3835
3836/**
3837 * @license
3838 * Copyright Google LLC All Rights Reserved.
3839 *
3840 * Use of this source code is governed by an MIT-style license that can be
3841 * found in the LICENSE file at https://angular.io/license
3842 */
3843/**
3844 * Creates a token that can be used in a DI Provider.
3845 *
3846 * Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a
3847 * runtime representation) such as when injecting an interface, callable type, array or
3848 * parameterized type.
3849 *
3850 * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
3851 * the `Injector`. This provides an additional level of type safety.
3852 *
3853 * ```
3854 * interface MyInterface {...}
3855 * const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
3856 * // myInterface is inferred to be MyInterface.
3857 * ```
3858 *
3859 * When creating an `InjectionToken`, you can optionally specify a factory function which returns
3860 * (possibly by creating) a default value of the parameterized type `T`. This sets up the
3861 * `InjectionToken` using this factory as a provider as if it was defined explicitly in the
3862 * application's root injector. If the factory function, which takes zero arguments, needs to inject
3863 * dependencies, it can do so using the `inject` function.
3864 * As you can see in the Tree-shakable InjectionToken example below.
3865 *
3866 * Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
3867 * overrides the above behavior and marks the token as belonging to a particular `@NgModule`. As
3868 * mentioned above, `'root'` is the default value for `providedIn`.
3869 *
3870 * @usageNotes
3871 * ### Basic Examples
3872 *
3873 * ### Plain InjectionToken
3874 *
3875 * {@example core/di/ts/injector_spec.ts region='InjectionToken'}
3876 *
3877 * ### Tree-shakable InjectionToken
3878 *
3879 * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
3880 *
3881 *
3882 * @publicApi
3883 */
3884class InjectionToken {
3885 /**
3886 * @param _desc Description for the token,
3887 * used only for debugging purposes,
3888 * it should but does not need to be unique
3889 * @param options Options for the token's usage, as described above
3890 */
3891 constructor(_desc, options) {
3892 this._desc = _desc;
3893 /** @internal */
3894 this.ngMetadataName = 'InjectionToken';
3895 this.ɵprov = undefined;
3896 if (typeof options == 'number') {
3897 (typeof ngDevMode === 'undefined' || ngDevMode) &&
3898 assertLessThan(options, 0, 'Only negative numbers are supported here');
3899 // This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
3900 // See `InjectorMarkers`
3901 this.__NG_ELEMENT_ID__ = options;
3902 }
3903 else if (options !== undefined) {
3904 this.ɵprov = ɵɵdefineInjectable({
3905 token: this,
3906 providedIn: options.providedIn || 'root',
3907 factory: options.factory,
3908 });
3909 }
3910 }
3911 toString() {
3912 return `InjectionToken ${this._desc}`;
3913 }
3914}
3915
3916/**
3917 * @license
3918 * Copyright Google LLC All Rights Reserved.
3919 *
3920 * Use of this source code is governed by an MIT-style license that can be
3921 * found in the LICENSE file at https://angular.io/license
3922 */
3923/**
3924 * A DI token that you can use to create a virtual [provider](guide/glossary#provider)
3925 * that will populate the `entryComponents` field of components and NgModules
3926 * based on its `useValue` property value.
3927 * All components that are referenced in the `useValue` value (either directly
3928 * or in a nested array or map) are added to the `entryComponents` property.
3929 *
3930 * @usageNotes
3931 *
3932 * The following example shows how the router can populate the `entryComponents`
3933 * field of an NgModule based on a router configuration that refers
3934 * to components.
3935 *
3936 * ```typescript
3937 * // helper function inside the router
3938 * function provideRoutes(routes) {
3939 * return [
3940 * {provide: ROUTES, useValue: routes},
3941 * {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: routes, multi: true}
3942 * ];
3943 * }
3944 *
3945 * // user code
3946 * let routes = [
3947 * {path: '/root', component: RootComp},
3948 * {path: '/teams', component: TeamsComp}
3949 * ];
3950 *
3951 * @NgModule({
3952 * providers: [provideRoutes(routes)]
3953 * })
3954 * class ModuleWithRoutes {}
3955 * ```
3956 *
3957 * @publicApi
3958 * @deprecated Since 9.0.0. With Ivy, this property is no longer necessary.
3959 */
3960const ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken('AnalyzeForEntryComponents');
3961// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
3962// explicitly set.
3963const emitDistinctChangesOnlyDefaultValue = true;
3964/**
3965 * Base class for query metadata.
3966 *
3967 * @see `ContentChildren`.
3968 * @see `ContentChild`.
3969 * @see `ViewChildren`.
3970 * @see `ViewChild`.
3971 *
3972 * @publicApi
3973 */
3974class Query {
3975}
3976/**
3977 * ContentChildren decorator and metadata.
3978 *
3979 *
3980 * @Annotation
3981 * @publicApi
3982 */
3983const ContentChildren = makePropDecorator('ContentChildren', (selector, data = {}) => ({
3984 selector,
3985 first: false,
3986 isViewQuery: false,
3987 descendants: false,
3988 emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue,
3989 ...data
3990}), Query);
3991/**
3992 * ContentChild decorator and metadata.
3993 *
3994 *
3995 * @Annotation
3996 *
3997 * @publicApi
3998 */
3999const ContentChild = makePropDecorator('ContentChild', (selector, data = {}) => ({ selector, first: true, isViewQuery: false, descendants: true, ...data }), Query);
4000/**
4001 * ViewChildren decorator and metadata.
4002 *
4003 * @Annotation
4004 * @publicApi
4005 */
4006const ViewChildren = makePropDecorator('ViewChildren', (selector, data = {}) => ({
4007 selector,
4008 first: false,
4009 isViewQuery: true,
4010 descendants: true,
4011 emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue,
4012 ...data
4013}), Query);
4014/**
4015 * ViewChild decorator and metadata.
4016 *
4017 * @Annotation
4018 * @publicApi
4019 */
4020const ViewChild = makePropDecorator('ViewChild', (selector, data) => ({ selector, first: true, isViewQuery: true, descendants: true, ...data }), Query);
4021
4022/**
4023 * @license
4024 * Copyright Google LLC All Rights Reserved.
4025 *
4026 * Use of this source code is governed by an MIT-style license that can be
4027 * found in the LICENSE file at https://angular.io/license
4028 */
4029var FactoryTarget;
4030(function (FactoryTarget) {
4031 FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
4032 FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
4033 FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
4034 FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
4035 FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
4036})(FactoryTarget || (FactoryTarget = {}));
4037var ViewEncapsulation;
4038(function (ViewEncapsulation) {
4039 ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
4040 // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.
4041 ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
4042 ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
4043})(ViewEncapsulation || (ViewEncapsulation = {}));
4044
4045/**
4046 * @license
4047 * Copyright Google LLC All Rights Reserved.
4048 *
4049 * Use of this source code is governed by an MIT-style license that can be
4050 * found in the LICENSE file at https://angular.io/license
4051 */
4052function getCompilerFacade(request) {
4053 const globalNg = _global['ng'];
4054 if (globalNg && globalNg.ɵcompilerFacade) {
4055 return globalNg.ɵcompilerFacade;
4056 }
4057 if (typeof ngDevMode === 'undefined' || ngDevMode) {
4058 // Log the type as an error so that a developer can easily navigate to the type from the
4059 // console.
4060 console.error(`JIT compilation failed for ${request.kind}`, request.type);
4061 let message = `The ${request.kind} '${request
4062 .type.name}' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available.\n\n`;
4063 if (request.usage === 1 /* PartialDeclaration */) {
4064 message += `The ${request.kind} is part of a library that has been partially compiled.\n`;
4065 message +=
4066 `However, the Angular Linker has not processed the library such that JIT compilation is used as fallback.\n`;
4067 message += '\n';
4068 message +=
4069 `Ideally, the library is processed using the Angular Linker to become fully AOT compiled.\n`;
4070 }
4071 else {
4072 message +=
4073 `JIT compilation is discouraged for production use-cases! Consider using AOT mode instead.\n`;
4074 }
4075 message +=
4076 `Alternatively, the JIT compiler should be loaded by bootstrapping using '@angular/platform-browser-dynamic' or '@angular/platform-server',\n`;
4077 message +=
4078 `or manually provide the compiler with 'import "@angular/compiler";' before bootstrapping.`;
4079 throw new Error(message);
4080 }
4081 else {
4082 throw new Error('JIT compiler unavailable');
4083 }
4084}
4085
4086/**
4087 * @license
4088 * Copyright Google LLC All Rights Reserved.
4089 *
4090 * Use of this source code is governed by an MIT-style license that can be
4091 * found in the LICENSE file at https://angular.io/license
4092 */
4093/**
4094 * @description
4095 *
4096 * Represents a type that a Component or other object is instances of.
4097 *
4098 * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is represented by
4099 * the `MyCustomComponent` constructor function.
4100 *
4101 * @publicApi
4102 */
4103const Type = Function;
4104function isType(v) {
4105 return typeof v === 'function';
4106}
4107
4108/**
4109 * @license
4110 * Copyright Google LLC All Rights Reserved.
4111 *
4112 * Use of this source code is governed by an MIT-style license that can be
4113 * found in the LICENSE file at https://angular.io/license
4114 */
4115/**
4116 * Equivalent to ES6 spread, add each item to an array.
4117 *
4118 * @param items The items to add
4119 * @param arr The array to which you want to add the items
4120 */
4121function addAllToArray(items, arr) {
4122 for (let i = 0; i < items.length; i++) {
4123 arr.push(items[i]);
4124 }
4125}
4126/**
4127 * Determines if the contents of two arrays is identical
4128 *
4129 * @param a first array
4130 * @param b second array
4131 * @param identityAccessor Optional function for extracting stable object identity from a value in
4132 * the array.
4133 */
4134function arrayEquals(a, b, identityAccessor) {
4135 if (a.length !== b.length)
4136 return false;
4137 for (let i = 0; i < a.length; i++) {
4138 let valueA = a[i];
4139 let valueB = b[i];
4140 if (identityAccessor) {
4141 valueA = identityAccessor(valueA);
4142 valueB = identityAccessor(valueB);
4143 }
4144 if (valueB !== valueA) {
4145 return false;
4146 }
4147 }
4148 return true;
4149}
4150/**
4151 * Flattens an array.
4152 */
4153function flatten(list, dst) {
4154 if (dst === undefined)
4155 dst = list;
4156 for (let i = 0; i < list.length; i++) {
4157 let item = list[i];
4158 if (Array.isArray(item)) {
4159 // we need to inline it.
4160 if (dst === list) {
4161 // Our assumption that the list was already flat was wrong and
4162 // we need to clone flat since we need to write to it.
4163 dst = list.slice(0, i);
4164 }
4165 flatten(item, dst);
4166 }
4167 else if (dst !== list) {
4168 dst.push(item);
4169 }
4170 }
4171 return dst;
4172}
4173function deepForEach(input, fn) {
4174 input.forEach(value => Array.isArray(value) ? deepForEach(value, fn) : fn(value));
4175}
4176function addToArray(arr, index, value) {
4177 // perf: array.push is faster than array.splice!
4178 if (index >= arr.length) {
4179 arr.push(value);
4180 }
4181 else {
4182 arr.splice(index, 0, value);
4183 }
4184}
4185function removeFromArray(arr, index) {
4186 // perf: array.pop is faster than array.splice!
4187 if (index >= arr.length - 1) {
4188 return arr.pop();
4189 }
4190 else {
4191 return arr.splice(index, 1)[0];
4192 }
4193}
4194function newArray(size, value) {
4195 const list = [];
4196 for (let i = 0; i < size; i++) {
4197 list.push(value);
4198 }
4199 return list;
4200}
4201/**
4202 * Remove item from array (Same as `Array.splice()` but faster.)
4203 *
4204 * `Array.splice()` is not as fast because it has to allocate an array for the elements which were
4205 * removed. This causes memory pressure and slows down code when most of the time we don't
4206 * care about the deleted items array.
4207 *
4208 * https://jsperf.com/fast-array-splice (About 20x faster)
4209 *
4210 * @param array Array to splice
4211 * @param index Index of element in array to remove.
4212 * @param count Number of items to remove.
4213 */
4214function arraySplice(array, index, count) {
4215 const length = array.length - count;
4216 while (index < length) {
4217 array[index] = array[index + count];
4218 index++;
4219 }
4220 while (count--) {
4221 array.pop(); // shrink the array
4222 }
4223}
4224/**
4225 * Same as `Array.splice(index, 0, value)` but faster.
4226 *
4227 * `Array.splice()` is not fast because it has to allocate an array for the elements which were
4228 * removed. This causes memory pressure and slows down code when most of the time we don't
4229 * care about the deleted items array.
4230 *
4231 * @param array Array to splice.
4232 * @param index Index in array where the `value` should be added.
4233 * @param value Value to add to array.
4234 */
4235function arrayInsert(array, index, value) {
4236 ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.');
4237 let end = array.length;
4238 while (end > index) {
4239 const previousEnd = end - 1;
4240 array[end] = array[previousEnd];
4241 end = previousEnd;
4242 }
4243 array[index] = value;
4244}
4245/**
4246 * Same as `Array.splice2(index, 0, value1, value2)` but faster.
4247 *
4248 * `Array.splice()` is not fast because it has to allocate an array for the elements which were
4249 * removed. This causes memory pressure and slows down code when most of the time we don't
4250 * care about the deleted items array.
4251 *
4252 * @param array Array to splice.
4253 * @param index Index in array where the `value` should be added.
4254 * @param value1 Value to add to array.
4255 * @param value2 Value to add to array.
4256 */
4257function arrayInsert2(array, index, value1, value2) {
4258 ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.');
4259 let end = array.length;
4260 if (end == index) {
4261 // inserting at the end.
4262 array.push(value1, value2);
4263 }
4264 else if (end === 1) {
4265 // corner case when we have less items in array than we have items to insert.
4266 array.push(value2, array[0]);
4267 array[0] = value1;
4268 }
4269 else {
4270 end--;
4271 array.push(array[end - 1], array[end]);
4272 while (end > index) {
4273 const previousEnd = end - 2;
4274 array[end] = array[previousEnd];
4275 end--;
4276 }
4277 array[index] = value1;
4278 array[index + 1] = value2;
4279 }
4280}
4281/**
4282 * Insert a `value` into an `array` so that the array remains sorted.
4283 *
4284 * NOTE:
4285 * - Duplicates are not allowed, and are ignored.
4286 * - This uses binary search algorithm for fast inserts.
4287 *
4288 * @param array A sorted array to insert into.
4289 * @param value The value to insert.
4290 * @returns index of the inserted value.
4291 */
4292function arrayInsertSorted(array, value) {
4293 let index = arrayIndexOfSorted(array, value);
4294 if (index < 0) {
4295 // if we did not find it insert it.
4296 index = ~index;
4297 arrayInsert(array, index, value);
4298 }
4299 return index;
4300}
4301/**
4302 * Remove `value` from a sorted `array`.
4303 *
4304 * NOTE:
4305 * - This uses binary search algorithm for fast removals.
4306 *
4307 * @param array A sorted array to remove from.
4308 * @param value The value to remove.
4309 * @returns index of the removed value.
4310 * - positive index if value found and removed.
4311 * - negative index if value not found. (`~index` to get the value where it should have been
4312 * inserted)
4313 */
4314function arrayRemoveSorted(array, value) {
4315 const index = arrayIndexOfSorted(array, value);
4316 if (index >= 0) {
4317 arraySplice(array, index, 1);
4318 }
4319 return index;
4320}
4321/**
4322 * Get an index of an `value` in a sorted `array`.
4323 *
4324 * NOTE:
4325 * - This uses binary search algorithm for fast removals.
4326 *
4327 * @param array A sorted array to binary search.
4328 * @param value The value to look for.
4329 * @returns index of the value.
4330 * - positive index if value found.
4331 * - negative index if value not found. (`~index` to get the value where it should have been
4332 * located)
4333 */
4334function arrayIndexOfSorted(array, value) {
4335 return _arrayIndexOfSorted(array, value, 0);
4336}
4337/**
4338 * Set a `value` for a `key`.
4339 *
4340 * @param keyValueArray to modify.
4341 * @param key The key to locate or create.
4342 * @param value The value to set for a `key`.
4343 * @returns index (always even) of where the value vas set.
4344 */
4345function keyValueArraySet(keyValueArray, key, value) {
4346 let index = keyValueArrayIndexOf(keyValueArray, key);
4347 if (index >= 0) {
4348 // if we found it set it.
4349 keyValueArray[index | 1] = value;
4350 }
4351 else {
4352 index = ~index;
4353 arrayInsert2(keyValueArray, index, key, value);
4354 }
4355 return index;
4356}
4357/**
4358 * Retrieve a `value` for a `key` (on `undefined` if not found.)
4359 *
4360 * @param keyValueArray to search.
4361 * @param key The key to locate.
4362 * @return The `value` stored at the `key` location or `undefined if not found.
4363 */
4364function keyValueArrayGet(keyValueArray, key) {
4365 const index = keyValueArrayIndexOf(keyValueArray, key);
4366 if (index >= 0) {
4367 // if we found it retrieve it.
4368 return keyValueArray[index | 1];
4369 }
4370 return undefined;
4371}
4372/**
4373 * Retrieve a `key` index value in the array or `-1` if not found.
4374 *
4375 * @param keyValueArray to search.
4376 * @param key The key to locate.
4377 * @returns index of where the key is (or should have been.)
4378 * - positive (even) index if key found.
4379 * - negative index if key not found. (`~index` (even) to get the index where it should have
4380 * been inserted.)
4381 */
4382function keyValueArrayIndexOf(keyValueArray, key) {
4383 return _arrayIndexOfSorted(keyValueArray, key, 1);
4384}
4385/**
4386 * Delete a `key` (and `value`) from the `KeyValueArray`.
4387 *
4388 * @param keyValueArray to modify.
4389 * @param key The key to locate or delete (if exist).
4390 * @returns index of where the key was (or should have been.)
4391 * - positive (even) index if key found and deleted.
4392 * - negative index if key not found. (`~index` (even) to get the index where it should have
4393 * been.)
4394 */
4395function keyValueArrayDelete(keyValueArray, key) {
4396 const index = keyValueArrayIndexOf(keyValueArray, key);
4397 if (index >= 0) {
4398 // if we found it remove it.
4399 arraySplice(keyValueArray, index, 2);
4400 }
4401 return index;
4402}
4403/**
4404 * INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`.
4405 *
4406 * NOTE:
4407 * - This uses binary search algorithm for fast removals.
4408 *
4409 * @param array A sorted array to binary search.
4410 * @param value The value to look for.
4411 * @param shift grouping shift.
4412 * - `0` means look at every location
4413 * - `1` means only look at every other (even) location (the odd locations are to be ignored as
4414 * they are values.)
4415 * @returns index of the value.
4416 * - positive index if value found.
4417 * - negative index if value not found. (`~index` to get the value where it should have been
4418 * inserted)
4419 */
4420function _arrayIndexOfSorted(array, value, shift) {
4421 ngDevMode && assertEqual(Array.isArray(array), true, 'Expecting an array');
4422 let start = 0;
4423 let end = array.length >> shift;
4424 while (end !== start) {
4425 const middle = start + ((end - start) >> 1); // find the middle.
4426 const current = array[middle << shift];
4427 if (value === current) {
4428 return (middle << shift);
4429 }
4430 else if (current > value) {
4431 end = middle;
4432 }
4433 else {
4434 start = middle + 1; // We already searched middle so make it non-inclusive by adding 1
4435 }
4436 }
4437 return ~(end << shift);
4438}
4439
4440/**
4441 * @license
4442 * Copyright Google LLC All Rights Reserved.
4443 *
4444 * Use of this source code is governed by an MIT-style license that can be
4445 * found in the LICENSE file at https://angular.io/license
4446 */
4447/*
4448 * #########################
4449 * Attention: These Regular expressions have to hold even if the code is minified!
4450 * ##########################
4451 */
4452/**
4453 * Regular expression that detects pass-through constructors for ES5 output. This Regex
4454 * intends to capture the common delegation pattern emitted by TypeScript and Babel. Also
4455 * it intends to capture the pattern where existing constructors have been downleveled from
4456 * ES2015 to ES5 using TypeScript w/ downlevel iteration. e.g.
4457 *
4458 * ```
4459 * function MyClass() {
4460 * var _this = _super.apply(this, arguments) || this;
4461 * ```
4462 *
4463 * downleveled to ES5 with `downlevelIteration` for TypeScript < 4.2:
4464 * ```
4465 * function MyClass() {
4466 * var _this = _super.apply(this, __spread(arguments)) || this;
4467 * ```
4468 *
4469 * or downleveled to ES5 with `downlevelIteration` for TypeScript >= 4.2:
4470 * ```
4471 * function MyClass() {
4472 * var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
4473 * ```
4474 *
4475 * More details can be found in: https://github.com/angular/angular/issues/38453.
4476 */
4477const ES5_DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*(arguments|(?:[^()]+\(\[\],)?[^()]+\(arguments\).*)\)/;
4478/** Regular expression that detects ES2015 classes which extend from other classes. */
4479const ES2015_INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
4480/**
4481 * Regular expression that detects ES2015 classes which extend from other classes and
4482 * have an explicit constructor defined.
4483 */
4484const ES2015_INHERITED_CLASS_WITH_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/;
4485/**
4486 * Regular expression that detects ES2015 classes which extend from other classes
4487 * and inherit a constructor.
4488 */
4489const ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(\)\s*{\s*super\(\.\.\.arguments\)/;
4490/**
4491 * Determine whether a stringified type is a class which delegates its constructor
4492 * to its parent.
4493 *
4494 * This is not trivial since compiled code can actually contain a constructor function
4495 * even if the original source code did not. For instance, when the child class contains
4496 * an initialized instance property.
4497 */
4498function isDelegateCtor(typeStr) {
4499 return ES5_DELEGATE_CTOR.test(typeStr) ||
4500 ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR.test(typeStr) ||
4501 (ES2015_INHERITED_CLASS.test(typeStr) && !ES2015_INHERITED_CLASS_WITH_CTOR.test(typeStr));
4502}
4503class ReflectionCapabilities {
4504 constructor(reflect) {
4505 this._reflect = reflect || _global['Reflect'];
4506 }
4507 isReflectionEnabled() {
4508 return true;
4509 }
4510 factory(t) {
4511 return (...args) => new t(...args);
4512 }
4513 /** @internal */
4514 _zipTypesAndAnnotations(paramTypes, paramAnnotations) {
4515 let result;
4516 if (typeof paramTypes === 'undefined') {
4517 result = newArray(paramAnnotations.length);
4518 }
4519 else {
4520 result = newArray(paramTypes.length);
4521 }
4522 for (let i = 0; i < result.length; i++) {
4523 // TS outputs Object for parameters without types, while Traceur omits
4524 // the annotations. For now we preserve the Traceur behavior to aid
4525 // migration, but this can be revisited.
4526 if (typeof paramTypes === 'undefined') {
4527 result[i] = [];
4528 }
4529 else if (paramTypes[i] && paramTypes[i] != Object) {
4530 result[i] = [paramTypes[i]];
4531 }
4532 else {
4533 result[i] = [];
4534 }
4535 if (paramAnnotations && paramAnnotations[i] != null) {
4536 result[i] = result[i].concat(paramAnnotations[i]);
4537 }
4538 }
4539 return result;
4540 }
4541 _ownParameters(type, parentCtor) {
4542 const typeStr = type.toString();
4543 // If we have no decorators, we only have function.length as metadata.
4544 // In that case, to detect whether a child class declared an own constructor or not,
4545 // we need to look inside of that constructor to check whether it is
4546 // just calling the parent.
4547 // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439
4548 // that sets 'design:paramtypes' to []
4549 // if a class inherits from another class but has no ctor declared itself.
4550 if (isDelegateCtor(typeStr)) {
4551 return null;
4552 }
4553 // Prefer the direct API.
4554 if (type.parameters && type.parameters !== parentCtor.parameters) {
4555 return type.parameters;
4556 }
4557 // API of tsickle for lowering decorators to properties on the class.
4558 const tsickleCtorParams = type.ctorParameters;
4559 if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) {
4560 // Newer tsickle uses a function closure
4561 // Retain the non-function case for compatibility with older tsickle
4562 const ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams;
4563 const paramTypes = ctorParameters.map((ctorParam) => ctorParam && ctorParam.type);
4564 const paramAnnotations = ctorParameters.map((ctorParam) => ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators));
4565 return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
4566 }
4567 // API for metadata created by invoking the decorators.
4568 const paramAnnotations = type.hasOwnProperty(PARAMETERS) && type[PARAMETERS];
4569 const paramTypes = this._reflect && this._reflect.getOwnMetadata &&
4570 this._reflect.getOwnMetadata('design:paramtypes', type);
4571 if (paramTypes || paramAnnotations) {
4572 return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
4573 }
4574 // If a class has no decorators, at least create metadata
4575 // based on function.length.
4576 // Note: We know that this is a real constructor as we checked
4577 // the content of the constructor above.
4578 return newArray(type.length);
4579 }
4580 parameters(type) {
4581 // Note: only report metadata if we have at least one class decorator
4582 // to stay in sync with the static reflector.
4583 if (!isType(type)) {
4584 return [];
4585 }
4586 const parentCtor = getParentCtor(type);
4587 let parameters = this._ownParameters(type, parentCtor);
4588 if (!parameters && parentCtor !== Object) {
4589 parameters = this.parameters(parentCtor);
4590 }
4591 return parameters || [];
4592 }
4593 _ownAnnotations(typeOrFunc, parentCtor) {
4594 // Prefer the direct API.
4595 if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) {
4596 let annotations = typeOrFunc.annotations;
4597 if (typeof annotations === 'function' && annotations.annotations) {
4598 annotations = annotations.annotations;
4599 }
4600 return annotations;
4601 }
4602 // API of tsickle for lowering decorators to properties on the class.
4603 if (typeOrFunc.decorators && typeOrFunc.decorators !== parentCtor.decorators) {
4604 return convertTsickleDecoratorIntoMetadata(typeOrFunc.decorators);
4605 }
4606 // API for metadata created by invoking the decorators.
4607 if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
4608 return typeOrFunc[ANNOTATIONS];
4609 }
4610 return null;
4611 }
4612 annotations(typeOrFunc) {
4613 if (!isType(typeOrFunc)) {
4614 return [];
4615 }
4616 const parentCtor = getParentCtor(typeOrFunc);
4617 const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
4618 const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
4619 return parentAnnotations.concat(ownAnnotations);
4620 }
4621 _ownPropMetadata(typeOrFunc, parentCtor) {
4622 // Prefer the direct API.
4623 if (typeOrFunc.propMetadata &&
4624 typeOrFunc.propMetadata !== parentCtor.propMetadata) {
4625 let propMetadata = typeOrFunc.propMetadata;
4626 if (typeof propMetadata === 'function' && propMetadata.propMetadata) {
4627 propMetadata = propMetadata.propMetadata;
4628 }
4629 return propMetadata;
4630 }
4631 // API of tsickle for lowering decorators to properties on the class.
4632 if (typeOrFunc.propDecorators &&
4633 typeOrFunc.propDecorators !== parentCtor.propDecorators) {
4634 const propDecorators = typeOrFunc.propDecorators;
4635 const propMetadata = {};
4636 Object.keys(propDecorators).forEach(prop => {
4637 propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]);
4638 });
4639 return propMetadata;
4640 }
4641 // API for metadata created by invoking the decorators.
4642 if (typeOrFunc.hasOwnProperty(PROP_METADATA)) {
4643 return typeOrFunc[PROP_METADATA];
4644 }
4645 return null;
4646 }
4647 propMetadata(typeOrFunc) {
4648 if (!isType(typeOrFunc)) {
4649 return {};
4650 }
4651 const parentCtor = getParentCtor(typeOrFunc);
4652 const propMetadata = {};
4653 if (parentCtor !== Object) {
4654 const parentPropMetadata = this.propMetadata(parentCtor);
4655 Object.keys(parentPropMetadata).forEach((propName) => {
4656 propMetadata[propName] = parentPropMetadata[propName];
4657 });
4658 }
4659 const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor);
4660 if (ownPropMetadata) {
4661 Object.keys(ownPropMetadata).forEach((propName) => {
4662 const decorators = [];
4663 if (propMetadata.hasOwnProperty(propName)) {
4664 decorators.push(...propMetadata[propName]);
4665 }
4666 decorators.push(...ownPropMetadata[propName]);
4667 propMetadata[propName] = decorators;
4668 });
4669 }
4670 return propMetadata;
4671 }
4672 ownPropMetadata(typeOrFunc) {
4673 if (!isType(typeOrFunc)) {
4674 return {};
4675 }
4676 return this._ownPropMetadata(typeOrFunc, getParentCtor(typeOrFunc)) || {};
4677 }
4678 hasLifecycleHook(type, lcProperty) {
4679 return type instanceof Type && lcProperty in type.prototype;
4680 }
4681 guards(type) {
4682 return {};
4683 }
4684 getter(name) {
4685 return new Function('o', 'return o.' + name + ';');
4686 }
4687 setter(name) {
4688 return new Function('o', 'v', 'return o.' + name + ' = v;');
4689 }
4690 method(name) {
4691 const functionBody = `if (!o.${name}) throw new Error('"${name}" is undefined');
4692 return o.${name}.apply(o, args);`;
4693 return new Function('o', 'args', functionBody);
4694 }
4695 // There is not a concept of import uri in Js, but this is useful in developing Dart applications.
4696 importUri(type) {
4697 // StaticSymbol
4698 if (typeof type === 'object' && type['filePath']) {
4699 return type['filePath'];
4700 }
4701 // Runtime type
4702 return `./${stringify(type)}`;
4703 }
4704 resourceUri(type) {
4705 return `./${stringify(type)}`;
4706 }
4707 resolveIdentifier(name, moduleUrl, members, runtime) {
4708 return runtime;
4709 }
4710 resolveEnum(enumIdentifier, name) {
4711 return enumIdentifier[name];
4712 }
4713}
4714function convertTsickleDecoratorIntoMetadata(decoratorInvocations) {
4715 if (!decoratorInvocations) {
4716 return [];
4717 }
4718 return decoratorInvocations.map(decoratorInvocation => {
4719 const decoratorType = decoratorInvocation.type;
4720 const annotationCls = decoratorType.annotationCls;
4721 const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
4722 return new annotationCls(...annotationArgs);
4723 });
4724}
4725function getParentCtor(ctor) {
4726 const parentProto = ctor.prototype ? Object.getPrototypeOf(ctor.prototype) : null;
4727 const parentCtor = parentProto ? parentProto.constructor : null;
4728 // Note: We always use `Object` as the null value
4729 // to simplify checking later on.
4730 return parentCtor || Object;
4731}
4732
4733/**
4734 * @license
4735 * Copyright Google LLC All Rights Reserved.
4736 *
4737 * Use of this source code is governed by an MIT-style license that can be
4738 * found in the LICENSE file at https://angular.io/license
4739 */
4740const _THROW_IF_NOT_FOUND = {};
4741const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
4742/*
4743 * Name of a property (that we patch onto DI decorator), which is used as an annotation of which
4744 * InjectFlag this decorator represents. This allows to avoid direct references to the DI decorators
4745 * in the code, thus making them tree-shakable.
4746 */
4747const DI_DECORATOR_FLAG = '__NG_DI_FLAG__';
4748const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
4749const NG_TOKEN_PATH = 'ngTokenPath';
4750const NEW_LINE = /\n/gm;
4751const NO_NEW_LINE$1 = 'ɵ';
4752const SOURCE = '__source';
4753const USE_VALUE$2 = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
4754/**
4755 * Current injector value used by `inject`.
4756 * - `undefined`: it is an error to call `inject`
4757 * - `null`: `inject` can be called but there is no injector (limp-mode).
4758 * - Injector instance: Use the injector for resolution.
4759 */
4760let _currentInjector = undefined;
4761function setCurrentInjector(injector) {
4762 const former = _currentInjector;
4763 _currentInjector = injector;
4764 return former;
4765}
4766function injectInjectorOnly(token, flags = InjectFlags.Default) {
4767 if (_currentInjector === undefined) {
4768 throw new Error(`inject() must be called from an injection context`);
4769 }
4770 else if (_currentInjector === null) {
4771 return injectRootLimpMode(token, undefined, flags);
4772 }
4773 else {
4774 return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags);
4775 }
4776}
4777function ɵɵinject(token, flags = InjectFlags.Default) {
4778 return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags);
4779}
4780/**
4781 * Throws an error indicating that a factory function could not be generated by the compiler for a
4782 * particular class.
4783 *
4784 * This instruction allows the actual error message to be optimized away when ngDevMode is turned
4785 * off, saving bytes of generated code while still providing a good experience in dev mode.
4786 *
4787 * The name of the class is not mentioned here, but will be in the generated factory function name
4788 * and thus in the stack trace.
4789 *
4790 * @codeGenApi
4791 */
4792function ɵɵinvalidFactoryDep(index) {
4793 const msg = ngDevMode ?
4794 `This constructor is not compatible with Angular Dependency Injection because its dependency at index ${index} of the parameter list is invalid.
4795This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
4796
4797Please check that 1) the type for the parameter at index ${index} is correct and 2) the correct Angular decorators are defined for this class and its ancestors.` :
4798 'invalid';
4799 throw new Error(msg);
4800}
4801/**
4802 * Injects a token from the currently active injector.
4803 *
4804 * Must be used in the context of a factory function such as one defined for an
4805 * `InjectionToken`. Throws an error if not called from such a context.
4806 *
4807 * Within such a factory function, using this function to request injection of a dependency
4808 * is faster and more type-safe than providing an additional array of dependencies
4809 * (as has been common with `useFactory` providers).
4810 *
4811 * @param token The injection token for the dependency to be injected.
4812 * @param flags Optional flags that control how injection is executed.
4813 * The flags correspond to injection strategies that can be specified with
4814 * parameter decorators `@Host`, `@Self`, `@SkipSef`, and `@Optional`.
4815 * @returns the injected value if injection is successful, `null` otherwise.
4816 *
4817 * @usageNotes
4818 *
4819 * ### Example
4820 *
4821 * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
4822 *
4823 * @publicApi
4824 */
4825const inject = ɵɵinject;
4826function injectArgs(types) {
4827 const args = [];
4828 for (let i = 0; i < types.length; i++) {
4829 const arg = resolveForwardRef(types[i]);
4830 if (Array.isArray(arg)) {
4831 if (arg.length === 0) {
4832 throw new Error('Arguments array must have arguments.');
4833 }
4834 let type = undefined;
4835 let flags = InjectFlags.Default;
4836 for (let j = 0; j < arg.length; j++) {
4837 const meta = arg[j];
4838 const flag = getInjectFlag(meta);
4839 if (typeof flag === 'number') {
4840 // Special case when we handle @Inject decorator.
4841 if (flag === -1 /* Inject */) {
4842 type = meta.token;
4843 }
4844 else {
4845 flags |= flag;
4846 }
4847 }
4848 else {
4849 type = meta;
4850 }
4851 }
4852 args.push(ɵɵinject(type, flags));
4853 }
4854 else {
4855 args.push(ɵɵinject(arg));
4856 }
4857 }
4858 return args;
4859}
4860/**
4861 * Attaches a given InjectFlag to a given decorator using monkey-patching.
4862 * Since DI decorators can be used in providers `deps` array (when provider is configured using
4863 * `useFactory`) without initialization (e.g. `Host`) and as an instance (e.g. `new Host()`), we
4864 * attach the flag to make it available both as a static property and as a field on decorator
4865 * instance.
4866 *
4867 * @param decorator Provided DI decorator.
4868 * @param flag InjectFlag that should be applied.
4869 */
4870function attachInjectFlag(decorator, flag) {
4871 decorator[DI_DECORATOR_FLAG] = flag;
4872 decorator.prototype[DI_DECORATOR_FLAG] = flag;
4873 return decorator;
4874}
4875/**
4876 * Reads monkey-patched property that contains InjectFlag attached to a decorator.
4877 *
4878 * @param token Token that may contain monkey-patched DI flags property.
4879 */
4880function getInjectFlag(token) {
4881 return token[DI_DECORATOR_FLAG];
4882}
4883function catchInjectorError(e, token, injectorErrorName, source) {
4884 const tokenPath = e[NG_TEMP_TOKEN_PATH];
4885 if (token[SOURCE]) {
4886 tokenPath.unshift(token[SOURCE]);
4887 }
4888 e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source);
4889 e[NG_TOKEN_PATH] = tokenPath;
4890 e[NG_TEMP_TOKEN_PATH] = null;
4891 throw e;
4892}
4893function formatError(text, obj, injectorErrorName, source = null) {
4894 text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE$1 ? text.substr(2) : text;
4895 let context = stringify(obj);
4896 if (Array.isArray(obj)) {
4897 context = obj.map(stringify).join(' -> ');
4898 }
4899 else if (typeof obj === 'object') {
4900 let parts = [];
4901 for (let key in obj) {
4902 if (obj.hasOwnProperty(key)) {
4903 let value = obj[key];
4904 parts.push(key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value)));
4905 }
4906 }
4907 context = `{${parts.join(', ')}}`;
4908 }
4909 return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n ')}`;
4910}
4911
4912/**
4913 * @license
4914 * Copyright Google LLC All Rights Reserved.
4915 *
4916 * Use of this source code is governed by an MIT-style license that can be
4917 * found in the LICENSE file at https://angular.io/license
4918 */
4919/**
4920 * Inject decorator and metadata.
4921 *
4922 * @Annotation
4923 * @publicApi
4924 */
4925const Inject = attachInjectFlag(
4926// Disable tslint because `DecoratorFlags` is a const enum which gets inlined.
4927// tslint:disable-next-line: no-toplevel-property-access
4928makeParamDecorator('Inject', (token) => ({ token })), -1 /* Inject */);
4929/**
4930 * Optional decorator and metadata.
4931 *
4932 * @Annotation
4933 * @publicApi
4934 */
4935const Optional =
4936// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4937// tslint:disable-next-line: no-toplevel-property-access
4938attachInjectFlag(makeParamDecorator('Optional'), 8 /* Optional */);
4939/**
4940 * Self decorator and metadata.
4941 *
4942 * @Annotation
4943 * @publicApi
4944 */
4945const Self =
4946// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4947// tslint:disable-next-line: no-toplevel-property-access
4948attachInjectFlag(makeParamDecorator('Self'), 2 /* Self */);
4949/**
4950 * `SkipSelf` decorator and metadata.
4951 *
4952 * @Annotation
4953 * @publicApi
4954 */
4955const SkipSelf =
4956// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4957// tslint:disable-next-line: no-toplevel-property-access
4958attachInjectFlag(makeParamDecorator('SkipSelf'), 4 /* SkipSelf */);
4959/**
4960 * Host decorator and metadata.
4961 *
4962 * @Annotation
4963 * @publicApi
4964 */
4965const Host =
4966// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4967// tslint:disable-next-line: no-toplevel-property-access
4968attachInjectFlag(makeParamDecorator('Host'), 1 /* Host */);
4969
4970/**
4971 * @license
4972 * Copyright Google LLC All Rights Reserved.
4973 *
4974 * Use of this source code is governed by an MIT-style license that can be
4975 * found in the LICENSE file at https://angular.io/license
4976 */
4977let _reflect = null;
4978function getReflect() {
4979 return (_reflect = _reflect || new ReflectionCapabilities());
4980}
4981function reflectDependencies(type) {
4982 return convertDependencies(getReflect().parameters(type));
4983}
4984function convertDependencies(deps) {
4985 return deps.map(dep => reflectDependency(dep));
4986}
4987function reflectDependency(dep) {
4988 const meta = {
4989 token: null,
4990 attribute: null,
4991 host: false,
4992 optional: false,
4993 self: false,
4994 skipSelf: false,
4995 };
4996 if (Array.isArray(dep) && dep.length > 0) {
4997 for (let j = 0; j < dep.length; j++) {
4998 const param = dep[j];
4999 if (param === undefined) {
5000 // param may be undefined if type of dep is not set by ngtsc
5001 continue;
5002 }
5003 const proto = Object.getPrototypeOf(param);
5004 if (param instanceof Optional || proto.ngMetadataName === 'Optional') {
5005 meta.optional = true;
5006 }
5007 else if (param instanceof SkipSelf || proto.ngMetadataName === 'SkipSelf') {
5008 meta.skipSelf = true;
5009 }
5010 else if (param instanceof Self || proto.ngMetadataName === 'Self') {
5011 meta.self = true;
5012 }
5013 else if (param instanceof Host || proto.ngMetadataName === 'Host') {
5014 meta.host = true;
5015 }
5016 else if (param instanceof Inject) {
5017 meta.token = param.token;
5018 }
5019 else if (param instanceof Attribute) {
5020 if (param.attributeName === undefined) {
5021 throw new Error(`Attribute name must be defined.`);
5022 }
5023 meta.attribute = param.attributeName;
5024 }
5025 else {
5026 meta.token = param;
5027 }
5028 }
5029 }
5030 else if (dep === undefined || (Array.isArray(dep) && dep.length === 0)) {
5031 meta.token = null;
5032 }
5033 else {
5034 meta.token = dep;
5035 }
5036 return meta;
5037}
5038
5039/**
5040 * @license
5041 * Copyright Google LLC All Rights Reserved.
5042 *
5043 * Use of this source code is governed by an MIT-style license that can be
5044 * found in the LICENSE file at https://angular.io/license
5045 */
5046/**
5047 * Used to resolve resource URLs on `@Component` when used with JIT compilation.
5048 *
5049 * Example:
5050 * ```
5051 * @Component({
5052 * selector: 'my-comp',
5053 * templateUrl: 'my-comp.html', // This requires asynchronous resolution
5054 * })
5055 * class MyComponent{
5056 * }
5057 *
5058 * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process
5059 * // and `MyComponent`'s `@Component.templateUrl` needs to be resolved asynchronously.
5060 *
5061 * // Calling `resolveComponentResources()` will resolve `@Component.templateUrl` into
5062 * // `@Component.template`, which allows `renderComponent` to proceed in a synchronous manner.
5063 *
5064 * // Use browser's `fetch()` function as the default resource resolution strategy.
5065 * resolveComponentResources(fetch).then(() => {
5066 * // After resolution all URLs have been converted into `template` strings.
5067 * renderComponent(MyComponent);
5068 * });
5069 *
5070 * ```
5071 *
5072 * NOTE: In AOT the resolution happens during compilation, and so there should be no need
5073 * to call this method outside JIT mode.
5074 *
5075 * @param resourceResolver a function which is responsible for returning a `Promise` to the
5076 * contents of the resolved URL. Browser's `fetch()` method is a good default implementation.
5077 */
5078function resolveComponentResources(resourceResolver) {
5079 // Store all promises which are fetching the resources.
5080 const componentResolved = [];
5081 // Cache so that we don't fetch the same resource more than once.
5082 const urlMap = new Map();
5083 function cachedResourceResolve(url) {
5084 let promise = urlMap.get(url);
5085 if (!promise) {
5086 const resp = resourceResolver(url);
5087 urlMap.set(url, promise = resp.then(unwrapResponse));
5088 }
5089 return promise;
5090 }
5091 componentResourceResolutionQueue.forEach((component, type) => {
5092 const promises = [];
5093 if (component.templateUrl) {
5094 promises.push(cachedResourceResolve(component.templateUrl).then((template) => {
5095 component.template = template;
5096 }));
5097 }
5098 const styleUrls = component.styleUrls;
5099 const styles = component.styles || (component.styles = []);
5100 const styleOffset = component.styles.length;
5101 styleUrls && styleUrls.forEach((styleUrl, index) => {
5102 styles.push(''); // pre-allocate array.
5103 promises.push(cachedResourceResolve(styleUrl).then((style) => {
5104 styles[styleOffset + index] = style;
5105 styleUrls.splice(styleUrls.indexOf(styleUrl), 1);
5106 if (styleUrls.length == 0) {
5107 component.styleUrls = undefined;
5108 }
5109 }));
5110 });
5111 const fullyResolved = Promise.all(promises).then(() => componentDefResolved(type));
5112 componentResolved.push(fullyResolved);
5113 });
5114 clearResolutionOfComponentResourcesQueue();
5115 return Promise.all(componentResolved).then(() => undefined);
5116}
5117let componentResourceResolutionQueue = new Map();
5118// Track when existing ɵcmp for a Type is waiting on resources.
5119const componentDefPendingResolution = new Set();
5120function maybeQueueResolutionOfComponentResources(type, metadata) {
5121 if (componentNeedsResolution(metadata)) {
5122 componentResourceResolutionQueue.set(type, metadata);
5123 componentDefPendingResolution.add(type);
5124 }
5125}
5126function isComponentDefPendingResolution(type) {
5127 return componentDefPendingResolution.has(type);
5128}
5129function componentNeedsResolution(component) {
5130 return !!((component.templateUrl && !component.hasOwnProperty('template')) ||
5131 component.styleUrls && component.styleUrls.length);
5132}
5133function clearResolutionOfComponentResourcesQueue() {
5134 const old = componentResourceResolutionQueue;
5135 componentResourceResolutionQueue = new Map();
5136 return old;
5137}
5138function restoreComponentResolutionQueue(queue) {
5139 componentDefPendingResolution.clear();
5140 queue.forEach((_, type) => componentDefPendingResolution.add(type));
5141 componentResourceResolutionQueue = queue;
5142}
5143function isComponentResourceResolutionQueueEmpty() {
5144 return componentResourceResolutionQueue.size === 0;
5145}
5146function unwrapResponse(response) {
5147 return typeof response == 'string' ? response : response.text();
5148}
5149function componentDefResolved(type) {
5150 componentDefPendingResolution.delete(type);
5151}
5152
5153/**
5154 * @license
5155 * Copyright Google LLC All Rights Reserved.
5156 *
5157 * Use of this source code is governed by an MIT-style license that can be
5158 * found in the LICENSE file at https://angular.io/license
5159 */
5160/**
5161 * The Trusted Types policy, or null if Trusted Types are not
5162 * enabled/supported, or undefined if the policy has not been created yet.
5163 */
5164let policy$1;
5165/**
5166 * Returns the Trusted Types policy, or null if Trusted Types are not
5167 * enabled/supported. The first call to this function will create the policy.
5168 */
5169function getPolicy$1() {
5170 if (policy$1 === undefined) {
5171 policy$1 = null;
5172 if (_global.trustedTypes) {
5173 try {
5174 policy$1 = _global.trustedTypes.createPolicy('angular', {
5175 createHTML: (s) => s,
5176 createScript: (s) => s,
5177 createScriptURL: (s) => s,
5178 });
5179 }
5180 catch {
5181 // trustedTypes.createPolicy throws if called with a name that is
5182 // already registered, even in report-only mode. Until the API changes,
5183 // catch the error not to break the applications functionally. In such
5184 // cases, the code will fall back to using strings.
5185 }
5186 }
5187 }
5188 return policy$1;
5189}
5190/**
5191 * Unsafely promote a string to a TrustedHTML, falling back to strings when
5192 * Trusted Types are not available.
5193 * @security This is a security-sensitive function; any use of this function
5194 * must go through security review. In particular, it must be assured that the
5195 * provided string will never cause an XSS vulnerability if used in a context
5196 * that will be interpreted as HTML by a browser, e.g. when assigning to
5197 * element.innerHTML.
5198 */
5199function trustedHTMLFromString(html) {
5200 return getPolicy$1()?.createHTML(html) || html;
5201}
5202/**
5203 * Unsafely promote a string to a TrustedScript, falling back to strings when
5204 * Trusted Types are not available.
5205 * @security In particular, it must be assured that the provided string will
5206 * never cause an XSS vulnerability if used in a context that will be
5207 * interpreted and executed as a script by a browser, e.g. when calling eval.
5208 */
5209function trustedScriptFromString(script) {
5210 return getPolicy$1()?.createScript(script) || script;
5211}
5212/**
5213 * Unsafely promote a string to a TrustedScriptURL, falling back to strings
5214 * when Trusted Types are not available.
5215 * @security This is a security-sensitive function; any use of this function
5216 * must go through security review. In particular, it must be assured that the
5217 * provided string will never cause an XSS vulnerability if used in a context
5218 * that will cause a browser to load and execute a resource, e.g. when
5219 * assigning to script.src.
5220 */
5221function trustedScriptURLFromString(url) {
5222 return getPolicy$1()?.createScriptURL(url) || url;
5223}
5224/**
5225 * Unsafely call the Function constructor with the given string arguments. It
5226 * is only available in development mode, and should be stripped out of
5227 * production code.
5228 * @security This is a security-sensitive function; any use of this function
5229 * must go through security review. In particular, it must be assured that it
5230 * is only called from development code, as use in production code can lead to
5231 * XSS vulnerabilities.
5232 */
5233function newTrustedFunctionForDev(...args) {
5234 if (typeof ngDevMode === 'undefined') {
5235 throw new Error('newTrustedFunctionForDev should never be called in production');
5236 }
5237 if (!_global.trustedTypes) {
5238 // In environments that don't support Trusted Types, fall back to the most
5239 // straightforward implementation:
5240 return new Function(...args);
5241 }
5242 // Chrome currently does not support passing TrustedScript to the Function
5243 // constructor. The following implements the workaround proposed on the page
5244 // below, where the Chromium bug is also referenced:
5245 // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
5246 const fnArgs = args.slice(0, -1).join(',');
5247 const fnBody = args[args.length - 1];
5248 const body = `(function anonymous(${fnArgs}
5249) { ${fnBody}
5250})`;
5251 // Using eval directly confuses the compiler and prevents this module from
5252 // being stripped out of JS binaries even if not used. The global['eval']
5253 // indirection fixes that.
5254 const fn = _global['eval'](trustedScriptFromString(body));
5255 if (fn.bind === undefined) {
5256 // Workaround for a browser bug that only exists in Chrome 83, where passing
5257 // a TrustedScript to eval just returns the TrustedScript back without
5258 // evaluating it. In that case, fall back to the most straightforward
5259 // implementation:
5260 return new Function(...args);
5261 }
5262 // To completely mimic the behavior of calling "new Function", two more
5263 // things need to happen:
5264 // 1. Stringifying the resulting function should return its source code
5265 fn.toString = () => body;
5266 // 2. When calling the resulting function, `this` should refer to `global`
5267 return fn.bind(_global);
5268 // When Trusted Types support in Function constructors is widely available,
5269 // the implementation of this function can be simplified to:
5270 // return new Function(...args.map(a => trustedScriptFromString(a)));
5271}
5272
5273/**
5274 * @license
5275 * Copyright Google LLC All Rights Reserved.
5276 *
5277 * Use of this source code is governed by an MIT-style license that can be
5278 * found in the LICENSE file at https://angular.io/license
5279 */
5280/**
5281 * The Trusted Types policy, or null if Trusted Types are not
5282 * enabled/supported, or undefined if the policy has not been created yet.
5283 */
5284let policy;
5285/**
5286 * Returns the Trusted Types policy, or null if Trusted Types are not
5287 * enabled/supported. The first call to this function will create the policy.
5288 */
5289function getPolicy() {
5290 if (policy === undefined) {
5291 policy = null;
5292 if (_global.trustedTypes) {
5293 try {
5294 policy = _global.trustedTypes
5295 .createPolicy('angular#unsafe-bypass', {
5296 createHTML: (s) => s,
5297 createScript: (s) => s,
5298 createScriptURL: (s) => s,
5299 });
5300 }
5301 catch {
5302 // trustedTypes.createPolicy throws if called with a name that is
5303 // already registered, even in report-only mode. Until the API changes,
5304 // catch the error not to break the applications functionally. In such
5305 // cases, the code will fall back to using strings.
5306 }
5307 }
5308 }
5309 return policy;
5310}
5311/**
5312 * Unsafely promote a string to a TrustedHTML, falling back to strings when
5313 * Trusted Types are not available.
5314 * @security This is a security-sensitive function; any use of this function
5315 * must go through security review. In particular, it must be assured that it
5316 * is only passed strings that come directly from custom sanitizers or the
5317 * bypassSecurityTrust* functions.
5318 */
5319function trustedHTMLFromStringBypass(html) {
5320 return getPolicy()?.createHTML(html) || html;
5321}
5322/**
5323 * Unsafely promote a string to a TrustedScript, falling back to strings when
5324 * Trusted Types are not available.
5325 * @security This is a security-sensitive function; any use of this function
5326 * must go through security review. In particular, it must be assured that it
5327 * is only passed strings that come directly from custom sanitizers or the
5328 * bypassSecurityTrust* functions.
5329 */
5330function trustedScriptFromStringBypass(script) {
5331 return getPolicy()?.createScript(script) || script;
5332}
5333/**
5334 * Unsafely promote a string to a TrustedScriptURL, falling back to strings
5335 * when Trusted Types are not available.
5336 * @security This is a security-sensitive function; any use of this function
5337 * must go through security review. In particular, it must be assured that it
5338 * is only passed strings that come directly from custom sanitizers or the
5339 * bypassSecurityTrust* functions.
5340 */
5341function trustedScriptURLFromStringBypass(url) {
5342 return getPolicy()?.createScriptURL(url) || url;
5343}
5344
5345/**
5346 * @license
5347 * Copyright Google LLC All Rights Reserved.
5348 *
5349 * Use of this source code is governed by an MIT-style license that can be
5350 * found in the LICENSE file at https://angular.io/license
5351 */
5352class SafeValueImpl {
5353 constructor(changingThisBreaksApplicationSecurity) {
5354 this.changingThisBreaksApplicationSecurity = changingThisBreaksApplicationSecurity;
5355 }
5356 toString() {
5357 return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` +
5358 ` (see https://g.co/ng/security#xss)`;
5359 }
5360}
5361class SafeHtmlImpl extends SafeValueImpl {
5362 getTypeName() {
5363 return "HTML" /* Html */;
5364 }
5365}
5366class SafeStyleImpl extends SafeValueImpl {
5367 getTypeName() {
5368 return "Style" /* Style */;
5369 }
5370}
5371class SafeScriptImpl extends SafeValueImpl {
5372 getTypeName() {
5373 return "Script" /* Script */;
5374 }
5375}
5376class SafeUrlImpl extends SafeValueImpl {
5377 getTypeName() {
5378 return "URL" /* Url */;
5379 }
5380}
5381class SafeResourceUrlImpl extends SafeValueImpl {
5382 getTypeName() {
5383 return "ResourceURL" /* ResourceUrl */;
5384 }
5385}
5386function unwrapSafeValue(value) {
5387 return value instanceof SafeValueImpl ? value.changingThisBreaksApplicationSecurity :
5388 value;
5389}
5390function allowSanitizationBypassAndThrow(value, type) {
5391 const actualType = getSanitizationBypassType(value);
5392 if (actualType != null && actualType !== type) {
5393 // Allow ResourceURLs in URL contexts, they are strictly more trusted.
5394 if (actualType === "ResourceURL" /* ResourceUrl */ && type === "URL" /* Url */)
5395 return true;
5396 throw new Error(`Required a safe ${type}, got a ${actualType} (see https://g.co/ng/security#xss)`);
5397 }
5398 return actualType === type;
5399}
5400function getSanitizationBypassType(value) {
5401 return value instanceof SafeValueImpl && value.getTypeName() || null;
5402}
5403/**
5404 * Mark `html` string as trusted.
5405 *
5406 * This function wraps the trusted string in `String` and brands it in a way which makes it
5407 * recognizable to {@link htmlSanitizer} to be trusted implicitly.
5408 *
5409 * @param trustedHtml `html` string which needs to be implicitly trusted.
5410 * @returns a `html` which has been branded to be implicitly trusted.
5411 */
5412function bypassSanitizationTrustHtml(trustedHtml) {
5413 return new SafeHtmlImpl(trustedHtml);
5414}
5415/**
5416 * Mark `style` string as trusted.
5417 *
5418 * This function wraps the trusted string in `String` and brands it in a way which makes it
5419 * recognizable to {@link styleSanitizer} to be trusted implicitly.
5420 *
5421 * @param trustedStyle `style` string which needs to be implicitly trusted.
5422 * @returns a `style` hich has been branded to be implicitly trusted.
5423 */
5424function bypassSanitizationTrustStyle(trustedStyle) {
5425 return new SafeStyleImpl(trustedStyle);
5426}
5427/**
5428 * Mark `script` string as trusted.
5429 *
5430 * This function wraps the trusted string in `String` and brands it in a way which makes it
5431 * recognizable to {@link scriptSanitizer} to be trusted implicitly.
5432 *
5433 * @param trustedScript `script` string which needs to be implicitly trusted.
5434 * @returns a `script` which has been branded to be implicitly trusted.
5435 */
5436function bypassSanitizationTrustScript(trustedScript) {
5437 return new SafeScriptImpl(trustedScript);
5438}
5439/**
5440 * Mark `url` string as trusted.
5441 *
5442 * This function wraps the trusted string in `String` and brands it in a way which makes it
5443 * recognizable to {@link urlSanitizer} to be trusted implicitly.
5444 *
5445 * @param trustedUrl `url` string which needs to be implicitly trusted.
5446 * @returns a `url` which has been branded to be implicitly trusted.
5447 */
5448function bypassSanitizationTrustUrl(trustedUrl) {
5449 return new SafeUrlImpl(trustedUrl);
5450}
5451/**
5452 * Mark `url` string as trusted.
5453 *
5454 * This function wraps the trusted string in `String` and brands it in a way which makes it
5455 * recognizable to {@link resourceUrlSanitizer} to be trusted implicitly.
5456 *
5457 * @param trustedResourceUrl `url` string which needs to be implicitly trusted.
5458 * @returns a `url` which has been branded to be implicitly trusted.
5459 */
5460function bypassSanitizationTrustResourceUrl(trustedResourceUrl) {
5461 return new SafeResourceUrlImpl(trustedResourceUrl);
5462}
5463
5464/**
5465 * @license
5466 * Copyright Google LLC All Rights Reserved.
5467 *
5468 * Use of this source code is governed by an MIT-style license that can be
5469 * found in the LICENSE file at https://angular.io/license
5470 */
5471/**
5472 * This helper is used to get hold of an inert tree of DOM elements containing dirty HTML
5473 * that needs sanitizing.
5474 * Depending upon browser support we use one of two strategies for doing this.
5475 * Default: DOMParser strategy
5476 * Fallback: InertDocument strategy
5477 */
5478function getInertBodyHelper(defaultDoc) {
5479 const inertDocumentHelper = new InertDocumentHelper(defaultDoc);
5480 return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper;
5481}
5482/**
5483 * Uses DOMParser to create and fill an inert body element.
5484 * This is the default strategy used in browsers that support it.
5485 */
5486class DOMParserHelper {
5487 constructor(inertDocumentHelper) {
5488 this.inertDocumentHelper = inertDocumentHelper;
5489 }
5490 getInertBodyElement(html) {
5491 // We add these extra elements to ensure that the rest of the content is parsed as expected
5492 // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the
5493 // `<head>` tag. Note that the `<body>` tag is closed implicitly to prevent unclosed tags
5494 // in `html` from consuming the otherwise explicit `</body>` tag.
5495 html = '<body><remove></remove>' + html;
5496 try {
5497 const body = new window.DOMParser()
5498 .parseFromString(trustedHTMLFromString(html), 'text/html')
5499 .body;
5500 if (body === null) {
5501 // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only
5502 // becomes available in the following tick of the JS engine. In that case we fall back to
5503 // the `inertDocumentHelper` instead.
5504 return this.inertDocumentHelper.getInertBodyElement(html);
5505 }
5506 body.removeChild(body.firstChild);
5507 return body;
5508 }
5509 catch {
5510 return null;
5511 }
5512 }
5513}
5514/**
5515 * Use an HTML5 `template` element, if supported, or an inert body element created via
5516 * `createHtmlDocument` to create and fill an inert DOM element.
5517 * This is the fallback strategy if the browser does not support DOMParser.
5518 */
5519class InertDocumentHelper {
5520 constructor(defaultDoc) {
5521 this.defaultDoc = defaultDoc;
5522 this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert');
5523 if (this.inertDocument.body == null) {
5524 // usually there should be only one body element in the document, but IE doesn't have any, so
5525 // we need to create one.
5526 const inertHtml = this.inertDocument.createElement('html');
5527 this.inertDocument.appendChild(inertHtml);
5528 const inertBodyElement = this.inertDocument.createElement('body');
5529 inertHtml.appendChild(inertBodyElement);
5530 }
5531 }
5532 getInertBodyElement(html) {
5533 // Prefer using <template> element if supported.
5534 const templateEl = this.inertDocument.createElement('template');
5535 if ('content' in templateEl) {
5536 templateEl.innerHTML = trustedHTMLFromString(html);
5537 return templateEl;
5538 }
5539 // Note that previously we used to do something like `this.inertDocument.body.innerHTML = html`
5540 // and we returned the inert `body` node. This was changed, because IE seems to treat setting
5541 // `innerHTML` on an inserted element differently, compared to one that hasn't been inserted
5542 // yet. In particular, IE appears to split some of the text into multiple text nodes rather
5543 // than keeping them in a single one which ends up messing with Ivy's i18n parsing further
5544 // down the line. This has been worked around by creating a new inert `body` and using it as
5545 // the root node in which we insert the HTML.
5546 const inertBody = this.inertDocument.createElement('body');
5547 inertBody.innerHTML = trustedHTMLFromString(html);
5548 // Support: IE 11 only
5549 // strip custom-namespaced attributes on IE<=11
5550 if (this.defaultDoc.documentMode) {
5551 this.stripCustomNsAttrs(inertBody);
5552 }
5553 return inertBody;
5554 }
5555 /**
5556 * When IE11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1'
5557 * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g.
5558 * 'ns1:xlink:foo').
5559 *
5560 * This is undesirable since we don't want to allow any of these custom attributes. This method
5561 * strips them all.
5562 */
5563 stripCustomNsAttrs(el) {
5564 const elAttrs = el.attributes;
5565 // loop backwards so that we can support removals.
5566 for (let i = elAttrs.length - 1; 0 < i; i--) {
5567 const attrib = elAttrs.item(i);
5568 const attrName = attrib.name;
5569 if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
5570 el.removeAttribute(attrName);
5571 }
5572 }
5573 let childNode = el.firstChild;
5574 while (childNode) {
5575 if (childNode.nodeType === Node.ELEMENT_NODE)
5576 this.stripCustomNsAttrs(childNode);
5577 childNode = childNode.nextSibling;
5578 }
5579 }
5580}
5581/**
5582 * We need to determine whether the DOMParser exists in the global context and
5583 * supports parsing HTML; HTML parsing support is not as wide as other formats, see
5584 * https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility.
5585 *
5586 * @suppress {uselessCode}
5587 */
5588function isDOMParserAvailable() {
5589 try {
5590 return !!new window.DOMParser().parseFromString(trustedHTMLFromString(''), 'text/html');
5591 }
5592 catch {
5593 return false;
5594 }
5595}
5596
5597/**
5598 * @license
5599 * Copyright Google LLC All Rights Reserved.
5600 *
5601 * Use of this source code is governed by an MIT-style license that can be
5602 * found in the LICENSE file at https://angular.io/license
5603 */
5604/**
5605 * A pattern that recognizes a commonly useful subset of URLs that are safe.
5606 *
5607 * This regular expression matches a subset of URLs that will not cause script
5608 * execution if used in URL context within a HTML document. Specifically, this
5609 * regular expression matches if (comment from here on and regex copied from
5610 * Soy's EscapingConventions):
5611 * (1) Either an allowed protocol (http, https, mailto or ftp).
5612 * (2) or no protocol. A protocol must be followed by a colon. The below
5613 * allows that by allowing colons only after one of the characters [/?#].
5614 * A colon after a hash (#) must be in the fragment.
5615 * Otherwise, a colon after a (?) must be in a query.
5616 * Otherwise, a colon after a single solidus (/) must be in a path.
5617 * Otherwise, a colon after a double solidus (//) must be in the authority
5618 * (before port).
5619 *
5620 * The pattern disallows &, used in HTML entity declarations before
5621 * one of the characters in [/?#]. This disallows HTML entities used in the
5622 * protocol name, which should never happen, e.g. "h&#116;tp" for "http".
5623 * It also disallows HTML entities in the first path part of a relative path,
5624 * e.g. "foo&lt;bar/baz". Our existing escaping functions should not produce
5625 * that. More importantly, it disallows masking of a colon,
5626 * e.g. "javascript&#58;...".
5627 *
5628 * This regular expression was taken from the Closure sanitization library.
5629 */
5630const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;
5631/* A pattern that matches safe srcset values */
5632const SAFE_SRCSET_PATTERN = /^(?:(?:https?|file):|[^&:/?#]*(?:[/?#]|$))/gi;
5633/** A pattern that matches safe data URLs. Only matches image, video and audio types. */
5634const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+\/]+=*$/i;
5635function _sanitizeUrl(url) {
5636 url = String(url);
5637 if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN))
5638 return url;
5639 if (typeof ngDevMode === 'undefined' || ngDevMode) {
5640 console.warn(`WARNING: sanitizing unsafe URL value ${url} (see https://g.co/ng/security#xss)`);
5641 }
5642 return 'unsafe:' + url;
5643}
5644function sanitizeSrcset(srcset) {
5645 srcset = String(srcset);
5646 return srcset.split(',').map((srcset) => _sanitizeUrl(srcset.trim())).join(', ');
5647}
5648
5649/**
5650 * @license
5651 * Copyright Google LLC All Rights Reserved.
5652 *
5653 * Use of this source code is governed by an MIT-style license that can be
5654 * found in the LICENSE file at https://angular.io/license
5655 */
5656function tagSet(tags) {
5657 const res = {};
5658 for (const t of tags.split(','))
5659 res[t] = true;
5660 return res;
5661}
5662function merge(...sets) {
5663 const res = {};
5664 for (const s of sets) {
5665 for (const v in s) {
5666 if (s.hasOwnProperty(v))
5667 res[v] = true;
5668 }
5669 }
5670 return res;
5671}
5672// Good source of info about elements and attributes
5673// https://html.spec.whatwg.org/#semantics
5674// https://simon.html5.org/html-elements
5675// Safe Void Elements - HTML5
5676// https://html.spec.whatwg.org/#void-elements
5677const VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr');
5678// Elements that you can, intentionally, leave open (and which close themselves)
5679// https://html.spec.whatwg.org/#optional-tags
5680const OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr');
5681const OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt');
5682const OPTIONAL_END_TAG_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS);
5683// Safe Block Elements - HTML5
5684const BLOCK_ELEMENTS = merge(OPTIONAL_END_TAG_BLOCK_ELEMENTS, tagSet('address,article,' +
5685 'aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' +
5686 'h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul'));
5687// Inline Elements - HTML5
5688const INLINE_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, tagSet('a,abbr,acronym,audio,b,' +
5689 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' +
5690 'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video'));
5691const VALID_ELEMENTS = merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS);
5692// Attributes that have href and hence need to be sanitized
5693const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');
5694// Attributes that have special href set hence need to be sanitized
5695const SRCSET_ATTRS = tagSet('srcset');
5696const HTML_ATTRS = tagSet('abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' +
5697 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' +
5698 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' +
5699 'scope,scrolling,shape,size,sizes,span,srclang,start,summary,tabindex,target,title,translate,type,usemap,' +
5700 'valign,value,vspace,width');
5701// Accessibility attributes as per WAI-ARIA 1.1 (W3C Working Draft 14 December 2018)
5702const ARIA_ATTRS = tagSet('aria-activedescendant,aria-atomic,aria-autocomplete,aria-busy,aria-checked,aria-colcount,aria-colindex,' +
5703 'aria-colspan,aria-controls,aria-current,aria-describedby,aria-details,aria-disabled,aria-dropeffect,' +
5704 'aria-errormessage,aria-expanded,aria-flowto,aria-grabbed,aria-haspopup,aria-hidden,aria-invalid,' +
5705 'aria-keyshortcuts,aria-label,aria-labelledby,aria-level,aria-live,aria-modal,aria-multiline,' +
5706 'aria-multiselectable,aria-orientation,aria-owns,aria-placeholder,aria-posinset,aria-pressed,aria-readonly,' +
5707 'aria-relevant,aria-required,aria-roledescription,aria-rowcount,aria-rowindex,aria-rowspan,aria-selected,' +
5708 'aria-setsize,aria-sort,aria-valuemax,aria-valuemin,aria-valuenow,aria-valuetext');
5709// NB: This currently consciously doesn't support SVG. SVG sanitization has had several security
5710// issues in the past, so it seems safer to leave it out if possible. If support for binding SVG via
5711// innerHTML is required, SVG attributes should be added here.
5712// NB: Sanitization does not allow <form> elements or other active elements (<button> etc). Those
5713// can be sanitized, but they increase security surface area without a legitimate use case, so they
5714// are left out here.
5715const VALID_ATTRS = merge(URI_ATTRS, SRCSET_ATTRS, HTML_ATTRS, ARIA_ATTRS);
5716// Elements whose content should not be traversed/preserved, if the elements themselves are invalid.
5717//
5718// Typically, `<invalid>Some content</invalid>` would traverse (and in this case preserve)
5719// `Some content`, but strip `invalid-element` opening/closing tags. For some elements, though, we
5720// don't want to preserve the content, if the elements themselves are going to be removed.
5721const SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template');
5722/**
5723 * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe
5724 * attributes.
5725 */
5726class SanitizingHtmlSerializer {
5727 constructor() {
5728 // Explicitly track if something was stripped, to avoid accidentally warning of sanitization just
5729 // because characters were re-encoded.
5730 this.sanitizedSomething = false;
5731 this.buf = [];
5732 }
5733 sanitizeChildren(el) {
5734 // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters.
5735 // However this code never accesses properties off of `document` before deleting its contents
5736 // again, so it shouldn't be vulnerable to DOM clobbering.
5737 let current = el.firstChild;
5738 let traverseContent = true;
5739 while (current) {
5740 if (current.nodeType === Node.ELEMENT_NODE) {
5741 traverseContent = this.startElement(current);
5742 }
5743 else if (current.nodeType === Node.TEXT_NODE) {
5744 this.chars(current.nodeValue);
5745 }
5746 else {
5747 // Strip non-element, non-text nodes.
5748 this.sanitizedSomething = true;
5749 }
5750 if (traverseContent && current.firstChild) {
5751 current = current.firstChild;
5752 continue;
5753 }
5754 while (current) {
5755 // Leaving the element. Walk up and to the right, closing tags as we go.
5756 if (current.nodeType === Node.ELEMENT_NODE) {
5757 this.endElement(current);
5758 }
5759 let next = this.checkClobberedElement(current, current.nextSibling);
5760 if (next) {
5761 current = next;
5762 break;
5763 }
5764 current = this.checkClobberedElement(current, current.parentNode);
5765 }
5766 }
5767 return this.buf.join('');
5768 }
5769 /**
5770 * Sanitizes an opening element tag (if valid) and returns whether the element's contents should
5771 * be traversed. Element content must always be traversed (even if the element itself is not
5772 * valid/safe), unless the element is one of `SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS`.
5773 *
5774 * @param element The element to sanitize.
5775 * @return True if the element's contents should be traversed.
5776 */
5777 startElement(element) {
5778 const tagName = element.nodeName.toLowerCase();
5779 if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {
5780 this.sanitizedSomething = true;
5781 return !SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS.hasOwnProperty(tagName);
5782 }
5783 this.buf.push('<');
5784 this.buf.push(tagName);
5785 const elAttrs = element.attributes;
5786 for (let i = 0; i < elAttrs.length; i++) {
5787 const elAttr = elAttrs.item(i);
5788 const attrName = elAttr.name;
5789 const lower = attrName.toLowerCase();
5790 if (!VALID_ATTRS.hasOwnProperty(lower)) {
5791 this.sanitizedSomething = true;
5792 continue;
5793 }
5794 let value = elAttr.value;
5795 // TODO(martinprobst): Special case image URIs for data:image/...
5796 if (URI_ATTRS[lower])
5797 value = _sanitizeUrl(value);
5798 if (SRCSET_ATTRS[lower])
5799 value = sanitizeSrcset(value);
5800 this.buf.push(' ', attrName, '="', encodeEntities(value), '"');
5801 }
5802 this.buf.push('>');
5803 return true;
5804 }
5805 endElement(current) {
5806 const tagName = current.nodeName.toLowerCase();
5807 if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) {
5808 this.buf.push('</');
5809 this.buf.push(tagName);
5810 this.buf.push('>');
5811 }
5812 }
5813 chars(chars) {
5814 this.buf.push(encodeEntities(chars));
5815 }
5816 checkClobberedElement(node, nextNode) {
5817 if (nextNode &&
5818 (node.compareDocumentPosition(nextNode) &
5819 Node.DOCUMENT_POSITION_CONTAINED_BY) === Node.DOCUMENT_POSITION_CONTAINED_BY) {
5820 throw new Error(`Failed to sanitize html because the element is clobbered: ${node.outerHTML}`);
5821 }
5822 return nextNode;
5823 }
5824}
5825// Regular Expressions for parsing tags and attributes
5826const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
5827// ! to ~ is the ASCII range.
5828const NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;
5829/**
5830 * Escapes all potentially dangerous characters, so that the
5831 * resulting string can be safely inserted into attribute or
5832 * element text.
5833 * @param value
5834 */
5835function encodeEntities(value) {
5836 return value.replace(/&/g, '&amp;')
5837 .replace(SURROGATE_PAIR_REGEXP, function (match) {
5838 const hi = match.charCodeAt(0);
5839 const low = match.charCodeAt(1);
5840 return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
5841 })
5842 .replace(NON_ALPHANUMERIC_REGEXP, function (match) {
5843 return '&#' + match.charCodeAt(0) + ';';
5844 })
5845 .replace(/</g, '&lt;')
5846 .replace(/>/g, '&gt;');
5847}
5848let inertBodyHelper;
5849/**
5850 * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to
5851 * the DOM in a browser environment.
5852 */
5853function _sanitizeHtml(defaultDoc, unsafeHtmlInput) {
5854 let inertBodyElement = null;
5855 try {
5856 inertBodyHelper = inertBodyHelper || getInertBodyHelper(defaultDoc);
5857 // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime).
5858 let unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : '';
5859 inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
5860 // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser
5861 // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous.
5862 let mXSSAttempts = 5;
5863 let parsedHtml = unsafeHtml;
5864 do {
5865 if (mXSSAttempts === 0) {
5866 throw new Error('Failed to sanitize html because the input is unstable');
5867 }
5868 mXSSAttempts--;
5869 unsafeHtml = parsedHtml;
5870 parsedHtml = inertBodyElement.innerHTML;
5871 inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
5872 } while (unsafeHtml !== parsedHtml);
5873 const sanitizer = new SanitizingHtmlSerializer();
5874 const safeHtml = sanitizer.sanitizeChildren(getTemplateContent(inertBodyElement) || inertBodyElement);
5875 if ((typeof ngDevMode === 'undefined' || ngDevMode) && sanitizer.sanitizedSomething) {
5876 console.warn('WARNING: sanitizing HTML stripped some content, see https://g.co/ng/security#xss');
5877 }
5878 return trustedHTMLFromString(safeHtml);
5879 }
5880 finally {
5881 // In case anything goes wrong, clear out inertElement to reset the entire DOM structure.
5882 if (inertBodyElement) {
5883 const parent = getTemplateContent(inertBodyElement) || inertBodyElement;
5884 while (parent.firstChild) {
5885 parent.removeChild(parent.firstChild);
5886 }
5887 }
5888 }
5889}
5890function getTemplateContent(el) {
5891 return 'content' in el /** Microsoft/TypeScript#21517 */ && isTemplateElement(el) ?
5892 el.content :
5893 null;
5894}
5895function isTemplateElement(el) {
5896 return el.nodeType === Node.ELEMENT_NODE && el.nodeName === 'TEMPLATE';
5897}
5898
5899/**
5900 * @license
5901 * Copyright Google LLC All Rights Reserved.
5902 *
5903 * Use of this source code is governed by an MIT-style license that can be
5904 * found in the LICENSE file at https://angular.io/license
5905 */
5906/**
5907 * A SecurityContext marks a location that has dangerous security implications, e.g. a DOM property
5908 * like `innerHTML` that could cause Cross Site Scripting (XSS) security bugs when improperly
5909 * handled.
5910 *
5911 * See DomSanitizer for more details on security in Angular applications.
5912 *
5913 * @publicApi
5914 */
5915var SecurityContext;
5916(function (SecurityContext) {
5917 SecurityContext[SecurityContext["NONE"] = 0] = "NONE";
5918 SecurityContext[SecurityContext["HTML"] = 1] = "HTML";
5919 SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE";
5920 SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
5921 SecurityContext[SecurityContext["URL"] = 4] = "URL";
5922 SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
5923})(SecurityContext || (SecurityContext = {}));
5924
5925/**
5926 * @license
5927 * Copyright Google LLC All Rights Reserved.
5928 *
5929 * Use of this source code is governed by an MIT-style license that can be
5930 * found in the LICENSE file at https://angular.io/license
5931 */
5932/**
5933 * An `html` sanitizer which converts untrusted `html` **string** into trusted string by removing
5934 * dangerous content.
5935 *
5936 * This method parses the `html` and locates potentially dangerous content (such as urls and
5937 * javascript) and removes it.
5938 *
5939 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustHtml}.
5940 *
5941 * @param unsafeHtml untrusted `html`, typically from the user.
5942 * @returns `html` string which is safe to display to user, because all of the dangerous javascript
5943 * and urls have been removed.
5944 *
5945 * @codeGenApi
5946 */
5947function ɵɵsanitizeHtml(unsafeHtml) {
5948 const sanitizer = getSanitizer();
5949 if (sanitizer) {
5950 return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '');
5951 }
5952 if (allowSanitizationBypassAndThrow(unsafeHtml, "HTML" /* Html */)) {
5953 return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml));
5954 }
5955 return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
5956}
5957/**
5958 * A `style` sanitizer which converts untrusted `style` **string** into trusted string by removing
5959 * dangerous content.
5960 *
5961 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustStyle}.
5962 *
5963 * @param unsafeStyle untrusted `style`, typically from the user.
5964 * @returns `style` string which is safe to bind to the `style` properties.
5965 *
5966 * @codeGenApi
5967 */
5968function ɵɵsanitizeStyle(unsafeStyle) {
5969 const sanitizer = getSanitizer();
5970 if (sanitizer) {
5971 return sanitizer.sanitize(SecurityContext.STYLE, unsafeStyle) || '';
5972 }
5973 if (allowSanitizationBypassAndThrow(unsafeStyle, "Style" /* Style */)) {
5974 return unwrapSafeValue(unsafeStyle);
5975 }
5976 return renderStringify(unsafeStyle);
5977}
5978/**
5979 * A `url` sanitizer which converts untrusted `url` **string** into trusted string by removing
5980 * dangerous
5981 * content.
5982 *
5983 * This method parses the `url` and locates potentially dangerous content (such as javascript) and
5984 * removes it.
5985 *
5986 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustUrl}.
5987 *
5988 * @param unsafeUrl untrusted `url`, typically from the user.
5989 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because
5990 * all of the dangerous javascript has been removed.
5991 *
5992 * @codeGenApi
5993 */
5994function ɵɵsanitizeUrl(unsafeUrl) {
5995 const sanitizer = getSanitizer();
5996 if (sanitizer) {
5997 return sanitizer.sanitize(SecurityContext.URL, unsafeUrl) || '';
5998 }
5999 if (allowSanitizationBypassAndThrow(unsafeUrl, "URL" /* Url */)) {
6000 return unwrapSafeValue(unsafeUrl);
6001 }
6002 return _sanitizeUrl(renderStringify(unsafeUrl));
6003}
6004/**
6005 * A `url` sanitizer which only lets trusted `url`s through.
6006 *
6007 * This passes only `url`s marked trusted by calling {@link bypassSanitizationTrustResourceUrl}.
6008 *
6009 * @param unsafeResourceUrl untrusted `url`, typically from the user.
6010 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because
6011 * only trusted `url`s have been allowed to pass.
6012 *
6013 * @codeGenApi
6014 */
6015function ɵɵsanitizeResourceUrl(unsafeResourceUrl) {
6016 const sanitizer = getSanitizer();
6017 if (sanitizer) {
6018 return trustedScriptURLFromStringBypass(sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '');
6019 }
6020 if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL" /* ResourceUrl */)) {
6021 return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));
6022 }
6023 throw new Error('unsafe value used in a resource URL context (see https://g.co/ng/security#xss)');
6024}
6025/**
6026 * A `script` sanitizer which only lets trusted javascript through.
6027 *
6028 * This passes only `script`s marked trusted by calling {@link
6029 * bypassSanitizationTrustScript}.
6030 *
6031 * @param unsafeScript untrusted `script`, typically from the user.
6032 * @returns `url` string which is safe to bind to the `<script>` element such as `<img src>`,
6033 * because only trusted `scripts` have been allowed to pass.
6034 *
6035 * @codeGenApi
6036 */
6037function ɵɵsanitizeScript(unsafeScript) {
6038 const sanitizer = getSanitizer();
6039 if (sanitizer) {
6040 return trustedScriptFromStringBypass(sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '');
6041 }
6042 if (allowSanitizationBypassAndThrow(unsafeScript, "Script" /* Script */)) {
6043 return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
6044 }
6045 throw new Error('unsafe value used in a script context');
6046}
6047/**
6048 * A template tag function for promoting the associated constant literal to a
6049 * TrustedHTML. Interpolation is explicitly not allowed.
6050 *
6051 * @param html constant template literal containing trusted HTML.
6052 * @returns TrustedHTML wrapping `html`.
6053 *
6054 * @security This is a security-sensitive function and should only be used to
6055 * convert constant values of attributes and properties found in
6056 * application-provided Angular templates to TrustedHTML.
6057 *
6058 * @codeGenApi
6059 */
6060function ɵɵtrustConstantHtml(html) {
6061 // The following runtime check ensures that the function was called as a
6062 // template tag (e.g. ɵɵtrustConstantHtml`content`), without any interpolation
6063 // (e.g. not ɵɵtrustConstantHtml`content ${variable}`). A TemplateStringsArray
6064 // is an array with a `raw` property that is also an array. The associated
6065 // template literal has no interpolation if and only if the length of the
6066 // TemplateStringsArray is 1.
6067 if (ngDevMode && (!Array.isArray(html) || !Array.isArray(html.raw) || html.length !== 1)) {
6068 throw new Error(`Unexpected interpolation in trusted HTML constant: ${html.join('?')}`);
6069 }
6070 return trustedHTMLFromString(html[0]);
6071}
6072/**
6073 * A template tag function for promoting the associated constant literal to a
6074 * TrustedScriptURL. Interpolation is explicitly not allowed.
6075 *
6076 * @param url constant template literal containing a trusted script URL.
6077 * @returns TrustedScriptURL wrapping `url`.
6078 *
6079 * @security This is a security-sensitive function and should only be used to
6080 * convert constant values of attributes and properties found in
6081 * application-provided Angular templates to TrustedScriptURL.
6082 *
6083 * @codeGenApi
6084 */
6085function ɵɵtrustConstantResourceUrl(url) {
6086 // The following runtime check ensures that the function was called as a
6087 // template tag (e.g. ɵɵtrustConstantResourceUrl`content`), without any
6088 // interpolation (e.g. not ɵɵtrustConstantResourceUrl`content ${variable}`). A
6089 // TemplateStringsArray is an array with a `raw` property that is also an
6090 // array. The associated template literal has no interpolation if and only if
6091 // the length of the TemplateStringsArray is 1.
6092 if (ngDevMode && (!Array.isArray(url) || !Array.isArray(url.raw) || url.length !== 1)) {
6093 throw new Error(`Unexpected interpolation in trusted URL constant: ${url.join('?')}`);
6094 }
6095 return trustedScriptURLFromString(url[0]);
6096}
6097/**
6098 * Detects which sanitizer to use for URL property, based on tag name and prop name.
6099 *
6100 * The rules are based on the RESOURCE_URL context config from
6101 * `packages/compiler/src/schema/dom_security_schema.ts`.
6102 * If tag and prop names don't match Resource URL schema, use URL sanitizer.
6103 */
6104function getUrlSanitizer(tag, prop) {
6105 if ((prop === 'src' &&
6106 (tag === 'embed' || tag === 'frame' || tag === 'iframe' || tag === 'media' ||
6107 tag === 'script')) ||
6108 (prop === 'href' && (tag === 'base' || tag === 'link'))) {
6109 return ɵɵsanitizeResourceUrl;
6110 }
6111 return ɵɵsanitizeUrl;
6112}
6113/**
6114 * Sanitizes URL, selecting sanitizer function based on tag and property names.
6115 *
6116 * This function is used in case we can't define security context at compile time, when only prop
6117 * name is available. This happens when we generate host bindings for Directives/Components. The
6118 * host element is unknown at compile time, so we defer calculation of specific sanitizer to
6119 * runtime.
6120 *
6121 * @param unsafeUrl untrusted `url`, typically from the user.
6122 * @param tag target element tag name.
6123 * @param prop name of the property that contains the value.
6124 * @returns `url` string which is safe to bind.
6125 *
6126 * @codeGenApi
6127 */
6128function ɵɵsanitizeUrlOrResourceUrl(unsafeUrl, tag, prop) {
6129 return getUrlSanitizer(tag, prop)(unsafeUrl);
6130}
6131function validateAgainstEventProperties(name) {
6132 if (name.toLowerCase().startsWith('on')) {
6133 const msg = `Binding to event property '${name}' is disallowed for security reasons, ` +
6134 `please use (${name.slice(2)})=...` +
6135 `\nIf '${name}' is a directive input, make sure the directive is imported by the` +
6136 ` current module.`;
6137 throw new Error(msg);
6138 }
6139}
6140function validateAgainstEventAttributes(name) {
6141 if (name.toLowerCase().startsWith('on')) {
6142 const msg = `Binding to event attribute '${name}' is disallowed for security reasons, ` +
6143 `please use (${name.slice(2)})=...`;
6144 throw new Error(msg);
6145 }
6146}
6147function getSanitizer() {
6148 const lView = getLView();
6149 return lView && lView[SANITIZER];
6150}
6151
6152/**
6153 * @license
6154 * Copyright Google LLC All Rights Reserved.
6155 *
6156 * Use of this source code is governed by an MIT-style license that can be
6157 * found in the LICENSE file at https://angular.io/license
6158 */
6159/**
6160 * Returns the matching `LContext` data for a given DOM node, directive or component instance.
6161 *
6162 * This function will examine the provided DOM element, component, or directive instance\'s
6163 * monkey-patched property to derive the `LContext` data. Once called then the monkey-patched
6164 * value will be that of the newly created `LContext`.
6165 *
6166 * If the monkey-patched value is the `LView` instance then the context value for that
6167 * target will be created and the monkey-patch reference will be updated. Therefore when this
6168 * function is called it may mutate the provided element\'s, component\'s or any of the associated
6169 * directive\'s monkey-patch values.
6170 *
6171 * If the monkey-patch value is not detected then the code will walk up the DOM until an element
6172 * is found which contains a monkey-patch reference. When that occurs then the provided element
6173 * will be updated with a new context (which is then returned). If the monkey-patch value is not
6174 * detected for a component/directive instance then it will throw an error (all components and
6175 * directives should be automatically monkey-patched by ivy).
6176 *
6177 * @param target Component, Directive or DOM Node.
6178 */
6179function getLContext(target) {
6180 let mpValue = readPatchedData(target);
6181 if (mpValue) {
6182 // only when it's an array is it considered an LView instance
6183 // ... otherwise it's an already constructed LContext instance
6184 if (Array.isArray(mpValue)) {
6185 const lView = mpValue;
6186 let nodeIndex;
6187 let component = undefined;
6188 let directives = undefined;
6189 if (isComponentInstance(target)) {
6190 nodeIndex = findViaComponent(lView, target);
6191 if (nodeIndex == -1) {
6192 throw new Error('The provided component was not found in the application');
6193 }
6194 component = target;
6195 }
6196 else if (isDirectiveInstance(target)) {
6197 nodeIndex = findViaDirective(lView, target);
6198 if (nodeIndex == -1) {
6199 throw new Error('The provided directive was not found in the application');
6200 }
6201 directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
6202 }
6203 else {
6204 nodeIndex = findViaNativeElement(lView, target);
6205 if (nodeIndex == -1) {
6206 return null;
6207 }
6208 }
6209 // the goal is not to fill the entire context full of data because the lookups
6210 // are expensive. Instead, only the target data (the element, component, container, ICU
6211 // expression or directive details) are filled into the context. If called multiple times
6212 // with different target values then the missing target data will be filled in.
6213 const native = unwrapRNode(lView[nodeIndex]);
6214 const existingCtx = readPatchedData(native);
6215 const context = (existingCtx && !Array.isArray(existingCtx)) ?
6216 existingCtx :
6217 createLContext(lView, nodeIndex, native);
6218 // only when the component has been discovered then update the monkey-patch
6219 if (component && context.component === undefined) {
6220 context.component = component;
6221 attachPatchData(context.component, context);
6222 }
6223 // only when the directives have been discovered then update the monkey-patch
6224 if (directives && context.directives === undefined) {
6225 context.directives = directives;
6226 for (let i = 0; i < directives.length; i++) {
6227 attachPatchData(directives[i], context);
6228 }
6229 }
6230 attachPatchData(context.native, context);
6231 mpValue = context;
6232 }
6233 }
6234 else {
6235 const rElement = target;
6236 ngDevMode && assertDomNode(rElement);
6237 // if the context is not found then we need to traverse upwards up the DOM
6238 // to find the nearest element that has already been monkey patched with data
6239 let parent = rElement;
6240 while (parent = parent.parentNode) {
6241 const parentContext = readPatchedData(parent);
6242 if (parentContext) {
6243 let lView;
6244 if (Array.isArray(parentContext)) {
6245 lView = parentContext;
6246 }
6247 else {
6248 lView = parentContext.lView;
6249 }
6250 // the edge of the app was also reached here through another means
6251 // (maybe because the DOM was changed manually).
6252 if (!lView) {
6253 return null;
6254 }
6255 const index = findViaNativeElement(lView, rElement);
6256 if (index >= 0) {
6257 const native = unwrapRNode(lView[index]);
6258 const context = createLContext(lView, index, native);
6259 attachPatchData(native, context);
6260 mpValue = context;
6261 break;
6262 }
6263 }
6264 }
6265 }
6266 return mpValue || null;
6267}
6268/**
6269 * Creates an empty instance of a `LContext` context
6270 */
6271function createLContext(lView, nodeIndex, native) {
6272 return {
6273 lView,
6274 nodeIndex,
6275 native,
6276 component: undefined,
6277 directives: undefined,
6278 localRefs: undefined,
6279 };
6280}
6281/**
6282 * Takes a component instance and returns the view for that component.
6283 *
6284 * @param componentInstance
6285 * @returns The component's view
6286 */
6287function getComponentViewByInstance(componentInstance) {
6288 let lView = readPatchedData(componentInstance);
6289 let view;
6290 if (Array.isArray(lView)) {
6291 const nodeIndex = findViaComponent(lView, componentInstance);
6292 view = getComponentLViewByIndex(nodeIndex, lView);
6293 const context = createLContext(lView, nodeIndex, view[HOST]);
6294 context.component = componentInstance;
6295 attachPatchData(componentInstance, context);
6296 attachPatchData(context.native, context);
6297 }
6298 else {
6299 const context = lView;
6300 view = getComponentLViewByIndex(context.nodeIndex, context.lView);
6301 }
6302 return view;
6303}
6304/**
6305 * This property will be monkey-patched on elements, components and directives.
6306 */
6307const MONKEY_PATCH_KEY_NAME = '__ngContext__';
6308/**
6309 * Assigns the given data to the given target (which could be a component,
6310 * directive or DOM node instance) using monkey-patching.
6311 */
6312function attachPatchData(target, data) {
6313 ngDevMode && assertDefined(target, 'Target expected');
6314 target[MONKEY_PATCH_KEY_NAME] = data;
6315}
6316/**
6317 * Returns the monkey-patch value data present on the target (which could be
6318 * a component, directive or a DOM node).
6319 */
6320function readPatchedData(target) {
6321 ngDevMode && assertDefined(target, 'Target expected');
6322 return target[MONKEY_PATCH_KEY_NAME] || null;
6323}
6324function readPatchedLView(target) {
6325 const value = readPatchedData(target);
6326 if (value) {
6327 return Array.isArray(value) ? value : value.lView;
6328 }
6329 return null;
6330}
6331function isComponentInstance(instance) {
6332 return instance && instance.constructor && instance.constructor.ɵcmp;
6333}
6334function isDirectiveInstance(instance) {
6335 return instance && instance.constructor && instance.constructor.ɵdir;
6336}
6337/**
6338 * Locates the element within the given LView and returns the matching index
6339 */
6340function findViaNativeElement(lView, target) {
6341 const tView = lView[TVIEW];
6342 for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
6343 if (unwrapRNode(lView[i]) === target) {
6344 return i;
6345 }
6346 }
6347 return -1;
6348}
6349/**
6350 * Locates the next tNode (child, sibling or parent).
6351 */
6352function traverseNextElement(tNode) {
6353 if (tNode.child) {
6354 return tNode.child;
6355 }
6356 else if (tNode.next) {
6357 return tNode.next;
6358 }
6359 else {
6360 // Let's take the following template: <div><span>text</span></div><component/>
6361 // After checking the text node, we need to find the next parent that has a "next" TNode,
6362 // in this case the parent `div`, so that we can find the component.
6363 while (tNode.parent && !tNode.parent.next) {
6364 tNode = tNode.parent;
6365 }
6366 return tNode.parent && tNode.parent.next;
6367 }
6368}
6369/**
6370 * Locates the component within the given LView and returns the matching index
6371 */
6372function findViaComponent(lView, componentInstance) {
6373 const componentIndices = lView[TVIEW].components;
6374 if (componentIndices) {
6375 for (let i = 0; i < componentIndices.length; i++) {
6376 const elementComponentIndex = componentIndices[i];
6377 const componentView = getComponentLViewByIndex(elementComponentIndex, lView);
6378 if (componentView[CONTEXT] === componentInstance) {
6379 return elementComponentIndex;
6380 }
6381 }
6382 }
6383 else {
6384 const rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView);
6385 const rootComponent = rootComponentView[CONTEXT];
6386 if (rootComponent === componentInstance) {
6387 // we are dealing with the root element here therefore we know that the
6388 // element is the very first element after the HEADER data in the lView
6389 return HEADER_OFFSET;
6390 }
6391 }
6392 return -1;
6393}
6394/**
6395 * Locates the directive within the given LView and returns the matching index
6396 */
6397function findViaDirective(lView, directiveInstance) {
6398 // if a directive is monkey patched then it will (by default)
6399 // have a reference to the LView of the current view. The
6400 // element bound to the directive being search lives somewhere
6401 // in the view data. We loop through the nodes and check their
6402 // list of directives for the instance.
6403 let tNode = lView[TVIEW].firstChild;
6404 while (tNode) {
6405 const directiveIndexStart = tNode.directiveStart;
6406 const directiveIndexEnd = tNode.directiveEnd;
6407 for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {
6408 if (lView[i] === directiveInstance) {
6409 return tNode.index;
6410 }
6411 }
6412 tNode = traverseNextElement(tNode);
6413 }
6414 return -1;
6415}
6416/**
6417 * Returns a list of directives extracted from the given view based on the
6418 * provided list of directive index values.
6419 *
6420 * @param nodeIndex The node index
6421 * @param lView The target view data
6422 * @param includeComponents Whether or not to include components in returned directives
6423 */
6424function getDirectivesAtNodeIndex(nodeIndex, lView, includeComponents) {
6425 const tNode = lView[TVIEW].data[nodeIndex];
6426 let directiveStartIndex = tNode.directiveStart;
6427 if (directiveStartIndex == 0)
6428 return EMPTY_ARRAY;
6429 const directiveEndIndex = tNode.directiveEnd;
6430 if (!includeComponents && tNode.flags & 2 /* isComponentHost */)
6431 directiveStartIndex++;
6432 return lView.slice(directiveStartIndex, directiveEndIndex);
6433}
6434function getComponentAtNodeIndex(nodeIndex, lView) {
6435 const tNode = lView[TVIEW].data[nodeIndex];
6436 let directiveStartIndex = tNode.directiveStart;
6437 return tNode.flags & 2 /* isComponentHost */ ? lView[directiveStartIndex] : null;
6438}
6439/**
6440 * Returns a map of local references (local reference name => element or directive instance) that
6441 * exist on a given element.
6442 */
6443function discoverLocalRefs(lView, nodeIndex) {
6444 const tNode = lView[TVIEW].data[nodeIndex];
6445 if (tNode && tNode.localNames) {
6446 const result = {};
6447 let localIndex = tNode.index + 1;
6448 for (let i = 0; i < tNode.localNames.length; i += 2) {
6449 result[tNode.localNames[i]] = lView[localIndex];
6450 localIndex++;
6451 }
6452 return result;
6453 }
6454 return null;
6455}
6456
6457/**
6458 * @license
6459 * Copyright Google LLC All Rights Reserved.
6460 *
6461 * Use of this source code is governed by an MIT-style license that can be
6462 * found in the LICENSE file at https://angular.io/license
6463 */
6464const ERROR_TYPE = 'ngType';
6465const ERROR_DEBUG_CONTEXT = 'ngDebugContext';
6466const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
6467const ERROR_LOGGER = 'ngErrorLogger';
6468function wrappedError(message, originalError) {
6469 const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
6470 const error = Error(msg);
6471 error[ERROR_ORIGINAL_ERROR] = originalError;
6472 return error;
6473}
6474
6475/**
6476 * @license
6477 * Copyright Google LLC All Rights Reserved.
6478 *
6479 * Use of this source code is governed by an MIT-style license that can be
6480 * found in the LICENSE file at https://angular.io/license
6481 */
6482function getType(error) {
6483 return error[ERROR_TYPE];
6484}
6485function getDebugContext(error) {
6486 return error[ERROR_DEBUG_CONTEXT];
6487}
6488function getOriginalError(error) {
6489 return error[ERROR_ORIGINAL_ERROR];
6490}
6491function getErrorLogger(error) {
6492 return error && error[ERROR_LOGGER] || defaultErrorLogger;
6493}
6494function defaultErrorLogger(console, ...values) {
6495 console.error(...values);
6496}
6497
6498/**
6499 * @license
6500 * Copyright Google LLC All Rights Reserved.
6501 *
6502 * Use of this source code is governed by an MIT-style license that can be
6503 * found in the LICENSE file at https://angular.io/license
6504 */
6505/**
6506 * Provides a hook for centralized exception handling.
6507 *
6508 * The default implementation of `ErrorHandler` prints error messages to the `console`. To
6509 * intercept error handling, write a custom exception handler that replaces this default as
6510 * appropriate for your app.
6511 *
6512 * @usageNotes
6513 * ### Example
6514 *
6515 * ```
6516 * class MyErrorHandler implements ErrorHandler {
6517 * handleError(error) {
6518 * // do something with the exception
6519 * }
6520 * }
6521 *
6522 * @NgModule({
6523 * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
6524 * })
6525 * class MyModule {}
6526 * ```
6527 *
6528 * @publicApi
6529 */
6530class ErrorHandler {
6531 constructor() {
6532 /**
6533 * @internal
6534 */
6535 this._console = console;
6536 }
6537 handleError(error) {
6538 const originalError = this._findOriginalError(error);
6539 const context = this._findContext(error);
6540 // Note: Browser consoles show the place from where console.error was called.
6541 // We can use this to give users additional information about the error.
6542 const errorLogger = getErrorLogger(error);
6543 errorLogger(this._console, `ERROR`, error);
6544 if (originalError) {
6545 errorLogger(this._console, `ORIGINAL ERROR`, originalError);
6546 }
6547 if (context) {
6548 errorLogger(this._console, 'ERROR CONTEXT', context);
6549 }
6550 }
6551 /** @internal */
6552 _findContext(error) {
6553 return error ? (getDebugContext(error) || this._findContext(getOriginalError(error))) : null;
6554 }
6555 /** @internal */
6556 _findOriginalError(error) {
6557 let e = error && getOriginalError(error);
6558 while (e && getOriginalError(e)) {
6559 e = getOriginalError(e);
6560 }
6561 return e || null;
6562 }
6563}
6564
6565/**
6566 * @license
6567 * Copyright Google LLC All Rights Reserved.
6568 *
6569 * Use of this source code is governed by an MIT-style license that can be
6570 * found in the LICENSE file at https://angular.io/license
6571 */
6572/**
6573 * Defines a schema that allows an NgModule to contain the following:
6574 * - Non-Angular elements named with dash case (`-`).
6575 * - Element properties named with dash case (`-`).
6576 * Dash case is the naming convention for custom elements.
6577 *
6578 * @publicApi
6579 */
6580const CUSTOM_ELEMENTS_SCHEMA = {
6581 name: 'custom-elements'
6582};
6583/**
6584 * Defines a schema that allows any property on any element.
6585 *
6586 * This schema allows you to ignore the errors related to any unknown elements or properties in a
6587 * template. The usage of this schema is generally discouraged because it prevents useful validation
6588 * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
6589 *
6590 * @publicApi
6591 */
6592const NO_ERRORS_SCHEMA = {
6593 name: 'no-errors-schema'
6594};
6595
6596/**
6597 * @license
6598 * Copyright Google LLC All Rights Reserved.
6599 *
6600 * Use of this source code is governed by an MIT-style license that can be
6601 * found in the LICENSE file at https://angular.io/license
6602 */
6603/**
6604 * Disallowed strings in the comment.
6605 *
6606 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
6607 */
6608const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
6609/**
6610 * Delimiter in the disallowed strings which needs to be wrapped with zero with character.
6611 */
6612const COMMENT_DELIMITER = /(<|>)/;
6613const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
6614/**
6615 * Escape the content of comment strings so that it can be safely inserted into a comment node.
6616 *
6617 * The issue is that HTML does not specify any way to escape comment end text inside the comment.
6618 * Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
6619 * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
6620 * can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
6621 *
6622 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
6623 *
6624 * ```
6625 * div.innerHTML = div.innerHTML
6626 * ```
6627 *
6628 * One would expect that the above code would be safe to do, but it turns out that because comment
6629 * text is not escaped, the comment may contain text which will prematurely close the comment
6630 * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
6631 * may contain such text and expect them to be safe.)
6632 *
6633 * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
6634 * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
6635 * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
6636 * text it will render normally but it will not cause the HTML parser to close/open the comment.
6637 *
6638 * @param value text to make safe for comment node by escaping the comment open/close character
6639 * sequence.
6640 */
6641function escapeCommentText(value) {
6642 return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
6643}
6644
6645/**
6646 * @license
6647 * Copyright Google LLC All Rights Reserved.
6648 *
6649 * Use of this source code is governed by an MIT-style license that can be
6650 * found in the LICENSE file at https://angular.io/license
6651 */
6652function normalizeDebugBindingName(name) {
6653 // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
6654 name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
6655 return `ng-reflect-${name}`;
6656}
6657const CAMEL_CASE_REGEXP = /([A-Z])/g;
6658function camelCaseToDashCase(input) {
6659 return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
6660}
6661function normalizeDebugBindingValue(value) {
6662 try {
6663 // Limit the size of the value as otherwise the DOM just gets polluted.
6664 return value != null ? value.toString().slice(0, 30) : value;
6665 }
6666 catch (e) {
6667 return '[ERROR] Exception while trying to serialize the value';
6668 }
6669}
6670
6671/**
6672 * @license
6673 * Copyright Google LLC All Rights Reserved.
6674 *
6675 * Use of this source code is governed by an MIT-style license that can be
6676 * found in the LICENSE file at https://angular.io/license
6677 */
6678const defaultScheduler = (() => (typeof requestAnimationFrame !== 'undefined' &&
6679 requestAnimationFrame || // browser only
6680 setTimeout // everything else
6681)
6682 .bind(_global))();
6683/**
6684 *
6685 * @codeGenApi
6686 */
6687function ɵɵresolveWindow(element) {
6688 return element.ownerDocument.defaultView;
6689}
6690/**
6691 *
6692 * @codeGenApi
6693 */
6694function ɵɵresolveDocument(element) {
6695 return element.ownerDocument;
6696}
6697/**
6698 *
6699 * @codeGenApi
6700 */
6701function ɵɵresolveBody(element) {
6702 return element.ownerDocument.body;
6703}
6704/**
6705 * The special delimiter we use to separate property names, prefixes, and suffixes
6706 * in property binding metadata. See storeBindingMetadata().
6707 *
6708 * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
6709 * because it is a very uncommon character that is unlikely to be part of a user's
6710 * property names or interpolation strings. If it is in fact used in a property
6711 * binding, DebugElement.properties will not return the correct value for that
6712 * binding. However, there should be no runtime effect for real applications.
6713 *
6714 * This character is typically rendered as a question mark inside of a diamond.
6715 * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
6716 *
6717 */
6718const INTERPOLATION_DELIMITER = `�`;
6719/**
6720 * Unwrap a value which might be behind a closure (for forward declaration reasons).
6721 */
6722function maybeUnwrapFn(value) {
6723 if (value instanceof Function) {
6724 return value();
6725 }
6726 else {
6727 return value;
6728 }
6729}
6730
6731/**
6732 * @license
6733 * Copyright Google LLC All Rights Reserved.
6734 *
6735 * Use of this source code is governed by an MIT-style license that can be
6736 * found in the LICENSE file at https://angular.io/license
6737 */
6738/** Called when there are multiple component selectors that match a given node */
6739function throwMultipleComponentError(tNode) {
6740 throw new RuntimeError("300" /* MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}`);
6741}
6742/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
6743function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
6744 const field = propName ? ` for '${propName}'` : '';
6745 let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
6746 if (creationMode) {
6747 msg +=
6748 ` It seems like the view has been created after its parent and its children have been dirty checked.` +
6749 ` Has it been created in a change detection hook?`;
6750 }
6751 // TODO: include debug context, see `viewDebugError` function in
6752 // `packages/core/src/view/errors.ts` for reference.
6753 throw new RuntimeError("100" /* EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
6754}
6755function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
6756 const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
6757 let oldValue = prefix, newValue = prefix;
6758 for (let i = 0; i < chunks.length; i++) {
6759 const slotIdx = rootIndex + i;
6760 oldValue += `${lView[slotIdx]}${chunks[i]}`;
6761 newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
6762 }
6763 return { propName, oldValue, newValue };
6764}
6765/**
6766 * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
6767 * - property name (for property bindings or interpolations)
6768 * - old and new values, enriched using information from metadata
6769 *
6770 * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
6771 * function description.
6772 */
6773function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
6774 const tData = lView[TVIEW].data;
6775 const metadata = tData[bindingIndex];
6776 if (typeof metadata === 'string') {
6777 // metadata for property interpolation
6778 if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
6779 return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
6780 }
6781 // metadata for property binding
6782 return { propName: metadata, oldValue, newValue };
6783 }
6784 // metadata is not available for this expression, check if this expression is a part of the
6785 // property interpolation by going from the current binding index left and look for a string that
6786 // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
6787 // [..., 'id�Prefix � and � suffix', null, null, null, ...]
6788 if (metadata === null) {
6789 let idx = bindingIndex - 1;
6790 while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
6791 idx--;
6792 }
6793 const meta = tData[idx];
6794 if (typeof meta === 'string') {
6795 const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
6796 // first interpolation delimiter separates property name from interpolation parts (in case of
6797 // property interpolations), so we subtract one from total number of found delimiters
6798 if (matches && (matches.length - 1) > bindingIndex - idx) {
6799 return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
6800 }
6801 }
6802 }
6803 return { propName: undefined, oldValue, newValue };
6804}
6805
6806/**
6807 * @license
6808 * Copyright Google LLC All Rights Reserved.
6809 *
6810 * Use of this source code is governed by an MIT-style license that can be
6811 * found in the LICENSE file at https://angular.io/license
6812 */
6813/**
6814 * Flags for renderer-specific style modifiers.
6815 * @publicApi
6816 */
6817var RendererStyleFlags2;
6818(function (RendererStyleFlags2) {
6819 // TODO(misko): This needs to be refactored into a separate file so that it can be imported from
6820 // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails
6821 // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.
6822 /**
6823 * Marks a style as important.
6824 */
6825 RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important";
6826 /**
6827 * Marks a style as using dash case naming (this-is-dash-case).
6828 */
6829 RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase";
6830})(RendererStyleFlags2 || (RendererStyleFlags2 = {}));
6831
6832/**
6833 * @license
6834 * Copyright Google LLC All Rights Reserved.
6835 *
6836 * Use of this source code is governed by an MIT-style license that can be
6837 * found in the LICENSE file at https://angular.io/license
6838 */
6839let _icuContainerIterate;
6840/**
6841 * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.
6842 */
6843function icuContainerIterate(tIcuContainerNode, lView) {
6844 return _icuContainerIterate(tIcuContainerNode, lView);
6845}
6846/**
6847 * Ensures that `IcuContainerVisitor`'s implementation is present.
6848 *
6849 * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the
6850 * bundler to tree shake ICU logic and only load it if ICU instruction is executed.
6851 */
6852function ensureIcuContainerVisitorLoaded(loader) {
6853 if (_icuContainerIterate === undefined) {
6854 // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it
6855 // can be inlined into call-site.
6856 _icuContainerIterate = loader();
6857 }
6858}
6859
6860/**
6861 * @license
6862 * Copyright Google LLC All Rights Reserved.
6863 *
6864 * Use of this source code is governed by an MIT-style license that can be
6865 * found in the LICENSE file at https://angular.io/license
6866 */
6867// Note: This hack is necessary so we don't erroneously get a circular dependency
6868// failure based on types.
6869const unusedValueExportToPlacateAjd$3 = 1;
6870
6871/**
6872 * @license
6873 * Copyright Google LLC All Rights Reserved.
6874 *
6875 * Use of this source code is governed by an MIT-style license that can be
6876 * found in the LICENSE file at https://angular.io/license
6877 */
6878/**
6879 * Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
6880 * that LContainer, which is an LView
6881 * @param lView the lView whose parent to get
6882 */
6883function getLViewParent(lView) {
6884 ngDevMode && assertLView(lView);
6885 const parent = lView[PARENT];
6886 return isLContainer(parent) ? parent[PARENT] : parent;
6887}
6888/**
6889 * Retrieve the root view from any component or `LView` by walking the parent `LView` until
6890 * reaching the root `LView`.
6891 *
6892 * @param componentOrLView any component or `LView`
6893 */
6894function getRootView(componentOrLView) {
6895 ngDevMode && assertDefined(componentOrLView, 'component');
6896 let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView);
6897 while (lView && !(lView[FLAGS] & 512 /* IsRoot */)) {
6898 lView = getLViewParent(lView);
6899 }
6900 ngDevMode && assertLView(lView);
6901 return lView;
6902}
6903/**
6904 * Returns the `RootContext` instance that is associated with
6905 * the application where the target is situated. It does this by walking the parent views until it
6906 * gets to the root view, then getting the context off of that.
6907 *
6908 * @param viewOrComponent the `LView` or component to get the root context for.
6909 */
6910function getRootContext(viewOrComponent) {
6911 const rootView = getRootView(viewOrComponent);
6912 ngDevMode &&
6913 assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
6914 return rootView[CONTEXT];
6915}
6916/**
6917 * Gets the first `LContainer` in the LView or `null` if none exists.
6918 */
6919function getFirstLContainer(lView) {
6920 return getNearestLContainer(lView[CHILD_HEAD]);
6921}
6922/**
6923 * Gets the next `LContainer` that is a sibling of the given container.
6924 */
6925function getNextLContainer(container) {
6926 return getNearestLContainer(container[NEXT]);
6927}
6928function getNearestLContainer(viewOrContainer) {
6929 while (viewOrContainer !== null && !isLContainer(viewOrContainer)) {
6930 viewOrContainer = viewOrContainer[NEXT];
6931 }
6932 return viewOrContainer;
6933}
6934
6935/**
6936 * @license
6937 * Copyright Google LLC All Rights Reserved.
6938 *
6939 * Use of this source code is governed by an MIT-style license that can be
6940 * found in the LICENSE file at https://angular.io/license
6941 */
6942const unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$7 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$6 + unusedValueExportToPlacateAjd$8;
6943/**
6944 * NOTE: for performance reasons, the possible actions are inlined within the function instead of
6945 * being passed as an argument.
6946 */
6947function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) {
6948 // If this slot was allocated for a text node dynamically created by i18n, the text node itself
6949 // won't be created until i18nApply() in the update block, so this node should be skipped.
6950 // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor"
6951 // in `i18n_spec.ts`.
6952 if (lNodeToHandle != null) {
6953 let lContainer;
6954 let isComponent = false;
6955 // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is
6956 // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if
6957 // it has LContainer so that we can process all of those cases appropriately.
6958 if (isLContainer(lNodeToHandle)) {
6959 lContainer = lNodeToHandle;
6960 }
6961 else if (isLView(lNodeToHandle)) {
6962 isComponent = true;
6963 ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');
6964 lNodeToHandle = lNodeToHandle[HOST];
6965 }
6966 const rNode = unwrapRNode(lNodeToHandle);
6967 ngDevMode && !isProceduralRenderer(renderer) && assertDomNode(rNode);
6968 if (action === 0 /* Create */ && parent !== null) {
6969 if (beforeNode == null) {
6970 nativeAppendChild(renderer, parent, rNode);
6971 }
6972 else {
6973 nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
6974 }
6975 }
6976 else if (action === 1 /* Insert */ && parent !== null) {
6977 nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
6978 }
6979 else if (action === 2 /* Detach */) {
6980 nativeRemoveNode(renderer, rNode, isComponent);
6981 }
6982 else if (action === 3 /* Destroy */) {
6983 ngDevMode && ngDevMode.rendererDestroyNode++;
6984 renderer.destroyNode(rNode);
6985 }
6986 if (lContainer != null) {
6987 applyContainer(renderer, action, lContainer, parent, beforeNode);
6988 }
6989 }
6990}
6991function createTextNode(renderer, value) {
6992 ngDevMode && ngDevMode.rendererCreateTextNode++;
6993 ngDevMode && ngDevMode.rendererSetText++;
6994 return isProceduralRenderer(renderer) ? renderer.createText(value) :
6995 renderer.createTextNode(value);
6996}
6997function updateTextNode(renderer, rNode, value) {
6998 ngDevMode && ngDevMode.rendererSetText++;
6999 isProceduralRenderer(renderer) ? renderer.setValue(rNode, value) : rNode.textContent = value;
7000}
7001function createCommentNode(renderer, value) {
7002 ngDevMode && ngDevMode.rendererCreateComment++;
7003 // isProceduralRenderer check is not needed because both `Renderer2` and `Renderer3` have the same
7004 // method name.
7005 return renderer.createComment(escapeCommentText(value));
7006}
7007/**
7008 * Creates a native element from a tag name, using a renderer.
7009 * @param renderer A renderer to use
7010 * @param name the tag name
7011 * @param namespace Optional namespace for element.
7012 * @returns the element created
7013 */
7014function createElementNode(renderer, name, namespace) {
7015 ngDevMode && ngDevMode.rendererCreateElement++;
7016 if (isProceduralRenderer(renderer)) {
7017 return renderer.createElement(name, namespace);
7018 }
7019 else {
7020 return namespace === null ? renderer.createElement(name) :
7021 renderer.createElementNS(namespace, name);
7022 }
7023}
7024/**
7025 * Removes all DOM elements associated with a view.
7026 *
7027 * Because some root nodes of the view may be containers, we sometimes need
7028 * to propagate deeply into the nested containers to remove all elements in the
7029 * views beneath it.
7030 *
7031 * @param tView The `TView' of the `LView` from which elements should be added or removed
7032 * @param lView The view from which elements should be added or removed
7033 */
7034function removeViewFromContainer(tView, lView) {
7035 const renderer = lView[RENDERER];
7036 applyView(tView, lView, renderer, 2 /* Detach */, null, null);
7037 lView[HOST] = null;
7038 lView[T_HOST] = null;
7039}
7040/**
7041 * Adds all DOM elements associated with a view.
7042 *
7043 * Because some root nodes of the view may be containers, we sometimes need
7044 * to propagate deeply into the nested containers to add all elements in the
7045 * views beneath it.
7046 *
7047 * @param tView The `TView' of the `LView` from which elements should be added or removed
7048 * @param parentTNode The `TNode` where the `LView` should be attached to.
7049 * @param renderer Current renderer to use for DOM manipulations.
7050 * @param lView The view from which elements should be added or removed
7051 * @param parentNativeNode The parent `RElement` where it should be inserted into.
7052 * @param beforeNode The node before which elements should be added, if insert mode
7053 */
7054function addViewToContainer(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
7055 lView[HOST] = parentNativeNode;
7056 lView[T_HOST] = parentTNode;
7057 applyView(tView, lView, renderer, 1 /* Insert */, parentNativeNode, beforeNode);
7058}
7059/**
7060 * Detach a `LView` from the DOM by detaching its nodes.
7061 *
7062 * @param tView The `TView' of the `LView` to be detached
7063 * @param lView the `LView` to be detached.
7064 */
7065function renderDetachView$1(tView, lView) {
7066 applyView(tView, lView, lView[RENDERER], 2 /* Detach */, null, null);
7067}
7068/**
7069 * Traverses down and up the tree of views and containers to remove listeners and
7070 * call onDestroy callbacks.
7071 *
7072 * Notes:
7073 * - Because it's used for onDestroy calls, it needs to be bottom-up.
7074 * - Must process containers instead of their views to avoid splicing
7075 * when views are destroyed and re-added.
7076 * - Using a while loop because it's faster than recursion
7077 * - Destroy only called on movement to sibling or movement to parent (laterally or up)
7078 *
7079 * @param rootView The view to destroy
7080 */
7081function destroyViewTree(rootView) {
7082 // If the view has no children, we can clean it up and return early.
7083 let lViewOrLContainer = rootView[CHILD_HEAD];
7084 if (!lViewOrLContainer) {
7085 return cleanUpView(rootView[TVIEW], rootView);
7086 }
7087 while (lViewOrLContainer) {
7088 let next = null;
7089 if (isLView(lViewOrLContainer)) {
7090 // If LView, traverse down to child.
7091 next = lViewOrLContainer[CHILD_HEAD];
7092 }
7093 else {
7094 ngDevMode && assertLContainer(lViewOrLContainer);
7095 // If container, traverse down to its first LView.
7096 const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
7097 if (firstView)
7098 next = firstView;
7099 }
7100 if (!next) {
7101 // Only clean up view when moving to the side or up, as destroy hooks
7102 // should be called in order from the bottom up.
7103 while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) {
7104 if (isLView(lViewOrLContainer)) {
7105 cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7106 }
7107 lViewOrLContainer = lViewOrLContainer[PARENT];
7108 }
7109 if (lViewOrLContainer === null)
7110 lViewOrLContainer = rootView;
7111 if (isLView(lViewOrLContainer)) {
7112 cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7113 }
7114 next = lViewOrLContainer && lViewOrLContainer[NEXT];
7115 }
7116 lViewOrLContainer = next;
7117 }
7118}
7119/**
7120 * Inserts a view into a container.
7121 *
7122 * This adds the view to the container's array of active views in the correct
7123 * position. It also adds the view's elements to the DOM if the container isn't a
7124 * root node of another view (in that case, the view's elements will be added when
7125 * the container's parent view is added later).
7126 *
7127 * @param tView The `TView' of the `LView` to insert
7128 * @param lView The view to insert
7129 * @param lContainer The container into which the view should be inserted
7130 * @param index Which index in the container to insert the child view into
7131 */
7132function insertView(tView, lView, lContainer, index) {
7133 ngDevMode && assertLView(lView);
7134 ngDevMode && assertLContainer(lContainer);
7135 const indexInContainer = CONTAINER_HEADER_OFFSET + index;
7136 const containerLength = lContainer.length;
7137 if (index > 0) {
7138 // This is a new view, we need to add it to the children.
7139 lContainer[indexInContainer - 1][NEXT] = lView;
7140 }
7141 if (index < containerLength - CONTAINER_HEADER_OFFSET) {
7142 lView[NEXT] = lContainer[indexInContainer];
7143 addToArray(lContainer, CONTAINER_HEADER_OFFSET + index, lView);
7144 }
7145 else {
7146 lContainer.push(lView);
7147 lView[NEXT] = null;
7148 }
7149 lView[PARENT] = lContainer;
7150 // track views where declaration and insertion points are different
7151 const declarationLContainer = lView[DECLARATION_LCONTAINER];
7152 if (declarationLContainer !== null && lContainer !== declarationLContainer) {
7153 trackMovedView(declarationLContainer, lView);
7154 }
7155 // notify query that a new view has been added
7156 const lQueries = lView[QUERIES];
7157 if (lQueries !== null) {
7158 lQueries.insertView(tView);
7159 }
7160 // Sets the attached flag
7161 lView[FLAGS] |= 128 /* Attached */;
7162}
7163/**
7164 * Track views created from the declaration container (TemplateRef) and inserted into a
7165 * different LContainer.
7166 */
7167function trackMovedView(declarationContainer, lView) {
7168 ngDevMode && assertDefined(lView, 'LView required');
7169 ngDevMode && assertLContainer(declarationContainer);
7170 const movedViews = declarationContainer[MOVED_VIEWS];
7171 const insertedLContainer = lView[PARENT];
7172 ngDevMode && assertLContainer(insertedLContainer);
7173 const insertedComponentLView = insertedLContainer[PARENT][DECLARATION_COMPONENT_VIEW];
7174 ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView');
7175 const declaredComponentLView = lView[DECLARATION_COMPONENT_VIEW];
7176 ngDevMode && assertDefined(declaredComponentLView, 'Missing declaredComponentLView');
7177 if (declaredComponentLView !== insertedComponentLView) {
7178 // At this point the declaration-component is not same as insertion-component; this means that
7179 // this is a transplanted view. Mark the declared lView as having transplanted views so that
7180 // those views can participate in CD.
7181 declarationContainer[HAS_TRANSPLANTED_VIEWS] = true;
7182 }
7183 if (movedViews === null) {
7184 declarationContainer[MOVED_VIEWS] = [lView];
7185 }
7186 else {
7187 movedViews.push(lView);
7188 }
7189}
7190function detachMovedView(declarationContainer, lView) {
7191 ngDevMode && assertLContainer(declarationContainer);
7192 ngDevMode &&
7193 assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');
7194 const movedViews = declarationContainer[MOVED_VIEWS];
7195 const declarationViewIndex = movedViews.indexOf(lView);
7196 const insertionLContainer = lView[PARENT];
7197 ngDevMode && assertLContainer(insertionLContainer);
7198 // If the view was marked for refresh but then detached before it was checked (where the flag
7199 // would be cleared and the counter decremented), we need to decrement the view counter here
7200 // instead.
7201 if (lView[FLAGS] & 1024 /* RefreshTransplantedView */) {
7202 lView[FLAGS] &= ~1024 /* RefreshTransplantedView */;
7203 updateTransplantedViewCount(insertionLContainer, -1);
7204 }
7205 movedViews.splice(declarationViewIndex, 1);
7206}
7207/**
7208 * Detaches a view from a container.
7209 *
7210 * This method removes the view from the container's array of active views. It also
7211 * removes the view's elements from the DOM.
7212 *
7213 * @param lContainer The container from which to detach a view
7214 * @param removeIndex The index of the view to detach
7215 * @returns Detached LView instance.
7216 */
7217function detachView(lContainer, removeIndex) {
7218 if (lContainer.length <= CONTAINER_HEADER_OFFSET)
7219 return;
7220 const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;
7221 const viewToDetach = lContainer[indexInContainer];
7222 if (viewToDetach) {
7223 const declarationLContainer = viewToDetach[DECLARATION_LCONTAINER];
7224 if (declarationLContainer !== null && declarationLContainer !== lContainer) {
7225 detachMovedView(declarationLContainer, viewToDetach);
7226 }
7227 if (removeIndex > 0) {
7228 lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT];
7229 }
7230 const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);
7231 removeViewFromContainer(viewToDetach[TVIEW], viewToDetach);
7232 // notify query that a view has been removed
7233 const lQueries = removedLView[QUERIES];
7234 if (lQueries !== null) {
7235 lQueries.detachView(removedLView[TVIEW]);
7236 }
7237 viewToDetach[PARENT] = null;
7238 viewToDetach[NEXT] = null;
7239 // Unsets the attached flag
7240 viewToDetach[FLAGS] &= ~128 /* Attached */;
7241 }
7242 return viewToDetach;
7243}
7244/**
7245 * A standalone function which destroys an LView,
7246 * conducting clean up (e.g. removing listeners, calling onDestroys).
7247 *
7248 * @param tView The `TView' of the `LView` to be destroyed
7249 * @param lView The view to be destroyed.
7250 */
7251function destroyLView(tView, lView) {
7252 if (!(lView[FLAGS] & 256 /* Destroyed */)) {
7253 const renderer = lView[RENDERER];
7254 if (isProceduralRenderer(renderer) && renderer.destroyNode) {
7255 applyView(tView, lView, renderer, 3 /* Destroy */, null, null);
7256 }
7257 destroyViewTree(lView);
7258 }
7259}
7260/**
7261 * Calls onDestroys hooks for all directives and pipes in a given view and then removes all
7262 * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
7263 * can be propagated to @Output listeners.
7264 *
7265 * @param tView `TView` for the `LView` to clean up.
7266 * @param lView The LView to clean up
7267 */
7268function cleanUpView(tView, lView) {
7269 if (!(lView[FLAGS] & 256 /* Destroyed */)) {
7270 // Usually the Attached flag is removed when the view is detached from its parent, however
7271 // if it's a root view, the flag won't be unset hence why we're also removing on destroy.
7272 lView[FLAGS] &= ~128 /* Attached */;
7273 // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
7274 // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
7275 // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
7276 // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
7277 // really more of an "afterDestroy" hook if you think about it.
7278 lView[FLAGS] |= 256 /* Destroyed */;
7279 executeOnDestroys(tView, lView);
7280 processCleanups(tView, lView);
7281 // For component views only, the local renderer is destroyed at clean up time.
7282 if (lView[TVIEW].type === 1 /* Component */ && isProceduralRenderer(lView[RENDERER])) {
7283 ngDevMode && ngDevMode.rendererDestroy++;
7284 lView[RENDERER].destroy();
7285 }
7286 const declarationContainer = lView[DECLARATION_LCONTAINER];
7287 // we are dealing with an embedded view that is still inserted into a container
7288 if (declarationContainer !== null && isLContainer(lView[PARENT])) {
7289 // and this is a projected view
7290 if (declarationContainer !== lView[PARENT]) {
7291 detachMovedView(declarationContainer, lView);
7292 }
7293 // For embedded views still attached to a container: remove query result from this view.
7294 const lQueries = lView[QUERIES];
7295 if (lQueries !== null) {
7296 lQueries.detachView(tView);
7297 }
7298 }
7299 }
7300}
7301/** Removes listeners and unsubscribes from output subscriptions */
7302function processCleanups(tView, lView) {
7303 const tCleanup = tView.cleanup;
7304 const lCleanup = lView[CLEANUP];
7305 // `LCleanup` contains both share information with `TCleanup` as well as instance specific
7306 // information appended at the end. We need to know where the end of the `TCleanup` information
7307 // is, and we track this with `lastLCleanupIndex`.
7308 let lastLCleanupIndex = -1;
7309 if (tCleanup !== null) {
7310 for (let i = 0; i < tCleanup.length - 1; i += 2) {
7311 if (typeof tCleanup[i] === 'string') {
7312 // This is a native DOM listener
7313 const idxOrTargetGetter = tCleanup[i + 1];
7314 const target = typeof idxOrTargetGetter === 'function' ?
7315 idxOrTargetGetter(lView) :
7316 unwrapRNode(lView[idxOrTargetGetter]);
7317 const listener = lCleanup[lastLCleanupIndex = tCleanup[i + 2]];
7318 const useCaptureOrSubIdx = tCleanup[i + 3];
7319 if (typeof useCaptureOrSubIdx === 'boolean') {
7320 // native DOM listener registered with Renderer3
7321 target.removeEventListener(tCleanup[i], listener, useCaptureOrSubIdx);
7322 }
7323 else {
7324 if (useCaptureOrSubIdx >= 0) {
7325 // unregister
7326 lCleanup[lastLCleanupIndex = useCaptureOrSubIdx]();
7327 }
7328 else {
7329 // Subscription
7330 lCleanup[lastLCleanupIndex = -useCaptureOrSubIdx].unsubscribe();
7331 }
7332 }
7333 i += 2;
7334 }
7335 else {
7336 // This is a cleanup function that is grouped with the index of its context
7337 const context = lCleanup[lastLCleanupIndex = tCleanup[i + 1]];
7338 tCleanup[i].call(context);
7339 }
7340 }
7341 }
7342 if (lCleanup !== null) {
7343 for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
7344 const instanceCleanupFn = lCleanup[i];
7345 ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
7346 instanceCleanupFn();
7347 }
7348 lView[CLEANUP] = null;
7349 }
7350}
7351/** Calls onDestroy hooks for this view */
7352function executeOnDestroys(tView, lView) {
7353 let destroyHooks;
7354 if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
7355 for (let i = 0; i < destroyHooks.length; i += 2) {
7356 const context = lView[destroyHooks[i]];
7357 // Only call the destroy hook if the context has been requested.
7358 if (!(context instanceof NodeInjectorFactory)) {
7359 const toCall = destroyHooks[i + 1];
7360 if (Array.isArray(toCall)) {
7361 for (let j = 0; j < toCall.length; j += 2) {
7362 const callContext = context[toCall[j]];
7363 const hook = toCall[j + 1];
7364 profiler(4 /* LifecycleHookStart */, callContext, hook);
7365 try {
7366 hook.call(callContext);
7367 }
7368 finally {
7369 profiler(5 /* LifecycleHookEnd */, callContext, hook);
7370 }
7371 }
7372 }
7373 else {
7374 profiler(4 /* LifecycleHookStart */, context, toCall);
7375 try {
7376 toCall.call(context);
7377 }
7378 finally {
7379 profiler(5 /* LifecycleHookEnd */, context, toCall);
7380 }
7381 }
7382 }
7383 }
7384 }
7385}
7386/**
7387 * Returns a native element if a node can be inserted into the given parent.
7388 *
7389 * There are two reasons why we may not be able to insert a element immediately.
7390 * - Projection: When creating a child content element of a component, we have to skip the
7391 * insertion because the content of a component will be projected.
7392 * `<component><content>delayed due to projection</content></component>`
7393 * - Parent container is disconnected: This can happen when we are inserting a view into
7394 * parent container, which itself is disconnected. For example the parent container is part
7395 * of a View which has not be inserted or is made for projection but has not been inserted
7396 * into destination.
7397 *
7398 * @param tView: Current `TView`.
7399 * @param tNode: `TNode` for which we wish to retrieve render parent.
7400 * @param lView: Current `LView`.
7401 */
7402function getParentRElement(tView, tNode, lView) {
7403 return getClosestRElement(tView, tNode.parent, lView);
7404}
7405/**
7406 * Get closest `RElement` or `null` if it can't be found.
7407 *
7408 * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.
7409 * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).
7410 * If `TNode` is `null` then return host `RElement`:
7411 * - return `null` if projection
7412 * - return `null` if parent container is disconnected (we have no parent.)
7413 *
7414 * @param tView: Current `TView`.
7415 * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is
7416 * needed).
7417 * @param lView: Current `LView`.
7418 * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)
7419 */
7420function getClosestRElement(tView, tNode, lView) {
7421 let parentTNode = tNode;
7422 // Skip over element and ICU containers as those are represented by a comment node and
7423 // can't be used as a render parent.
7424 while (parentTNode !== null &&
7425 (parentTNode.type & (8 /* ElementContainer */ | 32 /* Icu */))) {
7426 tNode = parentTNode;
7427 parentTNode = tNode.parent;
7428 }
7429 // If the parent tNode is null, then we are inserting across views: either into an embedded view
7430 // or a component view.
7431 if (parentTNode === null) {
7432 // We are inserting a root element of the component view into the component host element and
7433 // it should always be eager.
7434 return lView[HOST];
7435 }
7436 else {
7437 ngDevMode && assertTNodeType(parentTNode, 3 /* AnyRNode */ | 4 /* Container */);
7438 if (parentTNode.flags & 2 /* isComponentHost */) {
7439 ngDevMode && assertTNodeForLView(parentTNode, lView);
7440 const encapsulation = tView.data[parentTNode.directiveStart].encapsulation;
7441 // We've got a parent which is an element in the current view. We just need to verify if the
7442 // parent element is not a component. Component's content nodes are not inserted immediately
7443 // because they will be projected, and so doing insert at this point would be wasteful.
7444 // Since the projection would then move it to its final destination. Note that we can't
7445 // make this assumption when using the Shadow DOM, because the native projection placeholders
7446 // (<content> or <slot>) have to be in place as elements are being inserted.
7447 if (encapsulation === ViewEncapsulation$1.None ||
7448 encapsulation === ViewEncapsulation$1.Emulated) {
7449 return null;
7450 }
7451 }
7452 return getNativeByTNode(parentTNode, lView);
7453 }
7454}
7455/**
7456 * Inserts a native node before another native node for a given parent using {@link Renderer3}.
7457 * This is a utility function that can be used when native nodes were determined - it abstracts an
7458 * actual renderer being used.
7459 */
7460function nativeInsertBefore(renderer, parent, child, beforeNode, isMove) {
7461 ngDevMode && ngDevMode.rendererInsertBefore++;
7462 if (isProceduralRenderer(renderer)) {
7463 renderer.insertBefore(parent, child, beforeNode, isMove);
7464 }
7465 else {
7466 parent.insertBefore(child, beforeNode, isMove);
7467 }
7468}
7469function nativeAppendChild(renderer, parent, child) {
7470 ngDevMode && ngDevMode.rendererAppendChild++;
7471 ngDevMode && assertDefined(parent, 'parent node must be defined');
7472 if (isProceduralRenderer(renderer)) {
7473 renderer.appendChild(parent, child);
7474 }
7475 else {
7476 parent.appendChild(child);
7477 }
7478}
7479function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove) {
7480 if (beforeNode !== null) {
7481 nativeInsertBefore(renderer, parent, child, beforeNode, isMove);
7482 }
7483 else {
7484 nativeAppendChild(renderer, parent, child);
7485 }
7486}
7487/** Removes a node from the DOM given its native parent. */
7488function nativeRemoveChild(renderer, parent, child, isHostElement) {
7489 if (isProceduralRenderer(renderer)) {
7490 renderer.removeChild(parent, child, isHostElement);
7491 }
7492 else {
7493 parent.removeChild(child);
7494 }
7495}
7496/**
7497 * Returns a native parent of a given native node.
7498 */
7499function nativeParentNode(renderer, node) {
7500 return (isProceduralRenderer(renderer) ? renderer.parentNode(node) : node.parentNode);
7501}
7502/**
7503 * Returns a native sibling of a given native node.
7504 */
7505function nativeNextSibling(renderer, node) {
7506 return isProceduralRenderer(renderer) ? renderer.nextSibling(node) : node.nextSibling;
7507}
7508/**
7509 * Find a node in front of which `currentTNode` should be inserted.
7510 *
7511 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
7512 * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.
7513 *
7514 * @param parentTNode parent `TNode`
7515 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
7516 * @param lView current `LView`
7517 */
7518function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {
7519 return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);
7520}
7521/**
7522 * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into
7523 * account)
7524 *
7525 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
7526 * does not take `TNode.insertBeforeIndex` into account.
7527 *
7528 * @param parentTNode parent `TNode`
7529 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
7530 * @param lView current `LView`
7531 */
7532function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {
7533 if (parentTNode.type & (8 /* ElementContainer */ | 32 /* Icu */)) {
7534 return getNativeByTNode(parentTNode, lView);
7535 }
7536 return null;
7537}
7538/**
7539 * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.
7540 *
7541 * This function will only be set if i18n code runs.
7542 */
7543let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;
7544/**
7545 * Tree shakable boundary for `processI18nInsertBefore` function.
7546 *
7547 * This function will only be set if i18n code runs.
7548 */
7549let _processI18nInsertBefore;
7550function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {
7551 _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;
7552 _processI18nInsertBefore = processI18nInsertBefore;
7553}
7554/**
7555 * Appends the `child` native node (or a collection of nodes) to the `parent`.
7556 *
7557 * @param tView The `TView' to be appended
7558 * @param lView The current LView
7559 * @param childRNode The native child (or children) that should be appended
7560 * @param childTNode The TNode of the child element
7561 */
7562function appendChild(tView, lView, childRNode, childTNode) {
7563 const parentRNode = getParentRElement(tView, childTNode, lView);
7564 const renderer = lView[RENDERER];
7565 const parentTNode = childTNode.parent || lView[T_HOST];
7566 const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);
7567 if (parentRNode != null) {
7568 if (Array.isArray(childRNode)) {
7569 for (let i = 0; i < childRNode.length; i++) {
7570 nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);
7571 }
7572 }
7573 else {
7574 nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
7575 }
7576 }
7577 _processI18nInsertBefore !== undefined &&
7578 _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
7579}
7580/**
7581 * Returns the first native node for a given LView, starting from the provided TNode.
7582 *
7583 * Native nodes are returned in the order in which those appear in the native tree (DOM).
7584 */
7585function getFirstNativeNode(lView, tNode) {
7586 if (tNode !== null) {
7587 ngDevMode &&
7588 assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */ | 32 /* Icu */ | 16 /* Projection */);
7589 const tNodeType = tNode.type;
7590 if (tNodeType & 3 /* AnyRNode */) {
7591 return getNativeByTNode(tNode, lView);
7592 }
7593 else if (tNodeType & 4 /* Container */) {
7594 return getBeforeNodeForView(-1, lView[tNode.index]);
7595 }
7596 else if (tNodeType & 8 /* ElementContainer */) {
7597 const elIcuContainerChild = tNode.child;
7598 if (elIcuContainerChild !== null) {
7599 return getFirstNativeNode(lView, elIcuContainerChild);
7600 }
7601 else {
7602 const rNodeOrLContainer = lView[tNode.index];
7603 if (isLContainer(rNodeOrLContainer)) {
7604 return getBeforeNodeForView(-1, rNodeOrLContainer);
7605 }
7606 else {
7607 return unwrapRNode(rNodeOrLContainer);
7608 }
7609 }
7610 }
7611 else if (tNodeType & 32 /* Icu */) {
7612 let nextRNode = icuContainerIterate(tNode, lView);
7613 let rNode = nextRNode();
7614 // If the ICU container has no nodes, than we use the ICU anchor as the node.
7615 return rNode || unwrapRNode(lView[tNode.index]);
7616 }
7617 else {
7618 const projectionNodes = getProjectionNodes(lView, tNode);
7619 if (projectionNodes !== null) {
7620 if (Array.isArray(projectionNodes)) {
7621 return projectionNodes[0];
7622 }
7623 const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
7624 ngDevMode && assertParentView(parentView);
7625 return getFirstNativeNode(parentView, projectionNodes);
7626 }
7627 else {
7628 return getFirstNativeNode(lView, tNode.next);
7629 }
7630 }
7631 }
7632 return null;
7633}
7634function getProjectionNodes(lView, tNode) {
7635 if (tNode !== null) {
7636 const componentView = lView[DECLARATION_COMPONENT_VIEW];
7637 const componentHost = componentView[T_HOST];
7638 const slotIdx = tNode.projection;
7639 ngDevMode && assertProjectionSlots(lView);
7640 return componentHost.projection[slotIdx];
7641 }
7642 return null;
7643}
7644function getBeforeNodeForView(viewIndexInContainer, lContainer) {
7645 const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;
7646 if (nextViewIndex < lContainer.length) {
7647 const lView = lContainer[nextViewIndex];
7648 const firstTNodeOfView = lView[TVIEW].firstChild;
7649 if (firstTNodeOfView !== null) {
7650 return getFirstNativeNode(lView, firstTNodeOfView);
7651 }
7652 }
7653 return lContainer[NATIVE];
7654}
7655/**
7656 * Removes a native node itself using a given renderer. To remove the node we are looking up its
7657 * parent from the native tree as not all platforms / browsers support the equivalent of
7658 * node.remove().
7659 *
7660 * @param renderer A renderer to be used
7661 * @param rNode The native node that should be removed
7662 * @param isHostElement A flag indicating if a node to be removed is a host of a component.
7663 */
7664function nativeRemoveNode(renderer, rNode, isHostElement) {
7665 ngDevMode && ngDevMode.rendererRemoveNode++;
7666 const nativeParent = nativeParentNode(renderer, rNode);
7667 if (nativeParent) {
7668 nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);
7669 }
7670}
7671/**
7672 * Performs the operation of `action` on the node. Typically this involves inserting or removing
7673 * nodes on the LView or projection boundary.
7674 */
7675function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {
7676 while (tNode != null) {
7677 ngDevMode && assertTNodeForLView(tNode, lView);
7678 ngDevMode &&
7679 assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */ | 16 /* Projection */ | 32 /* Icu */);
7680 const rawSlotValue = lView[tNode.index];
7681 const tNodeType = tNode.type;
7682 if (isProjection) {
7683 if (action === 0 /* Create */) {
7684 rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
7685 tNode.flags |= 4 /* isProjected */;
7686 }
7687 }
7688 if ((tNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
7689 if (tNodeType & 8 /* ElementContainer */) {
7690 applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
7691 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7692 }
7693 else if (tNodeType & 32 /* Icu */) {
7694 const nextRNode = icuContainerIterate(tNode, lView);
7695 let rNode;
7696 while (rNode = nextRNode()) {
7697 applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
7698 }
7699 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7700 }
7701 else if (tNodeType & 16 /* Projection */) {
7702 applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);
7703 }
7704 else {
7705 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 4 /* Container */);
7706 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7707 }
7708 }
7709 tNode = isProjection ? tNode.projectionNext : tNode.next;
7710 }
7711}
7712function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
7713 applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
7714}
7715/**
7716 * `applyProjection` performs operation on the projection.
7717 *
7718 * Inserting a projection requires us to locate the projected nodes from the parent component. The
7719 * complication is that those nodes themselves could be re-projected from their parent component.
7720 *
7721 * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
7722 * @param lView The `LView` which needs to be inserted, detached, destroyed.
7723 * @param tProjectionNode node to project
7724 */
7725function applyProjection(tView, lView, tProjectionNode) {
7726 const renderer = lView[RENDERER];
7727 const parentRNode = getParentRElement(tView, tProjectionNode, lView);
7728 const parentTNode = tProjectionNode.parent || lView[T_HOST];
7729 let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);
7730 applyProjectionRecursive(renderer, 0 /* Create */, lView, tProjectionNode, parentRNode, beforeNode);
7731}
7732/**
7733 * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,
7734 * detach, destroy)
7735 *
7736 * Inserting a projection requires us to locate the projected nodes from the parent component. The
7737 * complication is that those nodes themselves could be re-projected from their parent component.
7738 *
7739 * @param renderer Render to use
7740 * @param action action to perform (insert, detach, destroy)
7741 * @param lView The LView which needs to be inserted, detached, destroyed.
7742 * @param tProjectionNode node to project
7743 * @param parentRElement parent DOM element for insertion/removal.
7744 * @param beforeNode Before which node the insertions should happen.
7745 */
7746function applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) {
7747 const componentLView = lView[DECLARATION_COMPONENT_VIEW];
7748 const componentNode = componentLView[T_HOST];
7749 ngDevMode &&
7750 assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');
7751 const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection];
7752 if (Array.isArray(nodeToProjectOrRNodes)) {
7753 // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we
7754 // need to support passing projectable nodes, so we cheat and put them in the TNode
7755 // of the Host TView. (Yes we put instance info at the T Level). We can get away with it
7756 // because we know that that TView is not shared and therefore it will not be a problem.
7757 // This should be refactored and cleaned up.
7758 for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {
7759 const rNode = nodeToProjectOrRNodes[i];
7760 applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
7761 }
7762 }
7763 else {
7764 let nodeToProject = nodeToProjectOrRNodes;
7765 const projectedComponentLView = componentLView[PARENT];
7766 applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
7767 }
7768}
7769/**
7770 * `applyContainer` performs an operation on the container and its views as specified by
7771 * `action` (insert, detach, destroy)
7772 *
7773 * Inserting a Container is complicated by the fact that the container may have Views which
7774 * themselves have containers or projections.
7775 *
7776 * @param renderer Renderer to use
7777 * @param action action to perform (insert, detach, destroy)
7778 * @param lContainer The LContainer which needs to be inserted, detached, destroyed.
7779 * @param parentRElement parent DOM element for insertion/removal.
7780 * @param beforeNode Before which node the insertions should happen.
7781 */
7782function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {
7783 ngDevMode && assertLContainer(lContainer);
7784 const anchor = lContainer[NATIVE]; // LContainer has its own before node.
7785 const native = unwrapRNode(lContainer);
7786 // An LContainer can be created dynamically on any node by injecting ViewContainerRef.
7787 // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor
7788 // node (comment in the DOM) that will be different from the LContainer's host node. In this
7789 // particular case we need to execute action on 2 nodes:
7790 // - container's host node (this is done in the executeActionOnElementOrContainer)
7791 // - container's host node (this is done here)
7792 if (anchor !== native) {
7793 // This is very strange to me (Misko). I would expect that the native is same as anchor. I
7794 // don't see a reason why they should be different, but they are.
7795 //
7796 // If they are we need to process the second anchor as well.
7797 applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
7798 }
7799 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
7800 const lView = lContainer[i];
7801 applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);
7802 }
7803}
7804/**
7805 * Writes class/style to element.
7806 *
7807 * @param renderer Renderer to use.
7808 * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)
7809 * @param rNode The Node to write to.
7810 * @param prop Property to write to. This would be the class/style name.
7811 * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add
7812 * otherwise).
7813 */
7814function applyStyling(renderer, isClassBased, rNode, prop, value) {
7815 const isProcedural = isProceduralRenderer(renderer);
7816 if (isClassBased) {
7817 // We actually want JS true/false here because any truthy value should add the class
7818 if (!value) {
7819 ngDevMode && ngDevMode.rendererRemoveClass++;
7820 if (isProcedural) {
7821 renderer.removeClass(rNode, prop);
7822 }
7823 else {
7824 rNode.classList.remove(prop);
7825 }
7826 }
7827 else {
7828 ngDevMode && ngDevMode.rendererAddClass++;
7829 if (isProcedural) {
7830 renderer.addClass(rNode, prop);
7831 }
7832 else {
7833 ngDevMode && assertDefined(rNode.classList, 'HTMLElement expected');
7834 rNode.classList.add(prop);
7835 }
7836 }
7837 }
7838 else {
7839 let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;
7840 if (value == null /** || value === undefined */) {
7841 ngDevMode && ngDevMode.rendererRemoveStyle++;
7842 if (isProcedural) {
7843 renderer.removeStyle(rNode, prop, flags);
7844 }
7845 else {
7846 rNode.style.removeProperty(prop);
7847 }
7848 }
7849 else {
7850 // A value is important if it ends with `!important`. The style
7851 // parser strips any semicolons at the end of the value.
7852 const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;
7853 if (isImportant) {
7854 // !important has to be stripped from the value for it to be valid.
7855 value = value.slice(0, -10);
7856 flags |= RendererStyleFlags2.Important;
7857 }
7858 ngDevMode && ngDevMode.rendererSetStyle++;
7859 if (isProcedural) {
7860 renderer.setStyle(rNode, prop, value, flags);
7861 }
7862 else {
7863 ngDevMode && assertDefined(rNode.style, 'HTMLElement expected');
7864 rNode.style.setProperty(prop, value, isImportant ? 'important' : '');
7865 }
7866 }
7867 }
7868}
7869/**
7870 * Write `cssText` to `RElement`.
7871 *
7872 * This function does direct write without any reconciliation. Used for writing initial values, so
7873 * that static styling values do not pull in the style parser.
7874 *
7875 * @param renderer Renderer to use
7876 * @param element The element which needs to be updated.
7877 * @param newValue The new class list to write.
7878 */
7879function writeDirectStyle(renderer, element, newValue) {
7880 ngDevMode && assertString(newValue, '\'newValue\' should be a string');
7881 if (isProceduralRenderer(renderer)) {
7882 renderer.setAttribute(element, 'style', newValue);
7883 }
7884 else {
7885 element.style.cssText = newValue;
7886 }
7887 ngDevMode && ngDevMode.rendererSetStyle++;
7888}
7889/**
7890 * Write `className` to `RElement`.
7891 *
7892 * This function does direct write without any reconciliation. Used for writing initial values, so
7893 * that static styling values do not pull in the style parser.
7894 *
7895 * @param renderer Renderer to use
7896 * @param element The element which needs to be updated.
7897 * @param newValue The new class list to write.
7898 */
7899function writeDirectClass(renderer, element, newValue) {
7900 ngDevMode && assertString(newValue, '\'newValue\' should be a string');
7901 if (isProceduralRenderer(renderer)) {
7902 if (newValue === '') {
7903 // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.
7904 renderer.removeAttribute(element, 'class');
7905 }
7906 else {
7907 renderer.setAttribute(element, 'class', newValue);
7908 }
7909 }
7910 else {
7911 element.className = newValue;
7912 }
7913 ngDevMode && ngDevMode.rendererSetClassName++;
7914}
7915
7916/**
7917 * @license
7918 * Copyright Google LLC All Rights Reserved.
7919 *
7920 * Use of this source code is governed by an MIT-style license that can be
7921 * found in the LICENSE file at https://angular.io/license
7922 */
7923/**
7924 * Returns an index of `classToSearch` in `className` taking token boundaries into account.
7925 *
7926 * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`)
7927 *
7928 * @param className A string containing classes (whitespace separated)
7929 * @param classToSearch A class name to locate
7930 * @param startingIndex Starting location of search
7931 * @returns an index of the located class (or -1 if not found)
7932 */
7933function classIndexOf(className, classToSearch, startingIndex) {
7934 ngDevMode && assertNotEqual(classToSearch, '', 'can not look for "" string.');
7935 let end = className.length;
7936 while (true) {
7937 const foundIndex = className.indexOf(classToSearch, startingIndex);
7938 if (foundIndex === -1)
7939 return foundIndex;
7940 if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32 /* SPACE */) {
7941 // Ensure that it has leading whitespace
7942 const length = classToSearch.length;
7943 if (foundIndex + length === end ||
7944 className.charCodeAt(foundIndex + length) <= 32 /* SPACE */) {
7945 // Ensure that it has trailing whitespace
7946 return foundIndex;
7947 }
7948 }
7949 // False positive, keep searching from where we left off.
7950 startingIndex = foundIndex + 1;
7951 }
7952}
7953
7954/**
7955 * @license
7956 * Copyright Google LLC All Rights Reserved.
7957 *
7958 * Use of this source code is governed by an MIT-style license that can be
7959 * found in the LICENSE file at https://angular.io/license
7960 */
7961const unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3;
7962const NG_TEMPLATE_SELECTOR = 'ng-template';
7963/**
7964 * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)
7965 *
7966 * @param attrs `TAttributes` to search through.
7967 * @param cssClassToMatch class to match (lowercase)
7968 * @param isProjectionMode Whether or not class matching should look into the attribute `class` in
7969 * addition to the `AttributeMarker.Classes`.
7970 */
7971function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
7972 // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect.
7973 // It is strange to me that sometimes the class information comes in form of `class` attribute
7974 // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine
7975 // if that is the right behavior.
7976 ngDevMode &&
7977 assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
7978 let i = 0;
7979 while (i < attrs.length) {
7980 let item = attrs[i++];
7981 if (isProjectionMode && item === 'class') {
7982 item = attrs[i];
7983 if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
7984 return true;
7985 }
7986 }
7987 else if (item === 1 /* Classes */) {
7988 // We found the classes section. Start searching for the class.
7989 while (i < attrs.length && typeof (item = attrs[i++]) == 'string') {
7990 // while we have strings
7991 if (item.toLowerCase() === cssClassToMatch)
7992 return true;
7993 }
7994 return false;
7995 }
7996 }
7997 return false;
7998}
7999/**
8000 * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`).
8001 *
8002 * @param tNode current TNode
8003 */
8004function isInlineTemplate(tNode) {
8005 return tNode.type === 4 /* Container */ && tNode.value !== NG_TEMPLATE_SELECTOR;
8006}
8007/**
8008 * Function that checks whether a given tNode matches tag-based selector and has a valid type.
8009 *
8010 * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular
8011 * directive matching mode:
8012 * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is
8013 * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a
8014 * tag name was extracted from * syntax so we would match the same directive twice);
8015 * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing
8016 * (applicable to TNodeType.Container only).
8017 */
8018function hasTagAndTypeMatch(tNode, currentSelector, isProjectionMode) {
8019 const tagNameToCompare = tNode.type === 4 /* Container */ && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value;
8020 return currentSelector === tagNameToCompare;
8021}
8022/**
8023 * A utility function to match an Ivy node static data against a simple CSS selector
8024 *
8025 * @param node static data of the node to match
8026 * @param selector The selector to try matching against the node.
8027 * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing
8028 * directive matching.
8029 * @returns true if node matches the selector.
8030 */
8031function isNodeMatchingSelector(tNode, selector, isProjectionMode) {
8032 ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');
8033 let mode = 4 /* ELEMENT */;
8034 const nodeAttrs = tNode.attrs || [];
8035 // Find the index of first attribute that has no value, only a name.
8036 const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs);
8037 // When processing ":not" selectors, we skip to the next ":not" if the
8038 // current one doesn't match
8039 let skipToNextSelector = false;
8040 for (let i = 0; i < selector.length; i++) {
8041 const current = selector[i];
8042 if (typeof current === 'number') {
8043 // If we finish processing a :not selector and it hasn't failed, return false
8044 if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) {
8045 return false;
8046 }
8047 // If we are skipping to the next :not() and this mode flag is positive,
8048 // it's a part of the current :not() selector, and we should keep skipping
8049 if (skipToNextSelector && isPositive(current))
8050 continue;
8051 skipToNextSelector = false;
8052 mode = current | (mode & 1 /* NOT */);
8053 continue;
8054 }
8055 if (skipToNextSelector)
8056 continue;
8057 if (mode & 4 /* ELEMENT */) {
8058 mode = 2 /* ATTRIBUTE */ | mode & 1 /* NOT */;
8059 if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) ||
8060 current === '' && selector.length === 1) {
8061 if (isPositive(mode))
8062 return false;
8063 skipToNextSelector = true;
8064 }
8065 }
8066 else {
8067 const selectorAttrValue = mode & 8 /* CLASS */ ? current : selector[++i];
8068 // special case for matching against classes when a tNode has been instantiated with
8069 // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo'])
8070 if ((mode & 8 /* CLASS */) && tNode.attrs !== null) {
8071 if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) {
8072 if (isPositive(mode))
8073 return false;
8074 skipToNextSelector = true;
8075 }
8076 continue;
8077 }
8078 const attrName = (mode & 8 /* CLASS */) ? 'class' : current;
8079 const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);
8080 if (attrIndexInNode === -1) {
8081 if (isPositive(mode))
8082 return false;
8083 skipToNextSelector = true;
8084 continue;
8085 }
8086 if (selectorAttrValue !== '') {
8087 let nodeAttrValue;
8088 if (attrIndexInNode > nameOnlyMarkerIdx) {
8089 nodeAttrValue = '';
8090 }
8091 else {
8092 ngDevMode &&
8093 assertNotEqual(nodeAttrs[attrIndexInNode], 0 /* NamespaceURI */, 'We do not match directives on namespaced attributes');
8094 // we lowercase the attribute value to be able to match
8095 // selectors without case-sensitivity
8096 // (selectors are already in lowercase when generated)
8097 nodeAttrValue = nodeAttrs[attrIndexInNode + 1].toLowerCase();
8098 }
8099 const compareAgainstClassName = mode & 8 /* CLASS */ ? nodeAttrValue : null;
8100 if (compareAgainstClassName &&
8101 classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 ||
8102 mode & 2 /* ATTRIBUTE */ && selectorAttrValue !== nodeAttrValue) {
8103 if (isPositive(mode))
8104 return false;
8105 skipToNextSelector = true;
8106 }
8107 }
8108 }
8109 }
8110 return isPositive(mode) || skipToNextSelector;
8111}
8112function isPositive(mode) {
8113 return (mode & 1 /* NOT */) === 0;
8114}
8115/**
8116 * Examines the attribute's definition array for a node to find the index of the
8117 * attribute that matches the given `name`.
8118 *
8119 * NOTE: This will not match namespaced attributes.
8120 *
8121 * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`.
8122 * The following table summarizes which types of attributes we attempt to match:
8123 *
8124 * ===========================================================================================================
8125 * Modes | Normal Attributes | Bindings Attributes | Template Attributes | I18n
8126 * Attributes
8127 * ===========================================================================================================
8128 * Inline + Projection | YES | YES | NO | YES
8129 * -----------------------------------------------------------------------------------------------------------
8130 * Inline + Directive | NO | NO | YES | NO
8131 * -----------------------------------------------------------------------------------------------------------
8132 * Non-inline + Projection | YES | YES | NO | YES
8133 * -----------------------------------------------------------------------------------------------------------
8134 * Non-inline + Directive | YES | YES | NO | YES
8135 * ===========================================================================================================
8136 *
8137 * @param name the name of the attribute to find
8138 * @param attrs the attribute array to examine
8139 * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`)
8140 * rather than a manually expanded template node (e.g `<ng-template>`).
8141 * @param isProjectionMode true if we are matching against content projection otherwise we are
8142 * matching against directives.
8143 */
8144function findAttrIndexInNode(name, attrs, isInlineTemplate, isProjectionMode) {
8145 if (attrs === null)
8146 return -1;
8147 let i = 0;
8148 if (isProjectionMode || !isInlineTemplate) {
8149 let bindingsMode = false;
8150 while (i < attrs.length) {
8151 const maybeAttrName = attrs[i];
8152 if (maybeAttrName === name) {
8153 return i;
8154 }
8155 else if (maybeAttrName === 3 /* Bindings */ || maybeAttrName === 6 /* I18n */) {
8156 bindingsMode = true;
8157 }
8158 else if (maybeAttrName === 1 /* Classes */ || maybeAttrName === 2 /* Styles */) {
8159 let value = attrs[++i];
8160 // We should skip classes here because we have a separate mechanism for
8161 // matching classes in projection mode.
8162 while (typeof value === 'string') {
8163 value = attrs[++i];
8164 }
8165 continue;
8166 }
8167 else if (maybeAttrName === 4 /* Template */) {
8168 // We do not care about Template attributes in this scenario.
8169 break;
8170 }
8171 else if (maybeAttrName === 0 /* NamespaceURI */) {
8172 // Skip the whole namespaced attribute and value. This is by design.
8173 i += 4;
8174 continue;
8175 }
8176 // In binding mode there are only names, rather than name-value pairs.
8177 i += bindingsMode ? 1 : 2;
8178 }
8179 // We did not match the attribute
8180 return -1;
8181 }
8182 else {
8183 return matchTemplateAttribute(attrs, name);
8184 }
8185}
8186function isNodeMatchingSelectorList(tNode, selector, isProjectionMode = false) {
8187 for (let i = 0; i < selector.length; i++) {
8188 if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {
8189 return true;
8190 }
8191 }
8192 return false;
8193}
8194function getProjectAsAttrValue(tNode) {
8195 const nodeAttrs = tNode.attrs;
8196 if (nodeAttrs != null) {
8197 const ngProjectAsAttrIdx = nodeAttrs.indexOf(5 /* ProjectAs */);
8198 // only check for ngProjectAs in attribute names, don't accidentally match attribute's value
8199 // (attribute names are stored at even indexes)
8200 if ((ngProjectAsAttrIdx & 1) === 0) {
8201 return nodeAttrs[ngProjectAsAttrIdx + 1];
8202 }
8203 }
8204 return null;
8205}
8206function getNameOnlyMarkerIndex(nodeAttrs) {
8207 for (let i = 0; i < nodeAttrs.length; i++) {
8208 const nodeAttr = nodeAttrs[i];
8209 if (isNameOnlyAttributeMarker(nodeAttr)) {
8210 return i;
8211 }
8212 }
8213 return nodeAttrs.length;
8214}
8215function matchTemplateAttribute(attrs, name) {
8216 let i = attrs.indexOf(4 /* Template */);
8217 if (i > -1) {
8218 i++;
8219 while (i < attrs.length) {
8220 const attr = attrs[i];
8221 // Return in case we checked all template attrs and are switching to the next section in the
8222 // attrs array (that starts with a number that represents an attribute marker).
8223 if (typeof attr === 'number')
8224 return -1;
8225 if (attr === name)
8226 return i;
8227 i++;
8228 }
8229 }
8230 return -1;
8231}
8232/**
8233 * Checks whether a selector is inside a CssSelectorList
8234 * @param selector Selector to be checked.
8235 * @param list List in which to look for the selector.
8236 */
8237function isSelectorInSelectorList(selector, list) {
8238 selectorListLoop: for (let i = 0; i < list.length; i++) {
8239 const currentSelectorInList = list[i];
8240 if (selector.length !== currentSelectorInList.length) {
8241 continue;
8242 }
8243 for (let j = 0; j < selector.length; j++) {
8244 if (selector[j] !== currentSelectorInList[j]) {
8245 continue selectorListLoop;
8246 }
8247 }
8248 return true;
8249 }
8250 return false;
8251}
8252function maybeWrapInNotSelector(isNegativeMode, chunk) {
8253 return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk;
8254}
8255function stringifyCSSSelector(selector) {
8256 let result = selector[0];
8257 let i = 1;
8258 let mode = 2 /* ATTRIBUTE */;
8259 let currentChunk = '';
8260 let isNegativeMode = false;
8261 while (i < selector.length) {
8262 let valueOrMarker = selector[i];
8263 if (typeof valueOrMarker === 'string') {
8264 if (mode & 2 /* ATTRIBUTE */) {
8265 const attrValue = selector[++i];
8266 currentChunk +=
8267 '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']';
8268 }
8269 else if (mode & 8 /* CLASS */) {
8270 currentChunk += '.' + valueOrMarker;
8271 }
8272 else if (mode & 4 /* ELEMENT */) {
8273 currentChunk += ' ' + valueOrMarker;
8274 }
8275 }
8276 else {
8277 //
8278 // Append current chunk to the final result in case we come across SelectorFlag, which
8279 // indicates that the previous section of a selector is over. We need to accumulate content
8280 // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g.
8281 // ```
8282 // ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC']
8283 // ```
8284 // should be transformed to `.classA :not(.classB .classC)`.
8285 //
8286 // Note: for negative selector part, we accumulate content between flags until we find the
8287 // next negative flag. This is needed to support a case where `:not()` rule contains more than
8288 // one chunk, e.g. the following selector:
8289 // ```
8290 // ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar']
8291 // ```
8292 // should be stringified to `:not(p.foo) :not(.bar)`
8293 //
8294 if (currentChunk !== '' && !isPositive(valueOrMarker)) {
8295 result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
8296 currentChunk = '';
8297 }
8298 mode = valueOrMarker;
8299 // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
8300 // mode is maintained for remaining chunks of a selector.
8301 isNegativeMode = isNegativeMode || !isPositive(mode);
8302 }
8303 i++;
8304 }
8305 if (currentChunk !== '') {
8306 result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
8307 }
8308 return result;
8309}
8310/**
8311 * Generates string representation of CSS selector in parsed form.
8312 *
8313 * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing
8314 * additional parsing at runtime (for example, for directive matching). However in some cases (for
8315 * example, while bootstrapping a component), a string version of the selector is required to query
8316 * for the host element on the page. This function takes the parsed form of a selector and returns
8317 * its string representation.
8318 *
8319 * @param selectorList selector in parsed form
8320 * @returns string representation of a given selector
8321 */
8322function stringifyCSSSelectorList(selectorList) {
8323 return selectorList.map(stringifyCSSSelector).join(',');
8324}
8325/**
8326 * Extracts attributes and classes information from a given CSS selector.
8327 *
8328 * This function is used while creating a component dynamically. In this case, the host element
8329 * (that is created dynamically) should contain attributes and classes specified in component's CSS
8330 * selector.
8331 *
8332 * @param selector CSS selector in parsed form (in a form of array)
8333 * @returns object with `attrs` and `classes` fields that contain extracted information
8334 */
8335function extractAttrsAndClassesFromSelector(selector) {
8336 const attrs = [];
8337 const classes = [];
8338 let i = 1;
8339 let mode = 2 /* ATTRIBUTE */;
8340 while (i < selector.length) {
8341 let valueOrMarker = selector[i];
8342 if (typeof valueOrMarker === 'string') {
8343 if (mode === 2 /* ATTRIBUTE */) {
8344 if (valueOrMarker !== '') {
8345 attrs.push(valueOrMarker, selector[++i]);
8346 }
8347 }
8348 else if (mode === 8 /* CLASS */) {
8349 classes.push(valueOrMarker);
8350 }
8351 }
8352 else {
8353 // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
8354 // mode is maintained for remaining chunks of a selector. Since attributes and classes are
8355 // extracted only for "positive" part of the selector, we can stop here.
8356 if (!isPositive(mode))
8357 break;
8358 mode = valueOrMarker;
8359 }
8360 i++;
8361 }
8362 return { attrs, classes };
8363}
8364
8365/**
8366 * @license
8367 * Copyright Google LLC All Rights Reserved.
8368 *
8369 * Use of this source code is governed by an MIT-style license that can be
8370 * found in the LICENSE file at https://angular.io/license
8371 */
8372/** A special value which designates that a value has not changed. */
8373const NO_CHANGE = (typeof ngDevMode === 'undefined' || ngDevMode) ? { __brand__: 'NO_CHANGE' } : {};
8374
8375/**
8376 * @license
8377 * Copyright Google LLC All Rights Reserved.
8378 *
8379 * Use of this source code is governed by an MIT-style license that can be
8380 * found in the LICENSE file at https://angular.io/license
8381 */
8382/**
8383 * Advances to an element for later binding instructions.
8384 *
8385 * Used in conjunction with instructions like {@link property} to act on elements with specified
8386 * indices, for example those created with {@link element} or {@link elementStart}.
8387 *
8388 * ```ts
8389 * (rf: RenderFlags, ctx: any) => {
8390 * if (rf & 1) {
8391 * text(0, 'Hello');
8392 * text(1, 'Goodbye')
8393 * element(2, 'div');
8394 * }
8395 * if (rf & 2) {
8396 * advance(2); // Advance twice to the <div>.
8397 * property('title', 'test');
8398 * }
8399 * }
8400 * ```
8401 * @param delta Number of elements to advance forwards by.
8402 *
8403 * @codeGenApi
8404 */
8405function ɵɵadvance(delta) {
8406 ngDevMode && assertGreaterThan(delta, 0, 'Can only advance forward');
8407 selectIndexInternal(getTView(), getLView(), getSelectedIndex() + delta, isInCheckNoChangesMode());
8408}
8409function selectIndexInternal(tView, lView, index, checkNoChangesMode) {
8410 ngDevMode && assertIndexInDeclRange(lView, index);
8411 // Flush the initial hooks for elements in the view that have been added up to this point.
8412 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
8413 if (!checkNoChangesMode) {
8414 const hooksInitPhaseCompleted = (lView[FLAGS] & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;
8415 if (hooksInitPhaseCompleted) {
8416 const preOrderCheckHooks = tView.preOrderCheckHooks;
8417 if (preOrderCheckHooks !== null) {
8418 executeCheckHooks(lView, preOrderCheckHooks, index);
8419 }
8420 }
8421 else {
8422 const preOrderHooks = tView.preOrderHooks;
8423 if (preOrderHooks !== null) {
8424 executeInitAndCheckHooks(lView, preOrderHooks, 0 /* OnInitHooksToBeRun */, index);
8425 }
8426 }
8427 }
8428 // We must set the selected index *after* running the hooks, because hooks may have side-effects
8429 // that cause other template functions to run, thus updating the selected index, which is global
8430 // state. If we run `setSelectedIndex` *before* we run the hooks, in some cases the selected index
8431 // will be altered by the time we leave the `ɵɵadvance` instruction.
8432 setSelectedIndex(index);
8433}
8434
8435/**
8436 * @license
8437 * Copyright Google LLC All Rights Reserved.
8438 *
8439 * Use of this source code is governed by an MIT-style license that can be
8440 * found in the LICENSE file at https://angular.io/license
8441 */
8442/**
8443 * THIS FILE CONTAINS CODE WHICH SHOULD BE TREE SHAKEN AND NEVER CALLED FROM PRODUCTION CODE!!!
8444 */
8445/**
8446 * Creates an `Array` construction with a given name. This is useful when
8447 * looking for memory consumption to see what time of array it is.
8448 *
8449 *
8450 * @param name Name to give to the constructor
8451 * @returns A subclass of `Array` if possible. This can only be done in
8452 * environments which support `class` construct.
8453 */
8454function createNamedArrayType(name) {
8455 // This should never be called in prod mode, so let's verify that is the case.
8456 if (ngDevMode) {
8457 try {
8458 // If this function were compromised the following could lead to arbitrary
8459 // script execution. We bless it with Trusted Types anyway since this
8460 // function is stripped out of production binaries.
8461 return (newTrustedFunctionForDev('Array', `return class ${name} extends Array{}`))(Array);
8462 }
8463 catch (e) {
8464 // If it does not work just give up and fall back to regular Array.
8465 return Array;
8466 }
8467 }
8468 else {
8469 throw new Error('Looks like we are in \'prod mode\', but we are creating a named Array type, which is wrong! Check your code');
8470 }
8471}
8472
8473/**
8474 * @license
8475 * Copyright Google LLC All Rights Reserved.
8476 *
8477 * Use of this source code is governed by an MIT-style license that can be
8478 * found in the LICENSE file at https://angular.io/license
8479 */
8480function toTStylingRange(prev, next) {
8481 ngDevMode && assertNumberInRange(prev, 0, 32767 /* UNSIGNED_MASK */);
8482 ngDevMode && assertNumberInRange(next, 0, 32767 /* UNSIGNED_MASK */);
8483 return (prev << 17 /* PREV_SHIFT */ | next << 2 /* NEXT_SHIFT */);
8484}
8485function getTStylingRangePrev(tStylingRange) {
8486 ngDevMode && assertNumber(tStylingRange, 'expected number');
8487 return (tStylingRange >> 17 /* PREV_SHIFT */) & 32767 /* UNSIGNED_MASK */;
8488}
8489function getTStylingRangePrevDuplicate(tStylingRange) {
8490 ngDevMode && assertNumber(tStylingRange, 'expected number');
8491 return (tStylingRange & 2 /* PREV_DUPLICATE */) ==
8492 2 /* PREV_DUPLICATE */;
8493}
8494function setTStylingRangePrev(tStylingRange, previous) {
8495 ngDevMode && assertNumber(tStylingRange, 'expected number');
8496 ngDevMode && assertNumberInRange(previous, 0, 32767 /* UNSIGNED_MASK */);
8497 return ((tStylingRange & ~4294836224 /* PREV_MASK */) |
8498 (previous << 17 /* PREV_SHIFT */));
8499}
8500function setTStylingRangePrevDuplicate(tStylingRange) {
8501 ngDevMode && assertNumber(tStylingRange, 'expected number');
8502 return (tStylingRange | 2 /* PREV_DUPLICATE */);
8503}
8504function getTStylingRangeNext(tStylingRange) {
8505 ngDevMode && assertNumber(tStylingRange, 'expected number');
8506 return (tStylingRange & 131068 /* NEXT_MASK */) >> 2 /* NEXT_SHIFT */;
8507}
8508function setTStylingRangeNext(tStylingRange, next) {
8509 ngDevMode && assertNumber(tStylingRange, 'expected number');
8510 ngDevMode && assertNumberInRange(next, 0, 32767 /* UNSIGNED_MASK */);
8511 return ((tStylingRange & ~131068 /* NEXT_MASK */) | //
8512 next << 2 /* NEXT_SHIFT */);
8513}
8514function getTStylingRangeNextDuplicate(tStylingRange) {
8515 ngDevMode && assertNumber(tStylingRange, 'expected number');
8516 return (tStylingRange & 1 /* NEXT_DUPLICATE */) ===
8517 1 /* NEXT_DUPLICATE */;
8518}
8519function setTStylingRangeNextDuplicate(tStylingRange) {
8520 ngDevMode && assertNumber(tStylingRange, 'expected number');
8521 return (tStylingRange | 1 /* NEXT_DUPLICATE */);
8522}
8523function getTStylingRangeTail(tStylingRange) {
8524 ngDevMode && assertNumber(tStylingRange, 'expected number');
8525 const next = getTStylingRangeNext(tStylingRange);
8526 return next === 0 ? getTStylingRangePrev(tStylingRange) : next;
8527}
8528
8529/**
8530 * @license
8531 * Copyright Google LLC All Rights Reserved.
8532 *
8533 * Use of this source code is governed by an MIT-style license that can be
8534 * found in the LICENSE file at https://angular.io/license
8535 */
8536/**
8537 * Patch a `debug` property on top of the existing object.
8538 *
8539 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`
8540 *
8541 * @param obj Object to patch
8542 * @param debug Value to patch
8543 */
8544function attachDebugObject(obj, debug) {
8545 if (ngDevMode) {
8546 Object.defineProperty(obj, 'debug', { value: debug, enumerable: false });
8547 }
8548 else {
8549 throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');
8550 }
8551}
8552/**
8553 * Patch a `debug` property getter on top of the existing object.
8554 *
8555 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`
8556 *
8557 * @param obj Object to patch
8558 * @param debugGetter Getter returning a value to patch
8559 */
8560function attachDebugGetter(obj, debugGetter) {
8561 if (ngDevMode) {
8562 Object.defineProperty(obj, 'debug', { get: debugGetter, enumerable: false });
8563 }
8564 else {
8565 throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');
8566 }
8567}
8568
8569/**
8570 * @license
8571 * Copyright Google LLC All Rights Reserved.
8572 *
8573 * Use of this source code is governed by an MIT-style license that can be
8574 * found in the LICENSE file at https://angular.io/license
8575 */
8576/*
8577 * This file contains conditionally attached classes which provide human readable (debug) level
8578 * information for `LView`, `LContainer` and other internal data structures. These data structures
8579 * are stored internally as array which makes it very difficult during debugging to reason about the
8580 * current state of the system.
8581 *
8582 * Patching the array with extra property does change the array's hidden class' but it does not
8583 * change the cost of access, therefore this patching should not have significant if any impact in
8584 * `ngDevMode` mode. (see: https://jsperf.com/array-vs-monkey-patch-array)
8585 *
8586 * So instead of seeing:
8587 * ```
8588 * Array(30) [Object, 659, null, …]
8589 * ```
8590 *
8591 * You get to see:
8592 * ```
8593 * LViewDebug {
8594 * views: [...],
8595 * flags: {attached: true, ...}
8596 * nodes: [
8597 * {html: '<div id="123">', ..., nodes: [
8598 * {html: '<span>', ..., nodes: null}
8599 * ]}
8600 * ]
8601 * }
8602 * ```
8603 */
8604let LVIEW_COMPONENT_CACHE;
8605let LVIEW_EMBEDDED_CACHE;
8606let LVIEW_ROOT;
8607let LVIEW_COMPONENT;
8608let LVIEW_EMBEDDED;
8609/**
8610 * This function clones a blueprint and creates LView.
8611 *
8612 * Simple slice will keep the same type, and we need it to be LView
8613 */
8614function cloneToLViewFromTViewBlueprint(tView) {
8615 const debugTView = tView;
8616 const lView = getLViewToClone(debugTView.type, tView.template && tView.template.name);
8617 return lView.concat(tView.blueprint);
8618}
8619class LRootView extends Array {
8620}
8621class LComponentView extends Array {
8622}
8623class LEmbeddedView extends Array {
8624}
8625function getLViewToClone(type, name) {
8626 switch (type) {
8627 case 0 /* Root */:
8628 if (LVIEW_ROOT === undefined)
8629 LVIEW_ROOT = new LRootView();
8630 return LVIEW_ROOT;
8631 case 1 /* Component */:
8632 if (!ngDevMode || !ngDevMode.namedConstructors) {
8633 if (LVIEW_COMPONENT === undefined)
8634 LVIEW_COMPONENT = new LComponentView();
8635 return LVIEW_COMPONENT;
8636 }
8637 if (LVIEW_COMPONENT_CACHE === undefined)
8638 LVIEW_COMPONENT_CACHE = new Map();
8639 let componentArray = LVIEW_COMPONENT_CACHE.get(name);
8640 if (componentArray === undefined) {
8641 componentArray = new (createNamedArrayType('LComponentView' + nameSuffix(name)))();
8642 LVIEW_COMPONENT_CACHE.set(name, componentArray);
8643 }
8644 return componentArray;
8645 case 2 /* Embedded */:
8646 if (!ngDevMode || !ngDevMode.namedConstructors) {
8647 if (LVIEW_EMBEDDED === undefined)
8648 LVIEW_EMBEDDED = new LEmbeddedView();
8649 return LVIEW_EMBEDDED;
8650 }
8651 if (LVIEW_EMBEDDED_CACHE === undefined)
8652 LVIEW_EMBEDDED_CACHE = new Map();
8653 let embeddedArray = LVIEW_EMBEDDED_CACHE.get(name);
8654 if (embeddedArray === undefined) {
8655 embeddedArray = new (createNamedArrayType('LEmbeddedView' + nameSuffix(name)))();
8656 LVIEW_EMBEDDED_CACHE.set(name, embeddedArray);
8657 }
8658 return embeddedArray;
8659 }
8660}
8661function nameSuffix(text) {
8662 if (text == null)
8663 return '';
8664 const index = text.lastIndexOf('_Template');
8665 return '_' + (index === -1 ? text : text.substr(0, index));
8666}
8667/**
8668 * This class is a debug version of Object literal so that we can have constructor name show up
8669 * in
8670 * debug tools in ngDevMode.
8671 */
8672const TViewConstructor = class TView {
8673 constructor(type, blueprint, template, queries, viewQuery, declTNode, data, bindingStartIndex, expandoStartIndex, hostBindingOpCodes, firstCreatePass, firstUpdatePass, staticViewQueries, staticContentQueries, preOrderHooks, preOrderCheckHooks, contentHooks, contentCheckHooks, viewHooks, viewCheckHooks, destroyHooks, cleanup, contentQueries, components, directiveRegistry, pipeRegistry, firstChild, schemas, consts, incompleteFirstPass, _decls, _vars) {
8674 this.type = type;
8675 this.blueprint = blueprint;
8676 this.template = template;
8677 this.queries = queries;
8678 this.viewQuery = viewQuery;
8679 this.declTNode = declTNode;
8680 this.data = data;
8681 this.bindingStartIndex = bindingStartIndex;
8682 this.expandoStartIndex = expandoStartIndex;
8683 this.hostBindingOpCodes = hostBindingOpCodes;
8684 this.firstCreatePass = firstCreatePass;
8685 this.firstUpdatePass = firstUpdatePass;
8686 this.staticViewQueries = staticViewQueries;
8687 this.staticContentQueries = staticContentQueries;
8688 this.preOrderHooks = preOrderHooks;
8689 this.preOrderCheckHooks = preOrderCheckHooks;
8690 this.contentHooks = contentHooks;
8691 this.contentCheckHooks = contentCheckHooks;
8692 this.viewHooks = viewHooks;
8693 this.viewCheckHooks = viewCheckHooks;
8694 this.destroyHooks = destroyHooks;
8695 this.cleanup = cleanup;
8696 this.contentQueries = contentQueries;
8697 this.components = components;
8698 this.directiveRegistry = directiveRegistry;
8699 this.pipeRegistry = pipeRegistry;
8700 this.firstChild = firstChild;
8701 this.schemas = schemas;
8702 this.consts = consts;
8703 this.incompleteFirstPass = incompleteFirstPass;
8704 this._decls = _decls;
8705 this._vars = _vars;
8706 }
8707 get template_() {
8708 const buf = [];
8709 processTNodeChildren(this.firstChild, buf);
8710 return buf.join('');
8711 }
8712 get type_() {
8713 return TViewTypeAsString[this.type] || `TViewType.?${this.type}?`;
8714 }
8715};
8716class TNode {
8717 constructor(tView_, //
8718 type, //
8719 index, //
8720 insertBeforeIndex, //
8721 injectorIndex, //
8722 directiveStart, //
8723 directiveEnd, //
8724 directiveStylingLast, //
8725 propertyBindings, //
8726 flags, //
8727 providerIndexes, //
8728 value, //
8729 attrs, //
8730 mergedAttrs, //
8731 localNames, //
8732 initialInputs, //
8733 inputs, //
8734 outputs, //
8735 tViews, //
8736 next, //
8737 projectionNext, //
8738 child, //
8739 parent, //
8740 projection, //
8741 styles, //
8742 stylesWithoutHost, //
8743 residualStyles, //
8744 classes, //
8745 classesWithoutHost, //
8746 residualClasses, //
8747 classBindings, //
8748 styleBindings) {
8749 this.tView_ = tView_;
8750 this.type = type;
8751 this.index = index;
8752 this.insertBeforeIndex = insertBeforeIndex;
8753 this.injectorIndex = injectorIndex;
8754 this.directiveStart = directiveStart;
8755 this.directiveEnd = directiveEnd;
8756 this.directiveStylingLast = directiveStylingLast;
8757 this.propertyBindings = propertyBindings;
8758 this.flags = flags;
8759 this.providerIndexes = providerIndexes;
8760 this.value = value;
8761 this.attrs = attrs;
8762 this.mergedAttrs = mergedAttrs;
8763 this.localNames = localNames;
8764 this.initialInputs = initialInputs;
8765 this.inputs = inputs;
8766 this.outputs = outputs;
8767 this.tViews = tViews;
8768 this.next = next;
8769 this.projectionNext = projectionNext;
8770 this.child = child;
8771 this.parent = parent;
8772 this.projection = projection;
8773 this.styles = styles;
8774 this.stylesWithoutHost = stylesWithoutHost;
8775 this.residualStyles = residualStyles;
8776 this.classes = classes;
8777 this.classesWithoutHost = classesWithoutHost;
8778 this.residualClasses = residualClasses;
8779 this.classBindings = classBindings;
8780 this.styleBindings = styleBindings;
8781 }
8782 /**
8783 * Return a human debug version of the set of `NodeInjector`s which will be consulted when
8784 * resolving tokens from this `TNode`.
8785 *
8786 * When debugging applications, it is often difficult to determine which `NodeInjector`s will be
8787 * consulted. This method shows a list of `DebugNode`s representing the `TNode`s which will be
8788 * consulted in order when resolving a token starting at this `TNode`.
8789 *
8790 * The original data is stored in `LView` and `TView` with a lot of offset indexes, and so it is
8791 * difficult to reason about.
8792 *
8793 * @param lView The `LView` instance for this `TNode`.
8794 */
8795 debugNodeInjectorPath(lView) {
8796 const path = [];
8797 let injectorIndex = getInjectorIndex(this, lView);
8798 if (injectorIndex === -1) {
8799 // Looks like the current `TNode` does not have `NodeInjector` associated with it => look for
8800 // parent NodeInjector.
8801 const parentLocation = getParentInjectorLocation(this, lView);
8802 if (parentLocation !== NO_PARENT_INJECTOR) {
8803 // We found a parent, so start searching from the parent location.
8804 injectorIndex = getParentInjectorIndex(parentLocation);
8805 lView = getParentInjectorView(parentLocation, lView);
8806 }
8807 else {
8808 // No parents have been found, so there are no `NodeInjector`s to consult.
8809 }
8810 }
8811 while (injectorIndex !== -1) {
8812 ngDevMode && assertNodeInjector(lView, injectorIndex);
8813 const tNode = lView[TVIEW].data[injectorIndex + 8 /* TNODE */];
8814 path.push(buildDebugNode(tNode, lView));
8815 const parentLocation = lView[injectorIndex + 8 /* PARENT */];
8816 if (parentLocation === NO_PARENT_INJECTOR) {
8817 injectorIndex = -1;
8818 }
8819 else {
8820 injectorIndex = getParentInjectorIndex(parentLocation);
8821 lView = getParentInjectorView(parentLocation, lView);
8822 }
8823 }
8824 return path;
8825 }
8826 get type_() {
8827 return toTNodeTypeAsString(this.type) || `TNodeType.?${this.type}?`;
8828 }
8829 get flags_() {
8830 const flags = [];
8831 if (this.flags & 16 /* hasClassInput */)
8832 flags.push('TNodeFlags.hasClassInput');
8833 if (this.flags & 8 /* hasContentQuery */)
8834 flags.push('TNodeFlags.hasContentQuery');
8835 if (this.flags & 32 /* hasStyleInput */)
8836 flags.push('TNodeFlags.hasStyleInput');
8837 if (this.flags & 128 /* hasHostBindings */)
8838 flags.push('TNodeFlags.hasHostBindings');
8839 if (this.flags & 2 /* isComponentHost */)
8840 flags.push('TNodeFlags.isComponentHost');
8841 if (this.flags & 1 /* isDirectiveHost */)
8842 flags.push('TNodeFlags.isDirectiveHost');
8843 if (this.flags & 64 /* isDetached */)
8844 flags.push('TNodeFlags.isDetached');
8845 if (this.flags & 4 /* isProjected */)
8846 flags.push('TNodeFlags.isProjected');
8847 return flags.join('|');
8848 }
8849 get template_() {
8850 if (this.type & 1 /* Text */)
8851 return this.value;
8852 const buf = [];
8853 const tagName = typeof this.value === 'string' && this.value || this.type_;
8854 buf.push('<', tagName);
8855 if (this.flags) {
8856 buf.push(' ', this.flags_);
8857 }
8858 if (this.attrs) {
8859 for (let i = 0; i < this.attrs.length;) {
8860 const attrName = this.attrs[i++];
8861 if (typeof attrName == 'number') {
8862 break;
8863 }
8864 const attrValue = this.attrs[i++];
8865 buf.push(' ', attrName, '="', attrValue, '"');
8866 }
8867 }
8868 buf.push('>');
8869 processTNodeChildren(this.child, buf);
8870 buf.push('</', tagName, '>');
8871 return buf.join('');
8872 }
8873 get styleBindings_() {
8874 return toDebugStyleBinding(this, false);
8875 }
8876 get classBindings_() {
8877 return toDebugStyleBinding(this, true);
8878 }
8879 get providerIndexStart_() {
8880 return this.providerIndexes & 1048575 /* ProvidersStartIndexMask */;
8881 }
8882 get providerIndexEnd_() {
8883 return this.providerIndexStart_ +
8884 (this.providerIndexes >>> 20 /* CptViewProvidersCountShift */);
8885 }
8886}
8887const TNodeDebug = TNode;
8888function toDebugStyleBinding(tNode, isClassBased) {
8889 const tData = tNode.tView_.data;
8890 const bindings = [];
8891 const range = isClassBased ? tNode.classBindings : tNode.styleBindings;
8892 const prev = getTStylingRangePrev(range);
8893 const next = getTStylingRangeNext(range);
8894 let isTemplate = next !== 0;
8895 let cursor = isTemplate ? next : prev;
8896 while (cursor !== 0) {
8897 const itemKey = tData[cursor];
8898 const itemRange = tData[cursor + 1];
8899 bindings.unshift({
8900 key: itemKey,
8901 index: cursor,
8902 isTemplate: isTemplate,
8903 prevDuplicate: getTStylingRangePrevDuplicate(itemRange),
8904 nextDuplicate: getTStylingRangeNextDuplicate(itemRange),
8905 nextIndex: getTStylingRangeNext(itemRange),
8906 prevIndex: getTStylingRangePrev(itemRange),
8907 });
8908 if (cursor === prev)
8909 isTemplate = false;
8910 cursor = getTStylingRangePrev(itemRange);
8911 }
8912 bindings.push((isClassBased ? tNode.residualClasses : tNode.residualStyles) || null);
8913 return bindings;
8914}
8915function processTNodeChildren(tNode, buf) {
8916 while (tNode) {
8917 buf.push(tNode.template_);
8918 tNode = tNode.next;
8919 }
8920}
8921class TViewData extends Array {
8922}
8923let TVIEWDATA_EMPTY; // can't initialize here or it will not be tree shaken, because
8924// `LView` constructor could have side-effects.
8925/**
8926 * This function clones a blueprint and creates TData.
8927 *
8928 * Simple slice will keep the same type, and we need it to be TData
8929 */
8930function cloneToTViewData(list) {
8931 if (TVIEWDATA_EMPTY === undefined)
8932 TVIEWDATA_EMPTY = new TViewData();
8933 return TVIEWDATA_EMPTY.concat(list);
8934}
8935class LViewBlueprint extends Array {
8936}
8937class MatchesArray extends Array {
8938}
8939class TViewComponents extends Array {
8940}
8941class TNodeLocalNames extends Array {
8942}
8943class TNodeInitialInputs extends Array {
8944}
8945class LCleanup extends Array {
8946}
8947class TCleanup extends Array {
8948}
8949function attachLViewDebug(lView) {
8950 attachDebugObject(lView, new LViewDebug(lView));
8951}
8952function attachLContainerDebug(lContainer) {
8953 attachDebugObject(lContainer, new LContainerDebug(lContainer));
8954}
8955function toDebug(obj) {
8956 if (obj) {
8957 const debug = obj.debug;
8958 assertDefined(debug, 'Object does not have a debug representation.');
8959 return debug;
8960 }
8961 else {
8962 return obj;
8963 }
8964}
8965/**
8966 * Use this method to unwrap a native element in `LView` and convert it into HTML for easier
8967 * reading.
8968 *
8969 * @param value possibly wrapped native DOM node.
8970 * @param includeChildren If `true` then the serialized HTML form will include child elements
8971 * (same
8972 * as `outerHTML`). If `false` then the serialized HTML form will only contain the element
8973 * itself
8974 * (will not serialize child elements).
8975 */
8976function toHtml(value, includeChildren = false) {
8977 const node = unwrapRNode(value);
8978 if (node) {
8979 switch (node.nodeType) {
8980 case Node.TEXT_NODE:
8981 return node.textContent;
8982 case Node.COMMENT_NODE:
8983 return `<!--${node.textContent}-->`;
8984 case Node.ELEMENT_NODE:
8985 const outerHTML = node.outerHTML;
8986 if (includeChildren) {
8987 return outerHTML;
8988 }
8989 else {
8990 const innerHTML = '>' + node.innerHTML + '<';
8991 return (outerHTML.split(innerHTML)[0]) + '>';
8992 }
8993 }
8994 }
8995 return null;
8996}
8997class LViewDebug {
8998 constructor(_raw_lView) {
8999 this._raw_lView = _raw_lView;
9000 }
9001 /**
9002 * Flags associated with the `LView` unpacked into a more readable state.
9003 */
9004 get flags() {
9005 const flags = this._raw_lView[FLAGS];
9006 return {
9007 __raw__flags__: flags,
9008 initPhaseState: flags & 3 /* InitPhaseStateMask */,
9009 creationMode: !!(flags & 4 /* CreationMode */),
9010 firstViewPass: !!(flags & 8 /* FirstLViewPass */),
9011 checkAlways: !!(flags & 16 /* CheckAlways */),
9012 dirty: !!(flags & 64 /* Dirty */),
9013 attached: !!(flags & 128 /* Attached */),
9014 destroyed: !!(flags & 256 /* Destroyed */),
9015 isRoot: !!(flags & 512 /* IsRoot */),
9016 indexWithinInitPhase: flags >> 11 /* IndexWithinInitPhaseShift */,
9017 };
9018 }
9019 get parent() {
9020 return toDebug(this._raw_lView[PARENT]);
9021 }
9022 get hostHTML() {
9023 return toHtml(this._raw_lView[HOST], true);
9024 }
9025 get html() {
9026 return (this.nodes || []).map(mapToHTML).join('');
9027 }
9028 get context() {
9029 return this._raw_lView[CONTEXT];
9030 }
9031 /**
9032 * The tree of nodes associated with the current `LView`. The nodes have been normalized into
9033 * a tree structure with relevant details pulled out for readability.
9034 */
9035 get nodes() {
9036 const lView = this._raw_lView;
9037 const tNode = lView[TVIEW].firstChild;
9038 return toDebugNodes(tNode, lView);
9039 }
9040 get template() {
9041 return this.tView.template_;
9042 }
9043 get tView() {
9044 return this._raw_lView[TVIEW];
9045 }
9046 get cleanup() {
9047 return this._raw_lView[CLEANUP];
9048 }
9049 get injector() {
9050 return this._raw_lView[INJECTOR$1];
9051 }
9052 get rendererFactory() {
9053 return this._raw_lView[RENDERER_FACTORY];
9054 }
9055 get renderer() {
9056 return this._raw_lView[RENDERER];
9057 }
9058 get sanitizer() {
9059 return this._raw_lView[SANITIZER];
9060 }
9061 get childHead() {
9062 return toDebug(this._raw_lView[CHILD_HEAD]);
9063 }
9064 get next() {
9065 return toDebug(this._raw_lView[NEXT]);
9066 }
9067 get childTail() {
9068 return toDebug(this._raw_lView[CHILD_TAIL]);
9069 }
9070 get declarationView() {
9071 return toDebug(this._raw_lView[DECLARATION_VIEW]);
9072 }
9073 get queries() {
9074 return this._raw_lView[QUERIES];
9075 }
9076 get tHost() {
9077 return this._raw_lView[T_HOST];
9078 }
9079 get decls() {
9080 return toLViewRange(this.tView, this._raw_lView, HEADER_OFFSET, this.tView.bindingStartIndex);
9081 }
9082 get vars() {
9083 return toLViewRange(this.tView, this._raw_lView, this.tView.bindingStartIndex, this.tView.expandoStartIndex);
9084 }
9085 get expando() {
9086 return toLViewRange(this.tView, this._raw_lView, this.tView.expandoStartIndex, this._raw_lView.length);
9087 }
9088 /**
9089 * Normalized view of child views (and containers) attached at this location.
9090 */
9091 get childViews() {
9092 const childViews = [];
9093 let child = this.childHead;
9094 while (child) {
9095 childViews.push(child);
9096 child = child.next;
9097 }
9098 return childViews;
9099 }
9100}
9101function mapToHTML(node) {
9102 if (node.type === 'ElementContainer') {
9103 return (node.children || []).map(mapToHTML).join('');
9104 }
9105 else if (node.type === 'IcuContainer') {
9106 throw new Error('Not implemented');
9107 }
9108 else {
9109 return toHtml(node.native, true) || '';
9110 }
9111}
9112function toLViewRange(tView, lView, start, end) {
9113 let content = [];
9114 for (let index = start; index < end; index++) {
9115 content.push({ index: index, t: tView.data[index], l: lView[index] });
9116 }
9117 return { start: start, end: end, length: end - start, content: content };
9118}
9119/**
9120 * Turns a flat list of nodes into a tree by walking the associated `TNode` tree.
9121 *
9122 * @param tNode
9123 * @param lView
9124 */
9125function toDebugNodes(tNode, lView) {
9126 if (tNode) {
9127 const debugNodes = [];
9128 let tNodeCursor = tNode;
9129 while (tNodeCursor) {
9130 debugNodes.push(buildDebugNode(tNodeCursor, lView));
9131 tNodeCursor = tNodeCursor.next;
9132 }
9133 return debugNodes;
9134 }
9135 else {
9136 return [];
9137 }
9138}
9139function buildDebugNode(tNode, lView) {
9140 const rawValue = lView[tNode.index];
9141 const native = unwrapRNode(rawValue);
9142 const factories = [];
9143 const instances = [];
9144 const tView = lView[TVIEW];
9145 for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) {
9146 const def = tView.data[i];
9147 factories.push(def.type);
9148 instances.push(lView[i]);
9149 }
9150 return {
9151 html: toHtml(native),
9152 type: toTNodeTypeAsString(tNode.type),
9153 tNode,
9154 native: native,
9155 children: toDebugNodes(tNode.child, lView),
9156 factories,
9157 instances,
9158 injector: buildNodeInjectorDebug(tNode, tView, lView),
9159 get injectorResolutionPath() {
9160 return tNode.debugNodeInjectorPath(lView);
9161 },
9162 };
9163}
9164function buildNodeInjectorDebug(tNode, tView, lView) {
9165 const viewProviders = [];
9166 for (let i = tNode.providerIndexStart_; i < tNode.providerIndexEnd_; i++) {
9167 viewProviders.push(tView.data[i]);
9168 }
9169 const providers = [];
9170 for (let i = tNode.providerIndexEnd_; i < tNode.directiveEnd; i++) {
9171 providers.push(tView.data[i]);
9172 }
9173 const nodeInjectorDebug = {
9174 bloom: toBloom(lView, tNode.injectorIndex),
9175 cumulativeBloom: toBloom(tView.data, tNode.injectorIndex),
9176 providers,
9177 viewProviders,
9178 parentInjectorIndex: lView[tNode.providerIndexStart_ - 1],
9179 };
9180 return nodeInjectorDebug;
9181}
9182/**
9183 * Convert a number at `idx` location in `array` into binary representation.
9184 *
9185 * @param array
9186 * @param idx
9187 */
9188function binary(array, idx) {
9189 const value = array[idx];
9190 // If not a number we print 8 `?` to retain alignment but let user know that it was called on
9191 // wrong type.
9192 if (typeof value !== 'number')
9193 return '????????';
9194 // We prefix 0s so that we have constant length number
9195 const text = '00000000' + value.toString(2);
9196 return text.substring(text.length - 8);
9197}
9198/**
9199 * Convert a bloom filter at location `idx` in `array` into binary representation.
9200 *
9201 * @param array
9202 * @param idx
9203 */
9204function toBloom(array, idx) {
9205 if (idx < 0) {
9206 return 'NO_NODE_INJECTOR';
9207 }
9208 return `${binary(array, idx + 7)}_${binary(array, idx + 6)}_${binary(array, idx + 5)}_${binary(array, idx + 4)}_${binary(array, idx + 3)}_${binary(array, idx + 2)}_${binary(array, idx + 1)}_${binary(array, idx + 0)}`;
9209}
9210class LContainerDebug {
9211 constructor(_raw_lContainer) {
9212 this._raw_lContainer = _raw_lContainer;
9213 }
9214 get hasTransplantedViews() {
9215 return this._raw_lContainer[HAS_TRANSPLANTED_VIEWS];
9216 }
9217 get views() {
9218 return this._raw_lContainer.slice(CONTAINER_HEADER_OFFSET)
9219 .map(toDebug);
9220 }
9221 get parent() {
9222 return toDebug(this._raw_lContainer[PARENT]);
9223 }
9224 get movedViews() {
9225 return this._raw_lContainer[MOVED_VIEWS];
9226 }
9227 get host() {
9228 return this._raw_lContainer[HOST];
9229 }
9230 get native() {
9231 return this._raw_lContainer[NATIVE];
9232 }
9233 get next() {
9234 return toDebug(this._raw_lContainer[NEXT]);
9235 }
9236}
9237
9238/**
9239 * A permanent marker promise which signifies that the current CD tree is
9240 * clean.
9241 */
9242const _CLEAN_PROMISE = (() => Promise.resolve(null))();
9243/**
9244 * Invoke `HostBindingsFunction`s for view.
9245 *
9246 * This methods executes `TView.hostBindingOpCodes`. It is used to execute the
9247 * `HostBindingsFunction`s associated with the current `LView`.
9248 *
9249 * @param tView Current `TView`.
9250 * @param lView Current `LView`.
9251 */
9252function processHostBindingOpCodes(tView, lView) {
9253 const hostBindingOpCodes = tView.hostBindingOpCodes;
9254 if (hostBindingOpCodes === null)
9255 return;
9256 try {
9257 for (let i = 0; i < hostBindingOpCodes.length; i++) {
9258 const opCode = hostBindingOpCodes[i];
9259 if (opCode < 0) {
9260 // Negative numbers are element indexes.
9261 setSelectedIndex(~opCode);
9262 }
9263 else {
9264 // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex.
9265 const directiveIdx = opCode;
9266 const bindingRootIndx = hostBindingOpCodes[++i];
9267 const hostBindingFn = hostBindingOpCodes[++i];
9268 setBindingRootForHostBindings(bindingRootIndx, directiveIdx);
9269 const context = lView[directiveIdx];
9270 hostBindingFn(2 /* Update */, context);
9271 }
9272 }
9273 }
9274 finally {
9275 setSelectedIndex(-1);
9276 }
9277}
9278/** Refreshes all content queries declared by directives in a given view */
9279function refreshContentQueries(tView, lView) {
9280 const contentQueries = tView.contentQueries;
9281 if (contentQueries !== null) {
9282 for (let i = 0; i < contentQueries.length; i += 2) {
9283 const queryStartIdx = contentQueries[i];
9284 const directiveDefIdx = contentQueries[i + 1];
9285 if (directiveDefIdx !== -1) {
9286 const directiveDef = tView.data[directiveDefIdx];
9287 ngDevMode && assertDefined(directiveDef, 'DirectiveDef not found.');
9288 ngDevMode &&
9289 assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined');
9290 setCurrentQueryIndex(queryStartIdx);
9291 directiveDef.contentQueries(2 /* Update */, lView[directiveDefIdx], directiveDefIdx);
9292 }
9293 }
9294 }
9295}
9296/** Refreshes child components in the current view (update mode). */
9297function refreshChildComponents(hostLView, components) {
9298 for (let i = 0; i < components.length; i++) {
9299 refreshComponent(hostLView, components[i]);
9300 }
9301}
9302/** Renders child components in the current view (creation mode). */
9303function renderChildComponents(hostLView, components) {
9304 for (let i = 0; i < components.length; i++) {
9305 renderComponent$1(hostLView, components[i]);
9306 }
9307}
9308function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector) {
9309 const lView = ngDevMode ? cloneToLViewFromTViewBlueprint(tView) : tView.blueprint.slice();
9310 lView[HOST] = host;
9311 lView[FLAGS] = flags | 4 /* CreationMode */ | 128 /* Attached */ | 8 /* FirstLViewPass */;
9312 resetPreOrderHookFlags(lView);
9313 ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView);
9314 lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;
9315 lView[CONTEXT] = context;
9316 lView[RENDERER_FACTORY] = (rendererFactory || parentLView && parentLView[RENDERER_FACTORY]);
9317 ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required');
9318 lView[RENDERER] = (renderer || parentLView && parentLView[RENDERER]);
9319 ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
9320 lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null;
9321 lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
9322 lView[T_HOST] = tHostNode;
9323 ngDevMode &&
9324 assertEqual(tView.type == 2 /* Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
9325 lView[DECLARATION_COMPONENT_VIEW] =
9326 tView.type == 2 /* Embedded */ ? parentLView[DECLARATION_COMPONENT_VIEW] : lView;
9327 ngDevMode && attachLViewDebug(lView);
9328 return lView;
9329}
9330function getOrCreateTNode(tView, index, type, name, attrs) {
9331 ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in
9332 // `view_engine_compatibility` for additional context.
9333 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.');
9334 // Keep this function short, so that the VM will inline it.
9335 ngDevMode && assertPureTNodeType(type);
9336 let tNode = tView.data[index];
9337 if (tNode === null) {
9338 tNode = createTNodeAtIndex(tView, index, type, name, attrs);
9339 if (isInI18nBlock()) {
9340 // If we are in i18n block then all elements should be pre declared through `Placeholder`
9341 // See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
9342 // If the `TNode` was not pre-declared than it means it was not mentioned which means it was
9343 // removed, so we mark it as detached.
9344 tNode.flags |= 64 /* isDetached */;
9345 }
9346 }
9347 else if (tNode.type & 64 /* Placeholder */) {
9348 tNode.type = type;
9349 tNode.value = name;
9350 tNode.attrs = attrs;
9351 const parent = getCurrentParentTNode();
9352 tNode.injectorIndex = parent === null ? -1 : parent.injectorIndex;
9353 ngDevMode && assertTNodeForTView(tNode, tView);
9354 ngDevMode && assertEqual(index, tNode.index, 'Expecting same index');
9355 }
9356 setCurrentTNode(tNode, true);
9357 return tNode;
9358}
9359function createTNodeAtIndex(tView, index, type, name, attrs) {
9360 const currentTNode = getCurrentTNodePlaceholderOk();
9361 const isParent = isCurrentTNodeParent();
9362 const parent = isParent ? currentTNode : currentTNode && currentTNode.parent;
9363 // Parents cannot cross component boundaries because components will be used in multiple places.
9364 const tNode = tView.data[index] =
9365 createTNode(tView, parent, type, index, name, attrs);
9366 // Assign a pointer to the first child node of a given view. The first node is not always the one
9367 // at index 0, in case of i18n, index 0 can be the instruction `i18nStart` and the first node has
9368 // the index 1 or more, so we can't just check node index.
9369 if (tView.firstChild === null) {
9370 tView.firstChild = tNode;
9371 }
9372 if (currentTNode !== null) {
9373 if (isParent) {
9374 // FIXME(misko): This logic looks unnecessarily complicated. Could we simplify?
9375 if (currentTNode.child == null && tNode.parent !== null) {
9376 // We are in the same view, which means we are adding content node to the parent view.
9377 currentTNode.child = tNode;
9378 }
9379 }
9380 else {
9381 if (currentTNode.next === null) {
9382 // In the case of i18n the `currentTNode` may already be linked, in which case we don't want
9383 // to break the links which i18n created.
9384 currentTNode.next = tNode;
9385 }
9386 }
9387 }
9388 return tNode;
9389}
9390/**
9391 * When elements are created dynamically after a view blueprint is created (e.g. through
9392 * i18nApply()), we need to adjust the blueprint for future
9393 * template passes.
9394 *
9395 * @param tView `TView` associated with `LView`
9396 * @param lView The `LView` containing the blueprint to adjust
9397 * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0
9398 * @param initialValue Initial value to store in blueprint
9399 */
9400function allocExpando(tView, lView, numSlotsToAlloc, initialValue) {
9401 if (numSlotsToAlloc === 0)
9402 return -1;
9403 if (ngDevMode) {
9404 assertFirstCreatePass(tView);
9405 assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!');
9406 assertEqual(tView.data.length, lView.length, 'Expecting LView to be same size as TView');
9407 assertEqual(tView.data.length, tView.blueprint.length, 'Expecting Blueprint to be same size as TView');
9408 assertFirstUpdatePass(tView);
9409 }
9410 const allocIdx = lView.length;
9411 for (let i = 0; i < numSlotsToAlloc; i++) {
9412 lView.push(initialValue);
9413 tView.blueprint.push(initialValue);
9414 tView.data.push(null);
9415 }
9416 return allocIdx;
9417}
9418//////////////////////////
9419//// Render
9420//////////////////////////
9421/**
9422 * Processes a view in the creation mode. This includes a number of steps in a specific order:
9423 * - creating view query functions (if any);
9424 * - executing a template function in the creation mode;
9425 * - updating static queries (if any);
9426 * - creating child components defined in a given view.
9427 */
9428function renderView(tView, lView, context) {
9429 ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
9430 enterView(lView);
9431 try {
9432 const viewQuery = tView.viewQuery;
9433 if (viewQuery !== null) {
9434 executeViewQueryFn(1 /* Create */, viewQuery, context);
9435 }
9436 // Execute a template associated with this view, if it exists. A template function might not be
9437 // defined for the root component views.
9438 const templateFn = tView.template;
9439 if (templateFn !== null) {
9440 executeTemplate(tView, lView, templateFn, 1 /* Create */, context);
9441 }
9442 // This needs to be set before children are processed to support recursive components.
9443 // This must be set to false immediately after the first creation run because in an
9444 // ngFor loop, all the views will be created together before update mode runs and turns
9445 // off firstCreatePass. If we don't set it here, instances will perform directive
9446 // matching, etc again and again.
9447 if (tView.firstCreatePass) {
9448 tView.firstCreatePass = false;
9449 }
9450 // We resolve content queries specifically marked as `static` in creation mode. Dynamic
9451 // content queries are resolved during change detection (i.e. update mode), after embedded
9452 // views are refreshed (see block above).
9453 if (tView.staticContentQueries) {
9454 refreshContentQueries(tView, lView);
9455 }
9456 // We must materialize query results before child components are processed
9457 // in case a child component has projected a container. The LContainer needs
9458 // to exist so the embedded views are properly attached by the container.
9459 if (tView.staticViewQueries) {
9460 executeViewQueryFn(2 /* Update */, tView.viewQuery, context);
9461 }
9462 // Render child component views.
9463 const components = tView.components;
9464 if (components !== null) {
9465 renderChildComponents(lView, components);
9466 }
9467 }
9468 catch (error) {
9469 // If we didn't manage to get past the first template pass due to
9470 // an error, mark the view as corrupted so we can try to recover.
9471 if (tView.firstCreatePass) {
9472 tView.incompleteFirstPass = true;
9473 tView.firstCreatePass = false;
9474 }
9475 throw error;
9476 }
9477 finally {
9478 lView[FLAGS] &= ~4 /* CreationMode */;
9479 leaveView();
9480 }
9481}
9482/**
9483 * Processes a view in update mode. This includes a number of steps in a specific order:
9484 * - executing a template function in update mode;
9485 * - executing hooks;
9486 * - refreshing queries;
9487 * - setting host bindings;
9488 * - refreshing child (embedded and component) views.
9489 */
9490function refreshView(tView, lView, templateFn, context) {
9491 ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
9492 const flags = lView[FLAGS];
9493 if ((flags & 256 /* Destroyed */) === 256 /* Destroyed */)
9494 return;
9495 enterView(lView);
9496 // Check no changes mode is a dev only mode used to verify that bindings have not changed
9497 // since they were assigned. We do not want to execute lifecycle hooks in that mode.
9498 const isInCheckNoChangesPass = isInCheckNoChangesMode();
9499 try {
9500 resetPreOrderHookFlags(lView);
9501 setBindingIndex(tView.bindingStartIndex);
9502 if (templateFn !== null) {
9503 executeTemplate(tView, lView, templateFn, 2 /* Update */, context);
9504 }
9505 const hooksInitPhaseCompleted = (flags & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;
9506 // execute pre-order hooks (OnInit, OnChanges, DoCheck)
9507 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
9508 if (!isInCheckNoChangesPass) {
9509 if (hooksInitPhaseCompleted) {
9510 const preOrderCheckHooks = tView.preOrderCheckHooks;
9511 if (preOrderCheckHooks !== null) {
9512 executeCheckHooks(lView, preOrderCheckHooks, null);
9513 }
9514 }
9515 else {
9516 const preOrderHooks = tView.preOrderHooks;
9517 if (preOrderHooks !== null) {
9518 executeInitAndCheckHooks(lView, preOrderHooks, 0 /* OnInitHooksToBeRun */, null);
9519 }
9520 incrementInitPhaseFlags(lView, 0 /* OnInitHooksToBeRun */);
9521 }
9522 }
9523 // First mark transplanted views that are declared in this lView as needing a refresh at their
9524 // insertion points. This is needed to avoid the situation where the template is defined in this
9525 // `LView` but its declaration appears after the insertion component.
9526 markTransplantedViewsForRefresh(lView);
9527 refreshEmbeddedViews(lView);
9528 // Content query results must be refreshed before content hooks are called.
9529 if (tView.contentQueries !== null) {
9530 refreshContentQueries(tView, lView);
9531 }
9532 // execute content hooks (AfterContentInit, AfterContentChecked)
9533 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
9534 if (!isInCheckNoChangesPass) {
9535 if (hooksInitPhaseCompleted) {
9536 const contentCheckHooks = tView.contentCheckHooks;
9537 if (contentCheckHooks !== null) {
9538 executeCheckHooks(lView, contentCheckHooks);
9539 }
9540 }
9541 else {
9542 const contentHooks = tView.contentHooks;
9543 if (contentHooks !== null) {
9544 executeInitAndCheckHooks(lView, contentHooks, 1 /* AfterContentInitHooksToBeRun */);
9545 }
9546 incrementInitPhaseFlags(lView, 1 /* AfterContentInitHooksToBeRun */);
9547 }
9548 }
9549 processHostBindingOpCodes(tView, lView);
9550 // Refresh child component views.
9551 const components = tView.components;
9552 if (components !== null) {
9553 refreshChildComponents(lView, components);
9554 }
9555 // View queries must execute after refreshing child components because a template in this view
9556 // could be inserted in a child component. If the view query executes before child component
9557 // refresh, the template might not yet be inserted.
9558 const viewQuery = tView.viewQuery;
9559 if (viewQuery !== null) {
9560 executeViewQueryFn(2 /* Update */, viewQuery, context);
9561 }
9562 // execute view hooks (AfterViewInit, AfterViewChecked)
9563 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
9564 if (!isInCheckNoChangesPass) {
9565 if (hooksInitPhaseCompleted) {
9566 const viewCheckHooks = tView.viewCheckHooks;
9567 if (viewCheckHooks !== null) {
9568 executeCheckHooks(lView, viewCheckHooks);
9569 }
9570 }
9571 else {
9572 const viewHooks = tView.viewHooks;
9573 if (viewHooks !== null) {
9574 executeInitAndCheckHooks(lView, viewHooks, 2 /* AfterViewInitHooksToBeRun */);
9575 }
9576 incrementInitPhaseFlags(lView, 2 /* AfterViewInitHooksToBeRun */);
9577 }
9578 }
9579 if (tView.firstUpdatePass === true) {
9580 // We need to make sure that we only flip the flag on successful `refreshView` only
9581 // Don't do this in `finally` block.
9582 // If we did this in `finally` block then an exception could block the execution of styling
9583 // instructions which in turn would be unable to insert themselves into the styling linked
9584 // list. The result of this would be that if the exception would not be throw on subsequent CD
9585 // the styling would be unable to process it data and reflect to the DOM.
9586 tView.firstUpdatePass = false;
9587 }
9588 // Do not reset the dirty state when running in check no changes mode. We don't want components
9589 // to behave differently depending on whether check no changes is enabled or not. For example:
9590 // Marking an OnPush component as dirty from within the `ngAfterViewInit` hook in order to
9591 // refresh a `NgClass` binding should work. If we would reset the dirty state in the check
9592 // no changes cycle, the component would be not be dirty for the next update pass. This would
9593 // be different in production mode where the component dirty state is not reset.
9594 if (!isInCheckNoChangesPass) {
9595 lView[FLAGS] &= ~(64 /* Dirty */ | 8 /* FirstLViewPass */);
9596 }
9597 if (lView[FLAGS] & 1024 /* RefreshTransplantedView */) {
9598 lView[FLAGS] &= ~1024 /* RefreshTransplantedView */;
9599 updateTransplantedViewCount(lView[PARENT], -1);
9600 }
9601 }
9602 finally {
9603 leaveView();
9604 }
9605}
9606function renderComponentOrTemplate(tView, lView, templateFn, context) {
9607 const rendererFactory = lView[RENDERER_FACTORY];
9608 const normalExecutionPath = !isInCheckNoChangesMode();
9609 const creationModeIsActive = isCreationMode(lView);
9610 try {
9611 if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
9612 rendererFactory.begin();
9613 }
9614 if (creationModeIsActive) {
9615 renderView(tView, lView, context);
9616 }
9617 refreshView(tView, lView, templateFn, context);
9618 }
9619 finally {
9620 if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
9621 rendererFactory.end();
9622 }
9623 }
9624}
9625function executeTemplate(tView, lView, templateFn, rf, context) {
9626 const prevSelectedIndex = getSelectedIndex();
9627 const isUpdatePhase = rf & 2 /* Update */;
9628 try {
9629 setSelectedIndex(-1);
9630 if (isUpdatePhase && lView.length > HEADER_OFFSET) {
9631 // When we're updating, inherently select 0 so we don't
9632 // have to generate that instruction for most update blocks.
9633 selectIndexInternal(tView, lView, HEADER_OFFSET, isInCheckNoChangesMode());
9634 }
9635 const preHookType = isUpdatePhase ? 2 /* TemplateUpdateStart */ : 0 /* TemplateCreateStart */;
9636 profiler(preHookType, context);
9637 templateFn(rf, context);
9638 }
9639 finally {
9640 setSelectedIndex(prevSelectedIndex);
9641 const postHookType = isUpdatePhase ? 3 /* TemplateUpdateEnd */ : 1 /* TemplateCreateEnd */;
9642 profiler(postHookType, context);
9643 }
9644}
9645//////////////////////////
9646//// Element
9647//////////////////////////
9648function executeContentQueries(tView, tNode, lView) {
9649 if (isContentQueryHost(tNode)) {
9650 const start = tNode.directiveStart;
9651 const end = tNode.directiveEnd;
9652 for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
9653 const def = tView.data[directiveIndex];
9654 if (def.contentQueries) {
9655 def.contentQueries(1 /* Create */, lView[directiveIndex], directiveIndex);
9656 }
9657 }
9658 }
9659}
9660/**
9661 * Creates directive instances.
9662 */
9663function createDirectivesInstances(tView, lView, tNode) {
9664 if (!getBindingsEnabled())
9665 return;
9666 instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView));
9667 if ((tNode.flags & 128 /* hasHostBindings */) === 128 /* hasHostBindings */) {
9668 invokeDirectivesHostBindings(tView, lView, tNode);
9669 }
9670}
9671/**
9672 * Takes a list of local names and indices and pushes the resolved local variable values
9673 * to LView in the same order as they are loaded in the template with load().
9674 */
9675function saveResolvedLocalsInData(viewData, tNode, localRefExtractor = getNativeByTNode) {
9676 const localNames = tNode.localNames;
9677 if (localNames !== null) {
9678 let localIndex = tNode.index + 1;
9679 for (let i = 0; i < localNames.length; i += 2) {
9680 const index = localNames[i + 1];
9681 const value = index === -1 ?
9682 localRefExtractor(tNode, viewData) :
9683 viewData[index];
9684 viewData[localIndex++] = value;
9685 }
9686 }
9687}
9688/**
9689 * Gets TView from a template function or creates a new TView
9690 * if it doesn't already exist.
9691 *
9692 * @param def ComponentDef
9693 * @returns TView
9694 */
9695function getOrCreateTComponentView(def) {
9696 const tView = def.tView;
9697 // Create a TView if there isn't one, or recreate it if the first create pass didn't
9698 // complete successfully since we can't know for sure whether it's in a usable shape.
9699 if (tView === null || tView.incompleteFirstPass) {
9700 // Declaration node here is null since this function is called when we dynamically create a
9701 // component and hence there is no declaration.
9702 const declTNode = null;
9703 return def.tView = createTView(1 /* Component */, declTNode, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts);
9704 }
9705 return tView;
9706}
9707/**
9708 * Creates a TView instance
9709 *
9710 * @param type Type of `TView`.
9711 * @param declTNode Declaration location of this `TView`.
9712 * @param templateFn Template function
9713 * @param decls The number of nodes, local refs, and pipes in this template
9714 * @param directives Registry of directives for this view
9715 * @param pipes Registry of pipes for this view
9716 * @param viewQuery View queries for this view
9717 * @param schemas Schemas for this view
9718 * @param consts Constants for this view
9719 */
9720function createTView(type, declTNode, templateFn, decls, vars, directives, pipes, viewQuery, schemas, constsOrFactory) {
9721 ngDevMode && ngDevMode.tView++;
9722 const bindingStartIndex = HEADER_OFFSET + decls;
9723 // This length does not yet contain host bindings from child directives because at this point,
9724 // we don't know which directives are active on this template. As soon as a directive is matched
9725 // that has a host binding, we will update the blueprint with that def's hostVars count.
9726 const initialViewLength = bindingStartIndex + vars;
9727 const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
9728 const consts = typeof constsOrFactory === 'function' ? constsOrFactory() : constsOrFactory;
9729 const tView = blueprint[TVIEW] = ngDevMode ?
9730 new TViewConstructor(type, // type: TViewType,
9731 blueprint, // blueprint: LView,
9732 templateFn, // template: ComponentTemplate<{}>|null,
9733 null, // queries: TQueries|null
9734 viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
9735 declTNode, // declTNode: TNode|null,
9736 cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
9737 bindingStartIndex, // bindingStartIndex: number,
9738 initialViewLength, // expandoStartIndex: number,
9739 null, // hostBindingOpCodes: HostBindingOpCodes,
9740 true, // firstCreatePass: boolean,
9741 true, // firstUpdatePass: boolean,
9742 false, // staticViewQueries: boolean,
9743 false, // staticContentQueries: boolean,
9744 null, // preOrderHooks: HookData|null,
9745 null, // preOrderCheckHooks: HookData|null,
9746 null, // contentHooks: HookData|null,
9747 null, // contentCheckHooks: HookData|null,
9748 null, // viewHooks: HookData|null,
9749 null, // viewCheckHooks: HookData|null,
9750 null, // destroyHooks: DestroyHookData|null,
9751 null, // cleanup: any[]|null,
9752 null, // contentQueries: number[]|null,
9753 null, // components: number[]|null,
9754 typeof directives === 'function' ? //
9755 directives() : //
9756 directives, // directiveRegistry: DirectiveDefList|null,
9757 typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null,
9758 null, // firstChild: TNode|null,
9759 schemas, // schemas: SchemaMetadata[]|null,
9760 consts, // consts: TConstants|null
9761 false, // incompleteFirstPass: boolean
9762 decls, // ngDevMode only: decls
9763 vars) :
9764 {
9765 type: type,
9766 blueprint: blueprint,
9767 template: templateFn,
9768 queries: null,
9769 viewQuery: viewQuery,
9770 declTNode: declTNode,
9771 data: blueprint.slice().fill(null, bindingStartIndex),
9772 bindingStartIndex: bindingStartIndex,
9773 expandoStartIndex: initialViewLength,
9774 hostBindingOpCodes: null,
9775 firstCreatePass: true,
9776 firstUpdatePass: true,
9777 staticViewQueries: false,
9778 staticContentQueries: false,
9779 preOrderHooks: null,
9780 preOrderCheckHooks: null,
9781 contentHooks: null,
9782 contentCheckHooks: null,
9783 viewHooks: null,
9784 viewCheckHooks: null,
9785 destroyHooks: null,
9786 cleanup: null,
9787 contentQueries: null,
9788 components: null,
9789 directiveRegistry: typeof directives === 'function' ? directives() : directives,
9790 pipeRegistry: typeof pipes === 'function' ? pipes() : pipes,
9791 firstChild: null,
9792 schemas: schemas,
9793 consts: consts,
9794 incompleteFirstPass: false
9795 };
9796 if (ngDevMode) {
9797 // For performance reasons it is important that the tView retains the same shape during runtime.
9798 // (To make sure that all of the code is monomorphic.) For this reason we seal the object to
9799 // prevent class transitions.
9800 Object.seal(tView);
9801 }
9802 return tView;
9803}
9804function createViewBlueprint(bindingStartIndex, initialViewLength) {
9805 const blueprint = ngDevMode ? new LViewBlueprint() : [];
9806 for (let i = 0; i < initialViewLength; i++) {
9807 blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
9808 }
9809 return blueprint;
9810}
9811function createError(text, token) {
9812 return new Error(`Renderer: ${text} [${stringifyForError(token)}]`);
9813}
9814function assertHostNodeExists(rElement, elementOrSelector) {
9815 if (!rElement) {
9816 if (typeof elementOrSelector === 'string') {
9817 throw createError('Host node with selector not found:', elementOrSelector);
9818 }
9819 else {
9820 throw createError('Host node is required:', elementOrSelector);
9821 }
9822 }
9823}
9824/**
9825 * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
9826 *
9827 * @param rendererFactory Factory function to create renderer instance.
9828 * @param elementOrSelector Render element or CSS selector to locate the element.
9829 * @param encapsulation View Encapsulation defined for component that requests host element.
9830 */
9831function locateHostElement(renderer, elementOrSelector, encapsulation) {
9832 if (isProceduralRenderer(renderer)) {
9833 // When using native Shadow DOM, do not clear host element to allow native slot projection
9834 const preserveContent = encapsulation === ViewEncapsulation$1.ShadowDom;
9835 return renderer.selectRootElement(elementOrSelector, preserveContent);
9836 }
9837 let rElement = typeof elementOrSelector === 'string' ?
9838 renderer.querySelector(elementOrSelector) :
9839 elementOrSelector;
9840 ngDevMode && assertHostNodeExists(rElement, elementOrSelector);
9841 // Always clear host element's content when Renderer3 is in use. For procedural renderer case we
9842 // make it depend on whether ShadowDom encapsulation is used (in which case the content should be
9843 // preserved to allow native slot projection). ShadowDom encapsulation requires procedural
9844 // renderer, and procedural renderer case is handled above.
9845 rElement.textContent = '';
9846 return rElement;
9847}
9848/**
9849 * Saves context for this cleanup function in LView.cleanupInstances.
9850 *
9851 * On the first template pass, saves in TView:
9852 * - Cleanup function
9853 * - Index of context we just saved in LView.cleanupInstances
9854 *
9855 * This function can also be used to store instance specific cleanup fns. In that case the `context`
9856 * is `null` and the function is store in `LView` (rather than it `TView`).
9857 */
9858function storeCleanupWithContext(tView, lView, context, cleanupFn) {
9859 const lCleanup = getOrCreateLViewCleanup(lView);
9860 if (context === null) {
9861 // If context is null that this is instance specific callback. These callbacks can only be
9862 // inserted after template shared instances. For this reason in ngDevMode we freeze the TView.
9863 if (ngDevMode) {
9864 Object.freeze(getOrCreateTViewCleanup(tView));
9865 }
9866 lCleanup.push(cleanupFn);
9867 }
9868 else {
9869 lCleanup.push(context);
9870 if (tView.firstCreatePass) {
9871 getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
9872 }
9873 }
9874}
9875function createTNode(tView, tParent, type, index, value, attrs) {
9876 ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in
9877 // `view_engine_compatibility` for additional context.
9878 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.');
9879 ngDevMode && assertNotSame(attrs, undefined, '\'undefined\' is not valid value for \'attrs\'');
9880 ngDevMode && ngDevMode.tNode++;
9881 ngDevMode && tParent && assertTNodeForTView(tParent, tView);
9882 let injectorIndex = tParent ? tParent.injectorIndex : -1;
9883 const tNode = ngDevMode ?
9884 new TNodeDebug(tView, // tView_: TView
9885 type, // type: TNodeType
9886 index, // index: number
9887 null, // insertBeforeIndex: null|-1|number|number[]
9888 injectorIndex, // injectorIndex: number
9889 -1, // directiveStart: number
9890 -1, // directiveEnd: number
9891 -1, // directiveStylingLast: number
9892 null, // propertyBindings: number[]|null
9893 0, // flags: TNodeFlags
9894 0, // providerIndexes: TNodeProviderIndexes
9895 value, // value: string|null
9896 attrs, // attrs: (string|AttributeMarker|(string|SelectorFlags)[])[]|null
9897 null, // mergedAttrs
9898 null, // localNames: (string|number)[]|null
9899 undefined, // initialInputs: (string[]|null)[]|null|undefined
9900 null, // inputs: PropertyAliases|null
9901 null, // outputs: PropertyAliases|null
9902 null, // tViews: ITView|ITView[]|null
9903 null, // next: ITNode|null
9904 null, // projectionNext: ITNode|null
9905 null, // child: ITNode|null
9906 tParent, // parent: TElementNode|TContainerNode|null
9907 null, // projection: number|(ITNode|RNode[])[]|null
9908 null, // styles: string|null
9909 null, // stylesWithoutHost: string|null
9910 undefined, // residualStyles: string|null
9911 null, // classes: string|null
9912 null, // classesWithoutHost: string|null
9913 undefined, // residualClasses: string|null
9914 0, // classBindings: TStylingRange;
9915 0) :
9916 {
9917 type,
9918 index,
9919 insertBeforeIndex: null,
9920 injectorIndex,
9921 directiveStart: -1,
9922 directiveEnd: -1,
9923 directiveStylingLast: -1,
9924 propertyBindings: null,
9925 flags: 0,
9926 providerIndexes: 0,
9927 value: value,
9928 attrs: attrs,
9929 mergedAttrs: null,
9930 localNames: null,
9931 initialInputs: undefined,
9932 inputs: null,
9933 outputs: null,
9934 tViews: null,
9935 next: null,
9936 projectionNext: null,
9937 child: null,
9938 parent: tParent,
9939 projection: null,
9940 styles: null,
9941 stylesWithoutHost: null,
9942 residualStyles: undefined,
9943 classes: null,
9944 classesWithoutHost: null,
9945 residualClasses: undefined,
9946 classBindings: 0,
9947 styleBindings: 0,
9948 };
9949 if (ngDevMode) {
9950 // For performance reasons it is important that the tNode retains the same shape during runtime.
9951 // (To make sure that all of the code is monomorphic.) For this reason we seal the object to
9952 // prevent class transitions.
9953 Object.seal(tNode);
9954 }
9955 return tNode;
9956}
9957function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) {
9958 for (let publicName in inputAliasMap) {
9959 if (inputAliasMap.hasOwnProperty(publicName)) {
9960 propStore = propStore === null ? {} : propStore;
9961 const internalName = inputAliasMap[publicName];
9962 if (propStore.hasOwnProperty(publicName)) {
9963 propStore[publicName].push(directiveDefIdx, internalName);
9964 }
9965 else {
9966 (propStore[publicName] = [directiveDefIdx, internalName]);
9967 }
9968 }
9969 }
9970 return propStore;
9971}
9972/**
9973 * Initializes data structures required to work with directive inputs and outputs.
9974 * Initialization is done for all directives matched on a given TNode.
9975 */
9976function initializeInputAndOutputAliases(tView, tNode) {
9977 ngDevMode && assertFirstCreatePass(tView);
9978 const start = tNode.directiveStart;
9979 const end = tNode.directiveEnd;
9980 const tViewData = tView.data;
9981 const tNodeAttrs = tNode.attrs;
9982 const inputsFromAttrs = ngDevMode ? new TNodeInitialInputs() : [];
9983 let inputsStore = null;
9984 let outputsStore = null;
9985 for (let i = start; i < end; i++) {
9986 const directiveDef = tViewData[i];
9987 const directiveInputs = directiveDef.inputs;
9988 // Do not use unbound attributes as inputs to structural directives, since structural
9989 // directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
9990 // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which
9991 // should be set for inline templates.
9992 const initialInputs = (tNodeAttrs !== null && !isInlineTemplate(tNode)) ?
9993 generateInitialInputs(directiveInputs, tNodeAttrs) :
9994 null;
9995 inputsFromAttrs.push(initialInputs);
9996 inputsStore = generatePropertyAliases(directiveInputs, i, inputsStore);
9997 outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore);
9998 }
9999 if (inputsStore !== null) {
10000 if (inputsStore.hasOwnProperty('class')) {
10001 tNode.flags |= 16 /* hasClassInput */;
10002 }
10003 if (inputsStore.hasOwnProperty('style')) {
10004 tNode.flags |= 32 /* hasStyleInput */;
10005 }
10006 }
10007 tNode.initialInputs = inputsFromAttrs;
10008 tNode.inputs = inputsStore;
10009 tNode.outputs = outputsStore;
10010}
10011/**
10012 * Mapping between attributes names that don't correspond to their element property names.
10013 *
10014 * Performance note: this function is written as a series of if checks (instead of, say, a property
10015 * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of
10016 * mapping property names. Do NOT change without benchmarking.
10017 *
10018 * Note: this mapping has to be kept in sync with the equally named mapping in the template
10019 * type-checking machinery of ngtsc.
10020 */
10021function mapPropName(name) {
10022 if (name === 'class')
10023 return 'className';
10024 if (name === 'for')
10025 return 'htmlFor';
10026 if (name === 'formaction')
10027 return 'formAction';
10028 if (name === 'innerHtml')
10029 return 'innerHTML';
10030 if (name === 'readonly')
10031 return 'readOnly';
10032 if (name === 'tabindex')
10033 return 'tabIndex';
10034 return name;
10035}
10036function elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, nativeOnly) {
10037 ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
10038 const element = getNativeByTNode(tNode, lView);
10039 let inputData = tNode.inputs;
10040 let dataValue;
10041 if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) {
10042 setInputsForProperty(tView, lView, dataValue, propName, value);
10043 if (isComponentHost(tNode))
10044 markDirtyIfOnPush(lView, tNode.index);
10045 if (ngDevMode) {
10046 setNgReflectProperties(lView, element, tNode.type, dataValue, value);
10047 }
10048 }
10049 else if (tNode.type & 3 /* AnyRNode */) {
10050 propName = mapPropName(propName);
10051 if (ngDevMode) {
10052 validateAgainstEventProperties(propName);
10053 if (!validateProperty(tView, element, propName, tNode)) {
10054 // Return here since we only log warnings for unknown properties.
10055 logUnknownPropertyError(propName, tNode);
10056 return;
10057 }
10058 ngDevMode.rendererSetProperty++;
10059 }
10060 // It is assumed that the sanitizer is only added when the compiler determines that the
10061 // property is risky, so sanitization can be done without further checks.
10062 value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value;
10063 if (isProceduralRenderer(renderer)) {
10064 renderer.setProperty(element, propName, value);
10065 }
10066 else if (!isAnimationProp(propName)) {
10067 element.setProperty ? element.setProperty(propName, value) :
10068 element[propName] = value;
10069 }
10070 }
10071 else if (tNode.type & 12 /* AnyContainer */) {
10072 // If the node is a container and the property didn't
10073 // match any of the inputs or schemas we should throw.
10074 if (ngDevMode && !matchingSchemas(tView, tNode.value)) {
10075 logUnknownPropertyError(propName, tNode);
10076 }
10077 }
10078}
10079/** If node is an OnPush component, marks its LView dirty. */
10080function markDirtyIfOnPush(lView, viewIndex) {
10081 ngDevMode && assertLView(lView);
10082 const childComponentLView = getComponentLViewByIndex(viewIndex, lView);
10083 if (!(childComponentLView[FLAGS] & 16 /* CheckAlways */)) {
10084 childComponentLView[FLAGS] |= 64 /* Dirty */;
10085 }
10086}
10087function setNgReflectProperty(lView, element, type, attrName, value) {
10088 const renderer = lView[RENDERER];
10089 attrName = normalizeDebugBindingName(attrName);
10090 const debugValue = normalizeDebugBindingValue(value);
10091 if (type & 3 /* AnyRNode */) {
10092 if (value == null) {
10093 isProceduralRenderer(renderer) ? renderer.removeAttribute(element, attrName) :
10094 element.removeAttribute(attrName);
10095 }
10096 else {
10097 isProceduralRenderer(renderer) ?
10098 renderer.setAttribute(element, attrName, debugValue) :
10099 element.setAttribute(attrName, debugValue);
10100 }
10101 }
10102 else {
10103 const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
10104 if (isProceduralRenderer(renderer)) {
10105 renderer.setValue(element, textContent);
10106 }
10107 else {
10108 element.textContent = textContent;
10109 }
10110 }
10111}
10112function setNgReflectProperties(lView, element, type, dataValue, value) {
10113 if (type & (3 /* AnyRNode */ | 4 /* Container */)) {
10114 /**
10115 * dataValue is an array containing runtime input or output names for the directives:
10116 * i+0: directive instance index
10117 * i+1: privateName
10118 *
10119 * e.g. [0, 'change', 'change-minified']
10120 * we want to set the reflected property with the privateName: dataValue[i+1]
10121 */
10122 for (let i = 0; i < dataValue.length; i += 2) {
10123 setNgReflectProperty(lView, element, type, dataValue[i + 1], value);
10124 }
10125 }
10126}
10127function validateProperty(tView, element, propName, tNode) {
10128 // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
10129 // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
10130 // defined as an array (as an empty array in case `schemas` field is not defined) and we should
10131 // execute the check below.
10132 if (tView.schemas === null)
10133 return true;
10134 // The property is considered valid if the element matches the schema, it exists on the element
10135 // or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
10136 if (matchingSchemas(tView, tNode.value) || propName in element || isAnimationProp(propName)) {
10137 return true;
10138 }
10139 // Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
10140 // need to account for both here, while being careful for `typeof null` also returning 'object'.
10141 return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
10142}
10143function matchingSchemas(tView, tagName) {
10144 const schemas = tView.schemas;
10145 if (schemas !== null) {
10146 for (let i = 0; i < schemas.length; i++) {
10147 const schema = schemas[i];
10148 if (schema === NO_ERRORS_SCHEMA ||
10149 schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
10150 return true;
10151 }
10152 }
10153 }
10154 return false;
10155}
10156/**
10157 * Logs an error that a property is not supported on an element.
10158 * @param propName Name of the invalid property.
10159 * @param tNode Node on which we encountered the property.
10160 */
10161function logUnknownPropertyError(propName, tNode) {
10162 let message = `Can't bind to '${propName}' since it isn't a known property of '${tNode.value}'.`;
10163 console.error(formatRuntimeError("303" /* UNKNOWN_BINDING */, message));
10164}
10165/**
10166 * Instantiate a root component.
10167 */
10168function instantiateRootComponent(tView, lView, def) {
10169 const rootTNode = getCurrentTNode();
10170 if (tView.firstCreatePass) {
10171 if (def.providersResolver)
10172 def.providersResolver(def);
10173 const directiveIndex = allocExpando(tView, lView, 1, null);
10174 ngDevMode &&
10175 assertEqual(directiveIndex, rootTNode.directiveStart, 'Because this is a root component the allocated expando should match the TNode component.');
10176 configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def);
10177 }
10178 const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode);
10179 attachPatchData(directive, lView);
10180 const native = getNativeByTNode(rootTNode, lView);
10181 if (native) {
10182 attachPatchData(native, lView);
10183 }
10184 return directive;
10185}
10186/**
10187 * Resolve the matched directives on a node.
10188 */
10189function resolveDirectives(tView, lView, tNode, localRefs) {
10190 // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in
10191 // tsickle.
10192 ngDevMode && assertFirstCreatePass(tView);
10193 let hasDirectives = false;
10194 if (getBindingsEnabled()) {
10195 const directiveDefs = findDirectiveDefMatches(tView, lView, tNode);
10196 const exportsMap = localRefs === null ? null : { '': -1 };
10197 if (directiveDefs !== null) {
10198 hasDirectives = true;
10199 initTNodeFlags(tNode, tView.data.length, directiveDefs.length);
10200 // When the same token is provided by several directives on the same node, some rules apply in
10201 // the viewEngine:
10202 // - viewProviders have priority over providers
10203 // - the last directive in NgModule.declarations has priority over the previous one
10204 // So to match these rules, the order in which providers are added in the arrays is very
10205 // important.
10206 for (let i = 0; i < directiveDefs.length; i++) {
10207 const def = directiveDefs[i];
10208 if (def.providersResolver)
10209 def.providersResolver(def);
10210 }
10211 let preOrderHooksFound = false;
10212 let preOrderCheckHooksFound = false;
10213 let directiveIdx = allocExpando(tView, lView, directiveDefs.length, null);
10214 ngDevMode &&
10215 assertSame(directiveIdx, tNode.directiveStart, 'TNode.directiveStart should point to just allocated space');
10216 for (let i = 0; i < directiveDefs.length; i++) {
10217 const def = directiveDefs[i];
10218 // Merge the attrs in the order of matches. This assumes that the first directive is the
10219 // component itself, so that the component has the least priority.
10220 tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs);
10221 configureViewWithDirective(tView, tNode, lView, directiveIdx, def);
10222 saveNameToExportMap(directiveIdx, def, exportsMap);
10223 if (def.contentQueries !== null)
10224 tNode.flags |= 8 /* hasContentQuery */;
10225 if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0)
10226 tNode.flags |= 128 /* hasHostBindings */;
10227 const lifeCycleHooks = def.type.prototype;
10228 // Only push a node index into the preOrderHooks array if this is the first
10229 // pre-order hook found on this node.
10230 if (!preOrderHooksFound &&
10231 (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngOnInit || lifeCycleHooks.ngDoCheck)) {
10232 // We will push the actual hook function into this array later during dir instantiation.
10233 // We cannot do it now because we must ensure hooks are registered in the same
10234 // order that directives are created (i.e. injection order).
10235 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(tNode.index);
10236 preOrderHooksFound = true;
10237 }
10238 if (!preOrderCheckHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngDoCheck)) {
10239 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(tNode.index);
10240 preOrderCheckHooksFound = true;
10241 }
10242 directiveIdx++;
10243 }
10244 initializeInputAndOutputAliases(tView, tNode);
10245 }
10246 if (exportsMap)
10247 cacheMatchingLocalNames(tNode, localRefs, exportsMap);
10248 }
10249 // Merge the template attrs last so that they have the highest priority.
10250 tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
10251 return hasDirectives;
10252}
10253/**
10254 * Add `hostBindings` to the `TView.hostBindingOpCodes`.
10255 *
10256 * @param tView `TView` to which the `hostBindings` should be added.
10257 * @param tNode `TNode` the element which contains the directive
10258 * @param lView `LView` current `LView`
10259 * @param directiveIdx Directive index in view.
10260 * @param directiveVarsIdx Where will the directive's vars be stored
10261 * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add.
10262 */
10263function registerHostBindingOpCodes(tView, tNode, lView, directiveIdx, directiveVarsIdx, def) {
10264 ngDevMode && assertFirstCreatePass(tView);
10265 const hostBindings = def.hostBindings;
10266 if (hostBindings) {
10267 let hostBindingOpCodes = tView.hostBindingOpCodes;
10268 if (hostBindingOpCodes === null) {
10269 hostBindingOpCodes = tView.hostBindingOpCodes = [];
10270 }
10271 const elementIndx = ~tNode.index;
10272 if (lastSelectedElementIdx(hostBindingOpCodes) != elementIndx) {
10273 // Conditionally add select element so that we are more efficient in execution.
10274 // NOTE: this is strictly not necessary and it trades code size for runtime perf.
10275 // (We could just always add it.)
10276 hostBindingOpCodes.push(elementIndx);
10277 }
10278 hostBindingOpCodes.push(directiveIdx, directiveVarsIdx, hostBindings);
10279 }
10280}
10281/**
10282 * Returns the last selected element index in the `HostBindingOpCodes`
10283 *
10284 * For perf reasons we don't need to update the selected element index in `HostBindingOpCodes` only
10285 * if it changes. This method returns the last index (or '0' if not found.)
10286 *
10287 * Selected element index are only the ones which are negative.
10288 */
10289function lastSelectedElementIdx(hostBindingOpCodes) {
10290 let i = hostBindingOpCodes.length;
10291 while (i > 0) {
10292 const value = hostBindingOpCodes[--i];
10293 if (typeof value === 'number' && value < 0) {
10294 return value;
10295 }
10296 }
10297 return 0;
10298}
10299/**
10300 * Instantiate all the directives that were previously resolved on the current node.
10301 */
10302function instantiateAllDirectives(tView, lView, tNode, native) {
10303 const start = tNode.directiveStart;
10304 const end = tNode.directiveEnd;
10305 if (!tView.firstCreatePass) {
10306 getOrCreateNodeInjectorForNode(tNode, lView);
10307 }
10308 attachPatchData(native, lView);
10309 const initialInputs = tNode.initialInputs;
10310 for (let i = start; i < end; i++) {
10311 const def = tView.data[i];
10312 const isComponent = isComponentDef(def);
10313 if (isComponent) {
10314 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */);
10315 addComponentLogic(lView, tNode, def);
10316 }
10317 const directive = getNodeInjectable(lView, tView, i, tNode);
10318 attachPatchData(directive, lView);
10319 if (initialInputs !== null) {
10320 setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs);
10321 }
10322 if (isComponent) {
10323 const componentView = getComponentLViewByIndex(tNode.index, lView);
10324 componentView[CONTEXT] = directive;
10325 }
10326 }
10327}
10328function invokeDirectivesHostBindings(tView, lView, tNode) {
10329 const start = tNode.directiveStart;
10330 const end = tNode.directiveEnd;
10331 const firstCreatePass = tView.firstCreatePass;
10332 const elementIndex = tNode.index;
10333 const currentDirectiveIndex = getCurrentDirectiveIndex();
10334 try {
10335 setSelectedIndex(elementIndex);
10336 for (let dirIndex = start; dirIndex < end; dirIndex++) {
10337 const def = tView.data[dirIndex];
10338 const directive = lView[dirIndex];
10339 setCurrentDirectiveIndex(dirIndex);
10340 if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
10341 invokeHostBindingsInCreationMode(def, directive);
10342 }
10343 }
10344 }
10345 finally {
10346 setSelectedIndex(-1);
10347 setCurrentDirectiveIndex(currentDirectiveIndex);
10348 }
10349}
10350/**
10351 * Invoke the host bindings in creation mode.
10352 *
10353 * @param def `DirectiveDef` which may contain the `hostBindings` function.
10354 * @param directive Instance of directive.
10355 */
10356function invokeHostBindingsInCreationMode(def, directive) {
10357 if (def.hostBindings !== null) {
10358 def.hostBindings(1 /* Create */, directive);
10359 }
10360}
10361/**
10362 * Matches the current node against all available selectors.
10363 * If a component is matched (at most one), it is returned in first position in the array.
10364 */
10365function findDirectiveDefMatches(tView, viewData, tNode) {
10366 ngDevMode && assertFirstCreatePass(tView);
10367 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
10368 const registry = tView.directiveRegistry;
10369 let matches = null;
10370 if (registry) {
10371 for (let i = 0; i < registry.length; i++) {
10372 const def = registry[i];
10373 if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) {
10374 matches || (matches = ngDevMode ? new MatchesArray() : []);
10375 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, viewData), tView, def.type);
10376 if (isComponentDef(def)) {
10377 if (ngDevMode) {
10378 assertTNodeType(tNode, 2 /* Element */, `"${tNode.value}" tags cannot be used as component hosts. ` +
10379 `Please use a different tag to activate the ${stringify(def.type)} component.`);
10380 if (tNode.flags & 2 /* isComponentHost */)
10381 throwMultipleComponentError(tNode);
10382 }
10383 markAsComponentHost(tView, tNode);
10384 // The component is always stored first with directives after.
10385 matches.unshift(def);
10386 }
10387 else {
10388 matches.push(def);
10389 }
10390 }
10391 }
10392 }
10393 return matches;
10394}
10395/**
10396 * Marks a given TNode as a component's host. This consists of:
10397 * - setting appropriate TNode flags;
10398 * - storing index of component's host element so it will be queued for view refresh during CD.
10399 */
10400function markAsComponentHost(tView, hostTNode) {
10401 ngDevMode && assertFirstCreatePass(tView);
10402 hostTNode.flags |= 2 /* isComponentHost */;
10403 (tView.components || (tView.components = ngDevMode ? new TViewComponents() : []))
10404 .push(hostTNode.index);
10405}
10406/** Caches local names and their matching directive indices for query and template lookups. */
10407function cacheMatchingLocalNames(tNode, localRefs, exportsMap) {
10408 if (localRefs) {
10409 const localNames = tNode.localNames = ngDevMode ? new TNodeLocalNames() : [];
10410 // Local names must be stored in tNode in the same order that localRefs are defined
10411 // in the template to ensure the data is loaded in the same slots as their refs
10412 // in the template (for template queries).
10413 for (let i = 0; i < localRefs.length; i += 2) {
10414 const index = exportsMap[localRefs[i + 1]];
10415 if (index == null)
10416 throw new RuntimeError("301" /* EXPORT_NOT_FOUND */, `Export of name '${localRefs[i + 1]}' not found!`);
10417 localNames.push(localRefs[i], index);
10418 }
10419 }
10420}
10421/**
10422 * Builds up an export map as directives are created, so local refs can be quickly mapped
10423 * to their directive instances.
10424 */
10425function saveNameToExportMap(directiveIdx, def, exportsMap) {
10426 if (exportsMap) {
10427 if (def.exportAs) {
10428 for (let i = 0; i < def.exportAs.length; i++) {
10429 exportsMap[def.exportAs[i]] = directiveIdx;
10430 }
10431 }
10432 if (isComponentDef(def))
10433 exportsMap[''] = directiveIdx;
10434 }
10435}
10436/**
10437 * Initializes the flags on the current node, setting all indices to the initial index,
10438 * the directive count to 0, and adding the isComponent flag.
10439 * @param index the initial index
10440 */
10441function initTNodeFlags(tNode, index, numberOfDirectives) {
10442 ngDevMode &&
10443 assertNotEqual(numberOfDirectives, tNode.directiveEnd - tNode.directiveStart, 'Reached the max number of directives');
10444 tNode.flags |= 1 /* isDirectiveHost */;
10445 // When the first directive is created on a node, save the index
10446 tNode.directiveStart = index;
10447 tNode.directiveEnd = index + numberOfDirectives;
10448 tNode.providerIndexes = index;
10449}
10450/**
10451 * Setup directive for instantiation.
10452 *
10453 * We need to create a `NodeInjectorFactory` which is then inserted in both the `Blueprint` as well
10454 * as `LView`. `TView` gets the `DirectiveDef`.
10455 *
10456 * @param tView `TView`
10457 * @param tNode `TNode`
10458 * @param lView `LView`
10459 * @param directiveIndex Index where the directive will be stored in the Expando.
10460 * @param def `DirectiveDef`
10461 */
10462function configureViewWithDirective(tView, tNode, lView, directiveIndex, def) {
10463 ngDevMode &&
10464 assertGreaterThanOrEqual(directiveIndex, HEADER_OFFSET, 'Must be in Expando section');
10465 tView.data[directiveIndex] = def;
10466 const directiveFactory = def.factory || (def.factory = getFactoryDef(def.type, true));
10467 const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null);
10468 tView.blueprint[directiveIndex] = nodeInjectorFactory;
10469 lView[directiveIndex] = nodeInjectorFactory;
10470 registerHostBindingOpCodes(tView, tNode, lView, directiveIndex, allocExpando(tView, lView, def.hostVars, NO_CHANGE), def);
10471}
10472function addComponentLogic(lView, hostTNode, def) {
10473 const native = getNativeByTNode(hostTNode, lView);
10474 const tView = getOrCreateTComponentView(def);
10475 // Only component views should be added to the view tree directly. Embedded views are
10476 // accessed through their containers because they may be removed / re-added later.
10477 const rendererFactory = lView[RENDERER_FACTORY];
10478 const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 64 /* Dirty */ : 16 /* CheckAlways */, native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null));
10479 // Component view will always be created before any injected LContainers,
10480 // so this is a regular element, wrap it with the component view
10481 lView[hostTNode.index] = componentView;
10482}
10483function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) {
10484 if (ngDevMode) {
10485 assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
10486 validateAgainstEventAttributes(name);
10487 assertTNodeType(tNode, 2 /* Element */, `Attempted to set attribute \`${name}\` on a container node. ` +
10488 `Host bindings are not valid on ng-container or ng-template.`);
10489 }
10490 const element = getNativeByTNode(tNode, lView);
10491 setElementAttribute$1(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
10492}
10493function setElementAttribute$1(renderer, element, namespace, tagName, name, value, sanitizer) {
10494 if (value == null) {
10495 ngDevMode && ngDevMode.rendererRemoveAttribute++;
10496 isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) :
10497 element.removeAttribute(name);
10498 }
10499 else {
10500 ngDevMode && ngDevMode.rendererSetAttribute++;
10501 const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
10502 if (isProceduralRenderer(renderer)) {
10503 renderer.setAttribute(element, name, strValue, namespace);
10504 }
10505 else {
10506 namespace ? element.setAttributeNS(namespace, name, strValue) :
10507 element.setAttribute(name, strValue);
10508 }
10509 }
10510}
10511/**
10512 * Sets initial input properties on directive instances from attribute data
10513 *
10514 * @param lView Current LView that is being processed.
10515 * @param directiveIndex Index of the directive in directives array
10516 * @param instance Instance of the directive on which to set the initial inputs
10517 * @param def The directive def that contains the list of inputs
10518 * @param tNode The static data for this node
10519 */
10520function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
10521 const initialInputs = initialInputData[directiveIndex];
10522 if (initialInputs !== null) {
10523 const setInput = def.setInput;
10524 for (let i = 0; i < initialInputs.length;) {
10525 const publicName = initialInputs[i++];
10526 const privateName = initialInputs[i++];
10527 const value = initialInputs[i++];
10528 if (setInput !== null) {
10529 def.setInput(instance, value, publicName, privateName);
10530 }
10531 else {
10532 instance[privateName] = value;
10533 }
10534 if (ngDevMode) {
10535 const nativeElement = getNativeByTNode(tNode, lView);
10536 setNgReflectProperty(lView, nativeElement, tNode.type, privateName, value);
10537 }
10538 }
10539 }
10540}
10541/**
10542 * Generates initialInputData for a node and stores it in the template's static storage
10543 * so subsequent template invocations don't have to recalculate it.
10544 *
10545 * initialInputData is an array containing values that need to be set as input properties
10546 * for directives on this node, but only once on creation. We need this array to support
10547 * the case where you set an @Input property of a directive using attribute-like syntax.
10548 * e.g. if you have a `name` @Input, you can set it once like this:
10549 *
10550 * <my-component name="Bess"></my-component>
10551 *
10552 * @param inputs The list of inputs from the directive def
10553 * @param attrs The static attrs on this node
10554 */
10555function generateInitialInputs(inputs, attrs) {
10556 let inputsToStore = null;
10557 let i = 0;
10558 while (i < attrs.length) {
10559 const attrName = attrs[i];
10560 if (attrName === 0 /* NamespaceURI */) {
10561 // We do not allow inputs on namespaced attributes.
10562 i += 4;
10563 continue;
10564 }
10565 else if (attrName === 5 /* ProjectAs */) {
10566 // Skip over the `ngProjectAs` value.
10567 i += 2;
10568 continue;
10569 }
10570 // If we hit any other attribute markers, we're done anyway. None of those are valid inputs.
10571 if (typeof attrName === 'number')
10572 break;
10573 if (inputs.hasOwnProperty(attrName)) {
10574 if (inputsToStore === null)
10575 inputsToStore = [];
10576 inputsToStore.push(attrName, inputs[attrName], attrs[i + 1]);
10577 }
10578 i += 2;
10579 }
10580 return inputsToStore;
10581}
10582//////////////////////////
10583//// ViewContainer & View
10584//////////////////////////
10585// Not sure why I need to do `any` here but TS complains later.
10586const LContainerArray = class LContainer extends Array {
10587};
10588/**
10589 * Creates a LContainer, either from a container instruction, or for a ViewContainerRef.
10590 *
10591 * @param hostNative The host element for the LContainer
10592 * @param hostTNode The host TNode for the LContainer
10593 * @param currentView The parent view of the LContainer
10594 * @param native The native comment element
10595 * @param isForViewContainerRef Optional a flag indicating the ViewContainerRef case
10596 * @returns LContainer
10597 */
10598function createLContainer(hostNative, currentView, native, tNode) {
10599 ngDevMode && assertLView(currentView);
10600 ngDevMode && !isProceduralRenderer(currentView[RENDERER]) && assertDomNode(native);
10601 // https://jsperf.com/array-literal-vs-new-array-really
10602 const lContainer = new (ngDevMode ? LContainerArray : Array)(hostNative, // host native
10603 true, // Boolean `true` in this position signifies that this is an `LContainer`
10604 false, // has transplanted views
10605 currentView, // parent
10606 null, // next
10607 0, // transplanted views to refresh count
10608 tNode, // t_host
10609 native, // native,
10610 null, // view refs
10611 null);
10612 ngDevMode &&
10613 assertEqual(lContainer.length, CONTAINER_HEADER_OFFSET, 'Should allocate correct number of slots for LContainer header.');
10614 ngDevMode && attachLContainerDebug(lContainer);
10615 return lContainer;
10616}
10617/**
10618 * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes
10619 * them by executing an associated template function.
10620 */
10621function refreshEmbeddedViews(lView) {
10622 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
10623 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
10624 const embeddedLView = lContainer[i];
10625 const embeddedTView = embeddedLView[TVIEW];
10626 ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
10627 if (viewAttachedToChangeDetector(embeddedLView)) {
10628 refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
10629 }
10630 }
10631 }
10632}
10633/**
10634 * Mark transplanted views as needing to be refreshed at their insertion points.
10635 *
10636 * @param lView The `LView` that may have transplanted views.
10637 */
10638function markTransplantedViewsForRefresh(lView) {
10639 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
10640 if (!lContainer[HAS_TRANSPLANTED_VIEWS])
10641 continue;
10642 const movedViews = lContainer[MOVED_VIEWS];
10643 ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS');
10644 for (let i = 0; i < movedViews.length; i++) {
10645 const movedLView = movedViews[i];
10646 const insertionLContainer = movedLView[PARENT];
10647 ngDevMode && assertLContainer(insertionLContainer);
10648 // We don't want to increment the counter if the moved LView was already marked for
10649 // refresh.
10650 if ((movedLView[FLAGS] & 1024 /* RefreshTransplantedView */) === 0) {
10651 updateTransplantedViewCount(insertionLContainer, 1);
10652 }
10653 // Note, it is possible that the `movedViews` is tracking views that are transplanted *and*
10654 // those that aren't (declaration component === insertion component). In the latter case,
10655 // it's fine to add the flag, as we will clear it immediately in
10656 // `refreshEmbeddedViews` for the view currently being refreshed.
10657 movedLView[FLAGS] |= 1024 /* RefreshTransplantedView */;
10658 }
10659 }
10660}
10661/////////////
10662/**
10663 * Refreshes components by entering the component view and processing its bindings, queries, etc.
10664 *
10665 * @param componentHostIdx Element index in LView[] (adjusted for HEADER_OFFSET)
10666 */
10667function refreshComponent(hostLView, componentHostIdx) {
10668 ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');
10669 const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
10670 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
10671 if (viewAttachedToChangeDetector(componentView)) {
10672 const tView = componentView[TVIEW];
10673 if (componentView[FLAGS] & (16 /* CheckAlways */ | 64 /* Dirty */)) {
10674 refreshView(tView, componentView, tView.template, componentView[CONTEXT]);
10675 }
10676 else if (componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
10677 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
10678 refreshContainsDirtyView(componentView);
10679 }
10680 }
10681}
10682/**
10683 * Refreshes all transplanted views marked with `LViewFlags.RefreshTransplantedView` that are
10684 * children or descendants of the given lView.
10685 *
10686 * @param lView The lView which contains descendant transplanted views that need to be refreshed.
10687 */
10688function refreshContainsDirtyView(lView) {
10689 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
10690 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
10691 const embeddedLView = lContainer[i];
10692 if (embeddedLView[FLAGS] & 1024 /* RefreshTransplantedView */) {
10693 const embeddedTView = embeddedLView[TVIEW];
10694 ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
10695 refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
10696 }
10697 else if (embeddedLView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
10698 refreshContainsDirtyView(embeddedLView);
10699 }
10700 }
10701 }
10702 const tView = lView[TVIEW];
10703 // Refresh child component views.
10704 const components = tView.components;
10705 if (components !== null) {
10706 for (let i = 0; i < components.length; i++) {
10707 const componentView = getComponentLViewByIndex(components[i], lView);
10708 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
10709 if (viewAttachedToChangeDetector(componentView) &&
10710 componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
10711 refreshContainsDirtyView(componentView);
10712 }
10713 }
10714 }
10715}
10716function renderComponent$1(hostLView, componentHostIdx) {
10717 ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
10718 const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
10719 const componentTView = componentView[TVIEW];
10720 syncViewWithBlueprint(componentTView, componentView);
10721 renderView(componentTView, componentView, componentView[CONTEXT]);
10722}
10723/**
10724 * Syncs an LView instance with its blueprint if they have gotten out of sync.
10725 *
10726 * Typically, blueprints and their view instances should always be in sync, so the loop here
10727 * will be skipped. However, consider this case of two components side-by-side:
10728 *
10729 * App template:
10730 * ```
10731 * <comp></comp>
10732 * <comp></comp>
10733 * ```
10734 *
10735 * The following will happen:
10736 * 1. App template begins processing.
10737 * 2. First <comp> is matched as a component and its LView is created.
10738 * 3. Second <comp> is matched as a component and its LView is created.
10739 * 4. App template completes processing, so it's time to check child templates.
10740 * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.
10741 * 6. Second <comp> template is checked. Its blueprint has been updated by the first
10742 * <comp> template, but its LView was created before this update, so it is out of sync.
10743 *
10744 * Note that embedded views inside ngFor loops will never be out of sync because these views
10745 * are processed as soon as they are created.
10746 *
10747 * @param tView The `TView` that contains the blueprint for syncing
10748 * @param lView The view to sync
10749 */
10750function syncViewWithBlueprint(tView, lView) {
10751 for (let i = lView.length; i < tView.blueprint.length; i++) {
10752 lView.push(tView.blueprint[i]);
10753 }
10754}
10755/**
10756 * Adds LView or LContainer to the end of the current view tree.
10757 *
10758 * This structure will be used to traverse through nested views to remove listeners
10759 * and call onDestroy callbacks.
10760 *
10761 * @param lView The view where LView or LContainer should be added
10762 * @param adjustedHostIndex Index of the view's host node in LView[], adjusted for header
10763 * @param lViewOrLContainer The LView or LContainer to add to the view tree
10764 * @returns The state passed in
10765 */
10766function addToViewTree(lView, lViewOrLContainer) {
10767 // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer
10768 // to the end of the queue, which means if the developer retrieves the LContainers from RNodes out
10769 // of order, the change detection will run out of order, as the act of retrieving the the
10770 // LContainer from the RNode is what adds it to the queue.
10771 if (lView[CHILD_HEAD]) {
10772 lView[CHILD_TAIL][NEXT] = lViewOrLContainer;
10773 }
10774 else {
10775 lView[CHILD_HEAD] = lViewOrLContainer;
10776 }
10777 lView[CHILD_TAIL] = lViewOrLContainer;
10778 return lViewOrLContainer;
10779}
10780///////////////////////////////
10781//// Change detection
10782///////////////////////////////
10783/**
10784 * Marks current view and all ancestors dirty.
10785 *
10786 * Returns the root view because it is found as a byproduct of marking the view tree
10787 * dirty, and can be used by methods that consume markViewDirty() to easily schedule
10788 * change detection. Otherwise, such methods would need to traverse up the view tree
10789 * an additional time to get the root view and schedule a tick on it.
10790 *
10791 * @param lView The starting LView to mark dirty
10792 * @returns the root LView
10793 */
10794function markViewDirty(lView) {
10795 while (lView) {
10796 lView[FLAGS] |= 64 /* Dirty */;
10797 const parent = getLViewParent(lView);
10798 // Stop traversing up as soon as you find a root view that wasn't attached to any container
10799 if (isRootView(lView) && !parent) {
10800 return lView;
10801 }
10802 // continue otherwise
10803 lView = parent;
10804 }
10805 return null;
10806}
10807/**
10808 * Used to schedule change detection on the whole application.
10809 *
10810 * Unlike `tick`, `scheduleTick` coalesces multiple calls into one change detection run.
10811 * It is usually called indirectly by calling `markDirty` when the view needs to be
10812 * re-rendered.
10813 *
10814 * Typically `scheduleTick` uses `requestAnimationFrame` to coalesce multiple
10815 * `scheduleTick` requests. The scheduling function can be overridden in
10816 * `renderComponent`'s `scheduler` option.
10817 */
10818function scheduleTick(rootContext, flags) {
10819 const nothingScheduled = rootContext.flags === 0 /* Empty */;
10820 if (nothingScheduled && rootContext.clean == _CLEAN_PROMISE) {
10821 // https://github.com/angular/angular/issues/39296
10822 // should only attach the flags when really scheduling a tick
10823 rootContext.flags |= flags;
10824 let res;
10825 rootContext.clean = new Promise((r) => res = r);
10826 rootContext.scheduler(() => {
10827 if (rootContext.flags & 1 /* DetectChanges */) {
10828 rootContext.flags &= ~1 /* DetectChanges */;
10829 tickRootContext(rootContext);
10830 }
10831 if (rootContext.flags & 2 /* FlushPlayers */) {
10832 rootContext.flags &= ~2 /* FlushPlayers */;
10833 const playerHandler = rootContext.playerHandler;
10834 if (playerHandler) {
10835 playerHandler.flushPlayers();
10836 }
10837 }
10838 rootContext.clean = _CLEAN_PROMISE;
10839 res(null);
10840 });
10841 }
10842}
10843function tickRootContext(rootContext) {
10844 for (let i = 0; i < rootContext.components.length; i++) {
10845 const rootComponent = rootContext.components[i];
10846 const lView = readPatchedLView(rootComponent);
10847 const tView = lView[TVIEW];
10848 renderComponentOrTemplate(tView, lView, tView.template, rootComponent);
10849 }
10850}
10851function detectChangesInternal(tView, lView, context) {
10852 const rendererFactory = lView[RENDERER_FACTORY];
10853 if (rendererFactory.begin)
10854 rendererFactory.begin();
10855 try {
10856 refreshView(tView, lView, tView.template, context);
10857 }
10858 catch (error) {
10859 handleError(lView, error);
10860 throw error;
10861 }
10862 finally {
10863 if (rendererFactory.end)
10864 rendererFactory.end();
10865 }
10866}
10867/**
10868 * Synchronously perform change detection on a root view and its components.
10869 *
10870 * @param lView The view which the change detection should be performed on.
10871 */
10872function detectChangesInRootView(lView) {
10873 tickRootContext(lView[CONTEXT]);
10874}
10875function checkNoChangesInternal(tView, view, context) {
10876 setIsInCheckNoChangesMode(true);
10877 try {
10878 detectChangesInternal(tView, view, context);
10879 }
10880 finally {
10881 setIsInCheckNoChangesMode(false);
10882 }
10883}
10884/**
10885 * Checks the change detector on a root view and its components, and throws if any changes are
10886 * detected.
10887 *
10888 * This is used in development mode to verify that running change detection doesn't
10889 * introduce other changes.
10890 *
10891 * @param lView The view which the change detection should be checked on.
10892 */
10893function checkNoChangesInRootView(lView) {
10894 setIsInCheckNoChangesMode(true);
10895 try {
10896 detectChangesInRootView(lView);
10897 }
10898 finally {
10899 setIsInCheckNoChangesMode(false);
10900 }
10901}
10902function executeViewQueryFn(flags, viewQueryFn, component) {
10903 ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
10904 setCurrentQueryIndex(0);
10905 viewQueryFn(flags, component);
10906}
10907///////////////////////////////
10908//// Bindings & interpolations
10909///////////////////////////////
10910/**
10911 * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
10912 *
10913 * In order to support TestBed's `DebugElement.properties` we need to save, for each binding:
10914 * - a bound property name;
10915 * - a static parts of interpolated strings;
10916 *
10917 * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a
10918 * property binding metadata will be stored in `TView.data` at the same index as a bound value in
10919 * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
10920 * following format:
10921 * - `propertyName` for bound properties;
10922 * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for
10923 * interpolated properties.
10924 *
10925 * @param tData `TData` where meta-data will be saved;
10926 * @param tNode `TNode` that is a target of the binding;
10927 * @param propertyName bound property name;
10928 * @param bindingIndex binding index in `LView`
10929 * @param interpolationParts static interpolation parts (for property interpolations)
10930 */
10931function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) {
10932 // Binding meta-data are stored only the first time a given property instruction is processed.
10933 // Since we don't have a concept of the "first update pass" we need to check for presence of the
10934 // binding meta-data to decide if one should be stored (or if was stored already).
10935 if (tData[bindingIndex] === null) {
10936 if (tNode.inputs == null || !tNode.inputs[propertyName]) {
10937 const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
10938 propBindingIdxs.push(bindingIndex);
10939 let bindingMetadata = propertyName;
10940 if (interpolationParts.length > 0) {
10941 bindingMetadata +=
10942 INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
10943 }
10944 tData[bindingIndex] = bindingMetadata;
10945 }
10946 }
10947}
10948const CLEAN_PROMISE = _CLEAN_PROMISE;
10949function getOrCreateLViewCleanup(view) {
10950 // top level variables should not be exported for performance reasons (PERF_NOTES.md)
10951 return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []);
10952}
10953function getOrCreateTViewCleanup(tView) {
10954 return tView.cleanup || (tView.cleanup = ngDevMode ? new TCleanup() : []);
10955}
10956/**
10957 * There are cases where the sub component's renderer needs to be included
10958 * instead of the current renderer (see the componentSyntheticHost* instructions).
10959 */
10960function loadComponentRenderer(currentDef, tNode, lView) {
10961 // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root
10962 // component (see packages/core/src/render3/component.ts). This is not consistent with the process
10963 // of creating inner components, when current directive index is available in the state. In order
10964 // to avoid relying on current def being `null` (thus special-casing root component creation), the
10965 // process of creating root component should be unified with the process of creating inner
10966 // components.
10967 if (currentDef === null || isComponentDef(currentDef)) {
10968 lView = unwrapLView(lView[tNode.index]);
10969 }
10970 return lView[RENDERER];
10971}
10972/** Handles an error thrown in an LView. */
10973function handleError(lView, error) {
10974 const injector = lView[INJECTOR$1];
10975 const errorHandler = injector ? injector.get(ErrorHandler, null) : null;
10976 errorHandler && errorHandler.handleError(error);
10977}
10978/**
10979 * Set the inputs of directives at the current node to corresponding value.
10980 *
10981 * @param tView The current TView
10982 * @param lView the `LView` which contains the directives.
10983 * @param inputs mapping between the public "input" name and privately-known,
10984 * possibly minified, property names to write to.
10985 * @param value Value to set.
10986 */
10987function setInputsForProperty(tView, lView, inputs, publicName, value) {
10988 for (let i = 0; i < inputs.length;) {
10989 const index = inputs[i++];
10990 const privateName = inputs[i++];
10991 const instance = lView[index];
10992 ngDevMode && assertIndexInRange(lView, index);
10993 const def = tView.data[index];
10994 if (def.setInput !== null) {
10995 def.setInput(instance, value, publicName, privateName);
10996 }
10997 else {
10998 instance[privateName] = value;
10999 }
11000 }
11001}
11002/**
11003 * Updates a text binding at a given index in a given LView.
11004 */
11005function textBindingInternal(lView, index, value) {
11006 ngDevMode && assertString(value, 'Value should be a string');
11007 ngDevMode && assertNotSame(value, NO_CHANGE, 'value should not be NO_CHANGE');
11008 ngDevMode && assertIndexInRange(lView, index);
11009 const element = getNativeByIndex(index, lView);
11010 ngDevMode && assertDefined(element, 'native element should exist');
11011 updateTextNode(lView[RENDERER], element, value);
11012}
11013
11014/**
11015 * @license
11016 * Copyright Google LLC All Rights Reserved.
11017 *
11018 * Use of this source code is governed by an MIT-style license that can be
11019 * found in the LICENSE file at https://angular.io/license
11020 */
11021/**
11022 * Compute the static styling (class/style) from `TAttributes`.
11023 *
11024 * This function should be called during `firstCreatePass` only.
11025 *
11026 * @param tNode The `TNode` into which the styling information should be loaded.
11027 * @param attrs `TAttributes` containing the styling information.
11028 * @param writeToHost Where should the resulting static styles be written?
11029 * - `false` Write to `TNode.stylesWithoutHost` / `TNode.classesWithoutHost`
11030 * - `true` Write to `TNode.styles` / `TNode.classes`
11031 */
11032function computeStaticStyling(tNode, attrs, writeToHost) {
11033 ngDevMode &&
11034 assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only');
11035 let styles = writeToHost ? tNode.styles : null;
11036 let classes = writeToHost ? tNode.classes : null;
11037 let mode = 0;
11038 if (attrs !== null) {
11039 for (let i = 0; i < attrs.length; i++) {
11040 const value = attrs[i];
11041 if (typeof value === 'number') {
11042 mode = value;
11043 }
11044 else if (mode == 1 /* Classes */) {
11045 classes = concatStringsWithSpace(classes, value);
11046 }
11047 else if (mode == 2 /* Styles */) {
11048 const style = value;
11049 const styleValue = attrs[++i];
11050 styles = concatStringsWithSpace(styles, style + ': ' + styleValue + ';');
11051 }
11052 }
11053 }
11054 writeToHost ? tNode.styles = styles : tNode.stylesWithoutHost = styles;
11055 writeToHost ? tNode.classes = classes : tNode.classesWithoutHost = classes;
11056}
11057
11058/**
11059 * @license
11060 * Copyright Google LLC All Rights Reserved.
11061 *
11062 * Use of this source code is governed by an MIT-style license that can be
11063 * found in the LICENSE file at https://angular.io/license
11064 */
11065/**
11066 * Synchronously perform change detection on a component (and possibly its sub-components).
11067 *
11068 * This function triggers change detection in a synchronous way on a component.
11069 *
11070 * @param component The component which the change detection should be performed on.
11071 */
11072function detectChanges(component) {
11073 const view = getComponentViewByInstance(component);
11074 detectChangesInternal(view[TVIEW], view, component);
11075}
11076/**
11077 * Marks the component as dirty (needing change detection). Marking a component dirty will
11078 * schedule a change detection on it at some point in the future.
11079 *
11080 * Marking an already dirty component as dirty won't do anything. Only one outstanding change
11081 * detection can be scheduled per component tree.
11082 *
11083 * @param component Component to mark as dirty.
11084 */
11085function markDirty(component) {
11086 ngDevMode && assertDefined(component, 'component');
11087 const rootView = markViewDirty(getComponentViewByInstance(component));
11088 ngDevMode && assertDefined(rootView[CONTEXT], 'rootContext should be defined');
11089 scheduleTick(rootView[CONTEXT], 1 /* DetectChanges */);
11090}
11091/**
11092 * Used to perform change detection on the whole application.
11093 *
11094 * This is equivalent to `detectChanges`, but invoked on root component. Additionally, `tick`
11095 * executes lifecycle hooks and conditionally checks components based on their
11096 * `ChangeDetectionStrategy` and dirtiness.
11097 *
11098 * The preferred way to trigger change detection is to call `markDirty`. `markDirty` internally
11099 * schedules `tick` using a scheduler in order to coalesce multiple `markDirty` calls into a
11100 * single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
11101 * be changed when calling `renderComponent` and providing the `scheduler` option.
11102 */
11103function tick(component) {
11104 const rootView = getRootView(component);
11105 const rootContext = rootView[CONTEXT];
11106 tickRootContext(rootContext);
11107}
11108
11109/**
11110 * @license
11111 * Copyright Google LLC All Rights Reserved.
11112 *
11113 * Use of this source code is governed by an MIT-style license that can be
11114 * found in the LICENSE file at https://angular.io/license
11115 */
11116/**
11117 * An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.
11118 *
11119 * Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a
11120 * project.
11121 *
11122 * @publicApi
11123 */
11124const INJECTOR = new InjectionToken('INJECTOR',
11125// Dissable tslint because this is const enum which gets inlined not top level prop access.
11126// tslint:disable-next-line: no-toplevel-property-access
11127-1 /* Injector */);
11128
11129/**
11130 * @license
11131 * Copyright Google LLC All Rights Reserved.
11132 *
11133 * Use of this source code is governed by an MIT-style license that can be
11134 * found in the LICENSE file at https://angular.io/license
11135 */
11136class NullInjector {
11137 get(token, notFoundValue = THROW_IF_NOT_FOUND) {
11138 if (notFoundValue === THROW_IF_NOT_FOUND) {
11139 const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);
11140 error.name = 'NullInjectorError';
11141 throw error;
11142 }
11143 return notFoundValue;
11144 }
11145}
11146
11147/**
11148 * @license
11149 * Copyright Google LLC All Rights Reserved.
11150 *
11151 * Use of this source code is governed by an MIT-style license that can be
11152 * found in the LICENSE file at https://angular.io/license
11153 */
11154/**
11155 * An internal token whose presence in an injector indicates that the injector should treat itself
11156 * as a root scoped injector when processing requests for unknown tokens which may indicate
11157 * they are provided in the root scope.
11158 */
11159const INJECTOR_SCOPE = new InjectionToken('Set Injector scope.');
11160
11161/**
11162 * @license
11163 * Copyright Google LLC All Rights Reserved.
11164 *
11165 * Use of this source code is governed by an MIT-style license that can be
11166 * found in the LICENSE file at https://angular.io/license
11167 */
11168/**
11169 * Marker which indicates that a value has not yet been created from the factory function.
11170 */
11171const NOT_YET = {};
11172/**
11173 * Marker which indicates that the factory function for a token is in the process of being called.
11174 *
11175 * If the injector is asked to inject a token with its value set to CIRCULAR, that indicates
11176 * injection of a dependency has recursively attempted to inject the original token, and there is
11177 * a circular dependency among the providers.
11178 */
11179const CIRCULAR$1 = {};
11180/**
11181 * A lazily initialized NullInjector.
11182 */
11183let NULL_INJECTOR$1 = undefined;
11184function getNullInjector() {
11185 if (NULL_INJECTOR$1 === undefined) {
11186 NULL_INJECTOR$1 = new NullInjector();
11187 }
11188 return NULL_INJECTOR$1;
11189}
11190/**
11191 * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
11192 *
11193 * @publicApi
11194 */
11195function createInjector$1(defType, parent = null, additionalProviders = null, name) {
11196 const injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);
11197 injector._resolveInjectorDefTypes();
11198 return injector;
11199}
11200/**
11201 * Creates a new injector without eagerly resolving its injector types. Can be used in places
11202 * where resolving the injector types immediately can lead to an infinite loop. The injector types
11203 * should be resolved at a later point by calling `_resolveInjectorDefTypes`.
11204 */
11205function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name) {
11206 return new R3Injector(defType, additionalProviders, parent || getNullInjector(), name);
11207}
11208class R3Injector {
11209 constructor(def, additionalProviders, parent, source = null) {
11210 this.parent = parent;
11211 /**
11212 * Map of tokens to records which contain the instances of those tokens.
11213 * - `null` value implies that we don't have the record. Used by tree-shakable injectors
11214 * to prevent further searches.
11215 */
11216 this.records = new Map();
11217 /**
11218 * The transitive set of `InjectorType`s which define this injector.
11219 */
11220 this.injectorDefTypes = new Set();
11221 /**
11222 * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks.
11223 */
11224 this.onDestroy = new Set();
11225 this._destroyed = false;
11226 const dedupStack = [];
11227 // Start off by creating Records for every provider declared in every InjectorType
11228 // included transitively in additional providers then do the same for `def`. This order is
11229 // important because `def` may include providers that override ones in additionalProviders.
11230 additionalProviders &&
11231 deepForEach(additionalProviders, provider => this.processProvider(provider, def, additionalProviders));
11232 deepForEach([def], injectorDef => this.processInjectorType(injectorDef, [], dedupStack));
11233 // Make sure the INJECTOR token provides this injector.
11234 this.records.set(INJECTOR, makeRecord(undefined, this));
11235 // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide
11236 // any injectable scoped to APP_ROOT_SCOPE.
11237 const record = this.records.get(INJECTOR_SCOPE);
11238 this.scope = record != null ? record.value : null;
11239 // Source name, used for debugging
11240 this.source = source || (typeof def === 'object' ? null : stringify(def));
11241 }
11242 /**
11243 * Flag indicating that this injector was previously destroyed.
11244 */
11245 get destroyed() {
11246 return this._destroyed;
11247 }
11248 /**
11249 * Destroy the injector and release references to every instance or provider associated with it.
11250 *
11251 * Also calls the `OnDestroy` lifecycle hooks of every instance that was created for which a
11252 * hook was found.
11253 */
11254 destroy() {
11255 this.assertNotDestroyed();
11256 // Set destroyed = true first, in case lifecycle hooks re-enter destroy().
11257 this._destroyed = true;
11258 try {
11259 // Call all the lifecycle hooks.
11260 this.onDestroy.forEach(service => service.ngOnDestroy());
11261 }
11262 finally {
11263 // Release all references.
11264 this.records.clear();
11265 this.onDestroy.clear();
11266 this.injectorDefTypes.clear();
11267 }
11268 }
11269 get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
11270 this.assertNotDestroyed();
11271 // Set the injection context.
11272 const previousInjector = setCurrentInjector(this);
11273 const previousInjectImplementation = setInjectImplementation(undefined);
11274 try {
11275 // Check for the SkipSelf flag.
11276 if (!(flags & InjectFlags.SkipSelf)) {
11277 // SkipSelf isn't set, check if the record belongs to this injector.
11278 let record = this.records.get(token);
11279 if (record === undefined) {
11280 // No record, but maybe the token is scoped to this injector. Look for an injectable
11281 // def with a scope matching this injector.
11282 const def = couldBeInjectableType(token) && getInjectableDef(token);
11283 if (def && this.injectableDefInScope(def)) {
11284 // Found an injectable def and it's scoped to this injector. Pretend as if it was here
11285 // all along.
11286 record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);
11287 }
11288 else {
11289 record = null;
11290 }
11291 this.records.set(token, record);
11292 }
11293 // If a record was found, get the instance for it and return it.
11294 if (record != null /* NOT null || undefined */) {
11295 return this.hydrate(token, record);
11296 }
11297 }
11298 // Select the next injector based on the Self flag - if self is set, the next injector is
11299 // the NullInjector, otherwise it's the parent.
11300 const nextInjector = !(flags & InjectFlags.Self) ? this.parent : getNullInjector();
11301 // Set the notFoundValue based on the Optional flag - if optional is set and notFoundValue
11302 // is undefined, the value is null, otherwise it's the notFoundValue.
11303 notFoundValue = (flags & InjectFlags.Optional) && notFoundValue === THROW_IF_NOT_FOUND ?
11304 null :
11305 notFoundValue;
11306 return nextInjector.get(token, notFoundValue);
11307 }
11308 catch (e) {
11309 if (e.name === 'NullInjectorError') {
11310 const path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
11311 path.unshift(stringify(token));
11312 if (previousInjector) {
11313 // We still have a parent injector, keep throwing
11314 throw e;
11315 }
11316 else {
11317 // Format & throw the final error message when we don't have any previous injector
11318 return catchInjectorError(e, token, 'R3InjectorError', this.source);
11319 }
11320 }
11321 else {
11322 throw e;
11323 }
11324 }
11325 finally {
11326 // Lastly, restore the previous injection context.
11327 setInjectImplementation(previousInjectImplementation);
11328 setCurrentInjector(previousInjector);
11329 }
11330 }
11331 /** @internal */
11332 _resolveInjectorDefTypes() {
11333 this.injectorDefTypes.forEach(defType => this.get(defType));
11334 }
11335 toString() {
11336 const tokens = [], records = this.records;
11337 records.forEach((v, token) => tokens.push(stringify(token)));
11338 return `R3Injector[${tokens.join(', ')}]`;
11339 }
11340 assertNotDestroyed() {
11341 if (this._destroyed) {
11342 throw new Error('Injector has already been destroyed.');
11343 }
11344 }
11345 /**
11346 * Add an `InjectorType` or `InjectorTypeWithProviders` and all of its transitive providers
11347 * to this injector.
11348 *
11349 * If an `InjectorTypeWithProviders` that declares providers besides the type is specified,
11350 * the function will return "true" to indicate that the providers of the type definition need
11351 * to be processed. This allows us to process providers of injector types after all imports of
11352 * an injector definition are processed. (following View Engine semantics: see FW-1349)
11353 */
11354 processInjectorType(defOrWrappedDef, parents, dedupStack) {
11355 defOrWrappedDef = resolveForwardRef(defOrWrappedDef);
11356 if (!defOrWrappedDef)
11357 return false;
11358 // Either the defOrWrappedDef is an InjectorType (with injector def) or an
11359 // InjectorDefTypeWithProviders (aka ModuleWithProviders). Detecting either is a megamorphic
11360 // read, so care is taken to only do the read once.
11361 // First attempt to read the injector def (`ɵinj`).
11362 let def = getInjectorDef(defOrWrappedDef);
11363 // If that's not present, then attempt to read ngModule from the InjectorDefTypeWithProviders.
11364 const ngModule = (def == null) && defOrWrappedDef.ngModule || undefined;
11365 // Determine the InjectorType. In the case where `defOrWrappedDef` is an `InjectorType`,
11366 // then this is easy. In the case of an InjectorDefTypeWithProviders, then the definition type
11367 // is the `ngModule`.
11368 const defType = (ngModule === undefined) ? defOrWrappedDef : ngModule;
11369 // Check for circular dependencies.
11370 if (ngDevMode && parents.indexOf(defType) !== -1) {
11371 const defName = stringify(defType);
11372 const path = parents.map(stringify);
11373 throwCyclicDependencyError(defName, path);
11374 }
11375 // Check for multiple imports of the same module
11376 const isDuplicate = dedupStack.indexOf(defType) !== -1;
11377 // Finally, if defOrWrappedType was an `InjectorDefTypeWithProviders`, then the actual
11378 // `InjectorDef` is on its `ngModule`.
11379 if (ngModule !== undefined) {
11380 def = getInjectorDef(ngModule);
11381 }
11382 // If no definition was found, it might be from exports. Remove it.
11383 if (def == null) {
11384 return false;
11385 }
11386 // Add providers in the same way that @NgModule resolution did:
11387 // First, include providers from any imports.
11388 if (def.imports != null && !isDuplicate) {
11389 // Before processing defType's imports, add it to the set of parents. This way, if it ends
11390 // up deeply importing itself, this can be detected.
11391 ngDevMode && parents.push(defType);
11392 // Add it to the set of dedups. This way we can detect multiple imports of the same module
11393 dedupStack.push(defType);
11394 let importTypesWithProviders;
11395 try {
11396 deepForEach(def.imports, imported => {
11397 if (this.processInjectorType(imported, parents, dedupStack)) {
11398 if (importTypesWithProviders === undefined)
11399 importTypesWithProviders = [];
11400 // If the processed import is an injector type with providers, we store it in the
11401 // list of import types with providers, so that we can process those afterwards.
11402 importTypesWithProviders.push(imported);
11403 }
11404 });
11405 }
11406 finally {
11407 // Remove it from the parents set when finished.
11408 ngDevMode && parents.pop();
11409 }
11410 // Imports which are declared with providers (TypeWithProviders) need to be processed
11411 // after all imported modules are processed. This is similar to how View Engine
11412 // processes/merges module imports in the metadata resolver. See: FW-1349.
11413 if (importTypesWithProviders !== undefined) {
11414 for (let i = 0; i < importTypesWithProviders.length; i++) {
11415 const { ngModule, providers } = importTypesWithProviders[i];
11416 deepForEach(providers, provider => this.processProvider(provider, ngModule, providers || EMPTY_ARRAY));
11417 }
11418 }
11419 }
11420 // Track the InjectorType and add a provider for it. It's important that this is done after the
11421 // def's imports.
11422 this.injectorDefTypes.add(defType);
11423 const factory = getFactoryDef(defType) || (() => new defType());
11424 this.records.set(defType, makeRecord(factory, NOT_YET));
11425 // Next, include providers listed on the definition itself.
11426 const defProviders = def.providers;
11427 if (defProviders != null && !isDuplicate) {
11428 const injectorType = defOrWrappedDef;
11429 deepForEach(defProviders, provider => this.processProvider(provider, injectorType, defProviders));
11430 }
11431 return (ngModule !== undefined &&
11432 defOrWrappedDef.providers !== undefined);
11433 }
11434 /**
11435 * Process a `SingleProvider` and add it.
11436 */
11437 processProvider(provider, ngModuleType, providers) {
11438 // Determine the token from the provider. Either it's its own token, or has a {provide: ...}
11439 // property.
11440 provider = resolveForwardRef(provider);
11441 let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider && provider.provide);
11442 // Construct a `Record` for the provider.
11443 const record = providerToRecord(provider, ngModuleType, providers);
11444 if (!isTypeProvider(provider) && provider.multi === true) {
11445 // If the provider indicates that it's a multi-provider, process it specially.
11446 // First check whether it's been defined already.
11447 let multiRecord = this.records.get(token);
11448 if (multiRecord) {
11449 // It has. Throw a nice error if
11450 if (ngDevMode && multiRecord.multi === undefined) {
11451 throwMixedMultiProviderError();
11452 }
11453 }
11454 else {
11455 multiRecord = makeRecord(undefined, NOT_YET, true);
11456 multiRecord.factory = () => injectArgs(multiRecord.multi);
11457 this.records.set(token, multiRecord);
11458 }
11459 token = provider;
11460 multiRecord.multi.push(provider);
11461 }
11462 else {
11463 const existing = this.records.get(token);
11464 if (ngDevMode && existing && existing.multi !== undefined) {
11465 throwMixedMultiProviderError();
11466 }
11467 }
11468 this.records.set(token, record);
11469 }
11470 hydrate(token, record) {
11471 if (ngDevMode && record.value === CIRCULAR$1) {
11472 throwCyclicDependencyError(stringify(token));
11473 }
11474 else if (record.value === NOT_YET) {
11475 record.value = CIRCULAR$1;
11476 record.value = record.factory();
11477 }
11478 if (typeof record.value === 'object' && record.value && hasOnDestroy(record.value)) {
11479 this.onDestroy.add(record.value);
11480 }
11481 return record.value;
11482 }
11483 injectableDefInScope(def) {
11484 if (!def.providedIn) {
11485 return false;
11486 }
11487 const providedIn = resolveForwardRef(def.providedIn);
11488 if (typeof providedIn === 'string') {
11489 return providedIn === 'any' || (providedIn === this.scope);
11490 }
11491 else {
11492 return this.injectorDefTypes.has(providedIn);
11493 }
11494 }
11495}
11496function injectableDefOrInjectorDefFactory(token) {
11497 // Most tokens will have an injectable def directly on them, which specifies a factory directly.
11498 const injectableDef = getInjectableDef(token);
11499 const factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token);
11500 if (factory !== null) {
11501 return factory;
11502 }
11503 // InjectionTokens should have an injectable def (ɵprov) and thus should be handled above.
11504 // If it's missing that, it's an error.
11505 if (token instanceof InjectionToken) {
11506 throw new Error(`Token ${stringify(token)} is missing a ɵprov definition.`);
11507 }
11508 // Undecorated types can sometimes be created if they have no constructor arguments.
11509 if (token instanceof Function) {
11510 return getUndecoratedInjectableFactory(token);
11511 }
11512 // There was no way to resolve a factory for this token.
11513 throw new Error('unreachable');
11514}
11515function getUndecoratedInjectableFactory(token) {
11516 // If the token has parameters then it has dependencies that we cannot resolve implicitly.
11517 const paramLength = token.length;
11518 if (paramLength > 0) {
11519 const args = newArray(paramLength, '?');
11520 throw new Error(`Can't resolve all parameters for ${stringify(token)}: (${args.join(', ')}).`);
11521 }
11522 // The constructor function appears to have no parameters.
11523 // This might be because it inherits from a super-class. In which case, use an injectable
11524 // def from an ancestor if there is one.
11525 // Otherwise this really is a simple class with no dependencies, so return a factory that
11526 // just instantiates the zero-arg constructor.
11527 const inheritedInjectableDef = getInheritedInjectableDef(token);
11528 if (inheritedInjectableDef !== null) {
11529 return () => inheritedInjectableDef.factory(token);
11530 }
11531 else {
11532 return () => new token();
11533 }
11534}
11535function providerToRecord(provider, ngModuleType, providers) {
11536 if (isValueProvider(provider)) {
11537 return makeRecord(undefined, provider.useValue);
11538 }
11539 else {
11540 const factory = providerToFactory(provider, ngModuleType, providers);
11541 return makeRecord(factory, NOT_YET);
11542 }
11543}
11544/**
11545 * Converts a `SingleProvider` into a factory function.
11546 *
11547 * @param provider provider to convert to factory
11548 */
11549function providerToFactory(provider, ngModuleType, providers) {
11550 let factory = undefined;
11551 if (isTypeProvider(provider)) {
11552 const unwrappedProvider = resolveForwardRef(provider);
11553 return getFactoryDef(unwrappedProvider) || injectableDefOrInjectorDefFactory(unwrappedProvider);
11554 }
11555 else {
11556 if (isValueProvider(provider)) {
11557 factory = () => resolveForwardRef(provider.useValue);
11558 }
11559 else if (isFactoryProvider(provider)) {
11560 factory = () => provider.useFactory(...injectArgs(provider.deps || []));
11561 }
11562 else if (isExistingProvider(provider)) {
11563 factory = () => ɵɵinject(resolveForwardRef(provider.useExisting));
11564 }
11565 else {
11566 const classRef = resolveForwardRef(provider &&
11567 (provider.useClass || provider.provide));
11568 if (ngDevMode && !classRef) {
11569 throwInvalidProviderError(ngModuleType, providers, provider);
11570 }
11571 if (hasDeps(provider)) {
11572 factory = () => new (classRef)(...injectArgs(provider.deps));
11573 }
11574 else {
11575 return getFactoryDef(classRef) || injectableDefOrInjectorDefFactory(classRef);
11576 }
11577 }
11578 }
11579 return factory;
11580}
11581function makeRecord(factory, value, multi = false) {
11582 return {
11583 factory: factory,
11584 value: value,
11585 multi: multi ? [] : undefined,
11586 };
11587}
11588function isValueProvider(value) {
11589 return value !== null && typeof value == 'object' && USE_VALUE$2 in value;
11590}
11591function isExistingProvider(value) {
11592 return !!(value && value.useExisting);
11593}
11594function isFactoryProvider(value) {
11595 return !!(value && value.useFactory);
11596}
11597function isTypeProvider(value) {
11598 return typeof value === 'function';
11599}
11600function isClassProvider(value) {
11601 return !!value.useClass;
11602}
11603function hasDeps(value) {
11604 return !!value.deps;
11605}
11606function hasOnDestroy(value) {
11607 return value !== null && typeof value === 'object' &&
11608 typeof value.ngOnDestroy === 'function';
11609}
11610function couldBeInjectableType(value) {
11611 return (typeof value === 'function') ||
11612 (typeof value === 'object' && value instanceof InjectionToken);
11613}
11614
11615/**
11616 * @license
11617 * Copyright Google LLC All Rights Reserved.
11618 *
11619 * Use of this source code is governed by an MIT-style license that can be
11620 * found in the LICENSE file at https://angular.io/license
11621 */
11622function INJECTOR_IMPL__PRE_R3__(providers, parent, name) {
11623 return new StaticInjector(providers, parent, name);
11624}
11625function INJECTOR_IMPL__POST_R3__(providers, parent, name) {
11626 return createInjector$1({ name: name }, parent, providers, name);
11627}
11628const INJECTOR_IMPL = INJECTOR_IMPL__POST_R3__;
11629/**
11630 * Concrete injectors implement this interface. Injectors are configured
11631 * with [providers](guide/glossary#provider) that associate
11632 * dependencies of various types with [injection tokens](guide/glossary#di-token).
11633 *
11634 * @see ["DI Providers"](guide/dependency-injection-providers).
11635 * @see `StaticProvider`
11636 *
11637 * @usageNotes
11638 *
11639 * The following example creates a service injector instance.
11640 *
11641 * {@example core/di/ts/provider_spec.ts region='ConstructorProvider'}
11642 *
11643 * ### Usage example
11644 *
11645 * {@example core/di/ts/injector_spec.ts region='Injector'}
11646 *
11647 * `Injector` returns itself when given `Injector` as a token:
11648 *
11649 * {@example core/di/ts/injector_spec.ts region='injectInjector'}
11650 *
11651 * @publicApi
11652 */
11653class Injector {
11654 static create(options, parent) {
11655 if (Array.isArray(options)) {
11656 return INJECTOR_IMPL(options, parent, '');
11657 }
11658 else {
11659 return INJECTOR_IMPL(options.providers, options.parent, options.name || '');
11660 }
11661 }
11662}
11663Injector.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
11664Injector.NULL = ( /* @__PURE__ */new NullInjector());
11665/** @nocollapse */
11666Injector.ɵprov = ɵɵdefineInjectable({
11667 token: Injector,
11668 providedIn: 'any',
11669 factory: () => ɵɵinject(INJECTOR),
11670});
11671/**
11672 * @internal
11673 * @nocollapse
11674 */
11675Injector.__NG_ELEMENT_ID__ = -1 /* Injector */;
11676const IDENT = function (value) {
11677 return value;
11678};
11679const EMPTY = [];
11680const CIRCULAR = IDENT;
11681const MULTI_PROVIDER_FN = function () {
11682 return Array.prototype.slice.call(arguments);
11683};
11684const NO_NEW_LINE = 'ɵ';
11685class StaticInjector {
11686 constructor(providers, parent = Injector.NULL, source = null) {
11687 this.parent = parent;
11688 this.source = source;
11689 const records = this._records = new Map();
11690 records.set(Injector, { token: Injector, fn: IDENT, deps: EMPTY, value: this, useNew: false });
11691 records.set(INJECTOR, { token: INJECTOR, fn: IDENT, deps: EMPTY, value: this, useNew: false });
11692 this.scope = recursivelyProcessProviders(records, providers);
11693 }
11694 get(token, notFoundValue, flags = InjectFlags.Default) {
11695 const records = this._records;
11696 let record = records.get(token);
11697 if (record === undefined) {
11698 // This means we have never seen this record, see if it is tree shakable provider.
11699 const injectableDef = getInjectableDef(token);
11700 if (injectableDef) {
11701 const providedIn = injectableDef && resolveForwardRef(injectableDef.providedIn);
11702 if (providedIn === 'any' || providedIn != null && providedIn === this.scope) {
11703 records.set(token, record = resolveProvider$1({ provide: token, useFactory: injectableDef.factory, deps: EMPTY }));
11704 }
11705 }
11706 if (record === undefined) {
11707 // Set record to null to make sure that we don't go through expensive lookup above again.
11708 records.set(token, null);
11709 }
11710 }
11711 let lastInjector = setCurrentInjector(this);
11712 try {
11713 return tryResolveToken(token, record, records, this.parent, notFoundValue, flags);
11714 }
11715 catch (e) {
11716 return catchInjectorError(e, token, 'StaticInjectorError', this.source);
11717 }
11718 finally {
11719 setCurrentInjector(lastInjector);
11720 }
11721 }
11722 toString() {
11723 const tokens = [], records = this._records;
11724 records.forEach((v, token) => tokens.push(stringify(token)));
11725 return `StaticInjector[${tokens.join(', ')}]`;
11726 }
11727}
11728function resolveProvider$1(provider) {
11729 const deps = computeDeps(provider);
11730 let fn = IDENT;
11731 let value = EMPTY;
11732 let useNew = false;
11733 let provide = resolveForwardRef(provider.provide);
11734 if (USE_VALUE$2 in provider) {
11735 // We need to use USE_VALUE in provider since provider.useValue could be defined as undefined.
11736 value = provider.useValue;
11737 }
11738 else if (provider.useFactory) {
11739 fn = provider.useFactory;
11740 }
11741 else if (provider.useExisting) {
11742 // Just use IDENT
11743 }
11744 else if (provider.useClass) {
11745 useNew = true;
11746 fn = resolveForwardRef(provider.useClass);
11747 }
11748 else if (typeof provide == 'function') {
11749 useNew = true;
11750 fn = provide;
11751 }
11752 else {
11753 throw staticError('StaticProvider does not have [useValue|useFactory|useExisting|useClass] or [provide] is not newable', provider);
11754 }
11755 return { deps, fn, useNew, value };
11756}
11757function multiProviderMixError(token) {
11758 return staticError('Cannot mix multi providers and regular providers', token);
11759}
11760function recursivelyProcessProviders(records, provider) {
11761 let scope = null;
11762 if (provider) {
11763 provider = resolveForwardRef(provider);
11764 if (Array.isArray(provider)) {
11765 // if we have an array recurse into the array
11766 for (let i = 0; i < provider.length; i++) {
11767 scope = recursivelyProcessProviders(records, provider[i]) || scope;
11768 }
11769 }
11770 else if (typeof provider === 'function') {
11771 // Functions were supported in ReflectiveInjector, but are not here. For safety give useful
11772 // error messages
11773 throw staticError('Function/Class not supported', provider);
11774 }
11775 else if (provider && typeof provider === 'object' && provider.provide) {
11776 // At this point we have what looks like a provider: {provide: ?, ....}
11777 let token = resolveForwardRef(provider.provide);
11778 const resolvedProvider = resolveProvider$1(provider);
11779 if (provider.multi === true) {
11780 // This is a multi provider.
11781 let multiProvider = records.get(token);
11782 if (multiProvider) {
11783 if (multiProvider.fn !== MULTI_PROVIDER_FN) {
11784 throw multiProviderMixError(token);
11785 }
11786 }
11787 else {
11788 // Create a placeholder factory which will look up the constituents of the multi provider.
11789 records.set(token, multiProvider = {
11790 token: provider.provide,
11791 deps: [],
11792 useNew: false,
11793 fn: MULTI_PROVIDER_FN,
11794 value: EMPTY
11795 });
11796 }
11797 // Treat the provider as the token.
11798 token = provider;
11799 multiProvider.deps.push({ token, options: 6 /* Default */ });
11800 }
11801 const record = records.get(token);
11802 if (record && record.fn == MULTI_PROVIDER_FN) {
11803 throw multiProviderMixError(token);
11804 }
11805 if (token === INJECTOR_SCOPE) {
11806 scope = resolvedProvider.value;
11807 }
11808 records.set(token, resolvedProvider);
11809 }
11810 else {
11811 throw staticError('Unexpected provider', provider);
11812 }
11813 }
11814 return scope;
11815}
11816function tryResolveToken(token, record, records, parent, notFoundValue, flags) {
11817 try {
11818 return resolveToken(token, record, records, parent, notFoundValue, flags);
11819 }
11820 catch (e) {
11821 // ensure that 'e' is of type Error.
11822 if (!(e instanceof Error)) {
11823 e = new Error(e);
11824 }
11825 const path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
11826 path.unshift(token);
11827 if (record && record.value == CIRCULAR) {
11828 // Reset the Circular flag.
11829 record.value = EMPTY;
11830 }
11831 throw e;
11832 }
11833}
11834function resolveToken(token, record, records, parent, notFoundValue, flags) {
11835 let value;
11836 if (record && !(flags & InjectFlags.SkipSelf)) {
11837 // If we don't have a record, this implies that we don't own the provider hence don't know how
11838 // to resolve it.
11839 value = record.value;
11840 if (value == CIRCULAR) {
11841 throw Error(NO_NEW_LINE + 'Circular dependency');
11842 }
11843 else if (value === EMPTY) {
11844 record.value = CIRCULAR;
11845 let obj = undefined;
11846 let useNew = record.useNew;
11847 let fn = record.fn;
11848 let depRecords = record.deps;
11849 let deps = EMPTY;
11850 if (depRecords.length) {
11851 deps = [];
11852 for (let i = 0; i < depRecords.length; i++) {
11853 const depRecord = depRecords[i];
11854 const options = depRecord.options;
11855 const childRecord = options & 2 /* CheckSelf */ ? records.get(depRecord.token) : undefined;
11856 deps.push(tryResolveToken(
11857 // Current Token to resolve
11858 depRecord.token,
11859 // A record which describes how to resolve the token.
11860 // If undefined, this means we don't have such a record
11861 childRecord,
11862 // Other records we know about.
11863 records,
11864 // If we don't know how to resolve dependency and we should not check parent for it,
11865 // than pass in Null injector.
11866 !childRecord && !(options & 4 /* CheckParent */) ? Injector.NULL : parent, options & 1 /* Optional */ ? null : Injector.THROW_IF_NOT_FOUND, InjectFlags.Default));
11867 }
11868 }
11869 record.value = value = useNew ? new fn(...deps) : fn.apply(obj, deps);
11870 }
11871 }
11872 else if (!(flags & InjectFlags.Self)) {
11873 value = parent.get(token, notFoundValue, InjectFlags.Default);
11874 }
11875 else if (!(flags & InjectFlags.Optional)) {
11876 value = Injector.NULL.get(token, notFoundValue);
11877 }
11878 else {
11879 value = Injector.NULL.get(token, typeof notFoundValue !== 'undefined' ? notFoundValue : null);
11880 }
11881 return value;
11882}
11883function computeDeps(provider) {
11884 let deps = EMPTY;
11885 const providerDeps = provider.deps;
11886 if (providerDeps && providerDeps.length) {
11887 deps = [];
11888 for (let i = 0; i < providerDeps.length; i++) {
11889 let options = 6 /* Default */;
11890 let token = resolveForwardRef(providerDeps[i]);
11891 if (Array.isArray(token)) {
11892 for (let j = 0, annotations = token; j < annotations.length; j++) {
11893 const annotation = annotations[j];
11894 if (annotation instanceof Optional || annotation == Optional) {
11895 options = options | 1 /* Optional */;
11896 }
11897 else if (annotation instanceof SkipSelf || annotation == SkipSelf) {
11898 options = options & ~2 /* CheckSelf */;
11899 }
11900 else if (annotation instanceof Self || annotation == Self) {
11901 options = options & ~4 /* CheckParent */;
11902 }
11903 else if (annotation instanceof Inject) {
11904 token = annotation.token;
11905 }
11906 else {
11907 token = resolveForwardRef(annotation);
11908 }
11909 }
11910 }
11911 deps.push({ token, options });
11912 }
11913 }
11914 else if (provider.useExisting) {
11915 const token = resolveForwardRef(provider.useExisting);
11916 deps = [{ token, options: 6 /* Default */ }];
11917 }
11918 else if (!providerDeps && !(USE_VALUE$2 in provider)) {
11919 // useValue & useExisting are the only ones which are exempt from deps all others need it.
11920 throw staticError('\'deps\' required', provider);
11921 }
11922 return deps;
11923}
11924function staticError(text, obj) {
11925 return new Error(formatError(text, obj, 'StaticInjectorError'));
11926}
11927
11928/**
11929 * @license
11930 * Copyright Google LLC All Rights Reserved.
11931 *
11932 * Use of this source code is governed by an MIT-style license that can be
11933 * found in the LICENSE file at https://angular.io/license
11934 */
11935/**
11936 * Retrieves the component instance associated with a given DOM element.
11937 *
11938 * @usageNotes
11939 * Given the following DOM structure:
11940 *
11941 * ```html
11942 * <app-root>
11943 * <div>
11944 * <child-comp></child-comp>
11945 * </div>
11946 * </app-root>
11947 * ```
11948 *
11949 * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
11950 * associated with this DOM element.
11951 *
11952 * Calling the function on `<app-root>` will return the `MyApp` instance.
11953 *
11954 *
11955 * @param element DOM element from which the component should be retrieved.
11956 * @returns Component instance associated with the element or `null` if there
11957 * is no component associated with it.
11958 *
11959 * @publicApi
11960 * @globalApi ng
11961 */
11962function getComponent$1(element) {
11963 assertDomElement(element);
11964 const context = getLContext(element);
11965 if (context === null)
11966 return null;
11967 if (context.component === undefined) {
11968 context.component = getComponentAtNodeIndex(context.nodeIndex, context.lView);
11969 }
11970 return context.component;
11971}
11972/**
11973 * If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded
11974 * view that the element is part of. Otherwise retrieves the instance of the component whose view
11975 * owns the element (in this case, the result is the same as calling `getOwningComponent`).
11976 *
11977 * @param element Element for which to get the surrounding component instance.
11978 * @returns Instance of the component that is around the element or null if the element isn't
11979 * inside any component.
11980 *
11981 * @publicApi
11982 * @globalApi ng
11983 */
11984function getContext(element) {
11985 assertDomElement(element);
11986 const context = getLContext(element);
11987 return context === null ? null : context.lView[CONTEXT];
11988}
11989/**
11990 * Retrieves the component instance whose view contains the DOM element.
11991 *
11992 * For example, if `<child-comp>` is used in the template of `<app-comp>`
11993 * (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>`
11994 * would return `<app-comp>`.
11995 *
11996 * @param elementOrDir DOM element, component or directive instance
11997 * for which to retrieve the root components.
11998 * @returns Component instance whose view owns the DOM element or null if the element is not
11999 * part of a component view.
12000 *
12001 * @publicApi
12002 * @globalApi ng
12003 */
12004function getOwningComponent(elementOrDir) {
12005 const context = getLContext(elementOrDir);
12006 if (context === null)
12007 return null;
12008 let lView = context.lView;
12009 let parent;
12010 ngDevMode && assertLView(lView);
12011 while (lView[TVIEW].type === 2 /* Embedded */ && (parent = getLViewParent(lView))) {
12012 lView = parent;
12013 }
12014 return lView[FLAGS] & 512 /* IsRoot */ ? null : lView[CONTEXT];
12015}
12016/**
12017 * Retrieves all root components associated with a DOM element, directive or component instance.
12018 * Root components are those which have been bootstrapped by Angular.
12019 *
12020 * @param elementOrDir DOM element, component or directive instance
12021 * for which to retrieve the root components.
12022 * @returns Root components associated with the target object.
12023 *
12024 * @publicApi
12025 * @globalApi ng
12026 */
12027function getRootComponents(elementOrDir) {
12028 return [...getRootContext(elementOrDir).components];
12029}
12030/**
12031 * Retrieves an `Injector` associated with an element, component or directive instance.
12032 *
12033 * @param elementOrDir DOM element, component or directive instance for which to
12034 * retrieve the injector.
12035 * @returns Injector associated with the element, component or directive instance.
12036 *
12037 * @publicApi
12038 * @globalApi ng
12039 */
12040function getInjector(elementOrDir) {
12041 const context = getLContext(elementOrDir);
12042 if (context === null)
12043 return Injector.NULL;
12044 const tNode = context.lView[TVIEW].data[context.nodeIndex];
12045 return new NodeInjector(tNode, context.lView);
12046}
12047/**
12048 * Retrieve a set of injection tokens at a given DOM node.
12049 *
12050 * @param element Element for which the injection tokens should be retrieved.
12051 */
12052function getInjectionTokens(element) {
12053 const context = getLContext(element);
12054 if (context === null)
12055 return [];
12056 const lView = context.lView;
12057 const tView = lView[TVIEW];
12058 const tNode = tView.data[context.nodeIndex];
12059 const providerTokens = [];
12060 const startIndex = tNode.providerIndexes & 1048575 /* ProvidersStartIndexMask */;
12061 const endIndex = tNode.directiveEnd;
12062 for (let i = startIndex; i < endIndex; i++) {
12063 let value = tView.data[i];
12064 if (isDirectiveDefHack(value)) {
12065 // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
12066 // design flaw. We should always store same type so that we can be monomorphic. The issue
12067 // is that for Components/Directives we store the def instead the type. The correct behavior
12068 // is that we should always be storing injectable type in this location.
12069 value = value.type;
12070 }
12071 providerTokens.push(value);
12072 }
12073 return providerTokens;
12074}
12075/**
12076 * Retrieves directive instances associated with a given DOM node. Does not include
12077 * component instances.
12078 *
12079 * @usageNotes
12080 * Given the following DOM structure:
12081 *
12082 * ```html
12083 * <app-root>
12084 * <button my-button></button>
12085 * <my-comp></my-comp>
12086 * </app-root>
12087 * ```
12088 *
12089 * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
12090 * directive that is associated with the DOM node.
12091 *
12092 * Calling `getDirectives` on `<my-comp>` will return an empty array.
12093 *
12094 * @param node DOM node for which to get the directives.
12095 * @returns Array of directives associated with the node.
12096 *
12097 * @publicApi
12098 * @globalApi ng
12099 */
12100function getDirectives(node) {
12101 // Skip text nodes because we can't have directives associated with them.
12102 if (node instanceof Text) {
12103 return [];
12104 }
12105 const context = getLContext(node);
12106 if (context === null) {
12107 return [];
12108 }
12109 const lView = context.lView;
12110 const tView = lView[TVIEW];
12111 const nodeIndex = context.nodeIndex;
12112 if (!tView?.data[nodeIndex]) {
12113 return [];
12114 }
12115 if (context.directives === undefined) {
12116 context.directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
12117 }
12118 // The `directives` in this case are a named array called `LComponentView`. Clone the
12119 // result so we don't expose an internal data structure in the user's console.
12120 return context.directives === null ? [] : [...context.directives];
12121}
12122/**
12123 * Returns the debug (partial) metadata for a particular directive or component instance.
12124 * The function accepts an instance of a directive or component and returns the corresponding
12125 * metadata.
12126 *
12127 * @param directiveOrComponentInstance Instance of a directive or component
12128 * @returns metadata of the passed directive or component
12129 *
12130 * @publicApi
12131 * @globalApi ng
12132 */
12133function getDirectiveMetadata$1(directiveOrComponentInstance) {
12134 const { constructor } = directiveOrComponentInstance;
12135 if (!constructor) {
12136 throw new Error('Unable to find the instance constructor');
12137 }
12138 // In case a component inherits from a directive, we may have component and directive metadata
12139 // To ensure we don't get the metadata of the directive, we want to call `getComponentDef` first.
12140 const componentDef = getComponentDef(constructor);
12141 if (componentDef) {
12142 return {
12143 inputs: componentDef.inputs,
12144 outputs: componentDef.outputs,
12145 encapsulation: componentDef.encapsulation,
12146 changeDetection: componentDef.onPush ? ChangeDetectionStrategy.OnPush :
12147 ChangeDetectionStrategy.Default
12148 };
12149 }
12150 const directiveDef = getDirectiveDef(constructor);
12151 if (directiveDef) {
12152 return { inputs: directiveDef.inputs, outputs: directiveDef.outputs };
12153 }
12154 return null;
12155}
12156/**
12157 * Retrieve map of local references.
12158 *
12159 * The references are retrieved as a map of local reference name to element or directive instance.
12160 *
12161 * @param target DOM element, component or directive instance for which to retrieve
12162 * the local references.
12163 */
12164function getLocalRefs(target) {
12165 const context = getLContext(target);
12166 if (context === null)
12167 return {};
12168 if (context.localRefs === undefined) {
12169 context.localRefs = discoverLocalRefs(context.lView, context.nodeIndex);
12170 }
12171 return context.localRefs || {};
12172}
12173/**
12174 * Retrieves the host element of a component or directive instance.
12175 * The host element is the DOM element that matched the selector of the directive.
12176 *
12177 * @param componentOrDirective Component or directive instance for which the host
12178 * element should be retrieved.
12179 * @returns Host element of the target.
12180 *
12181 * @publicApi
12182 * @globalApi ng
12183 */
12184function getHostElement(componentOrDirective) {
12185 return getLContext(componentOrDirective).native;
12186}
12187/**
12188 * Retrieves the rendered text for a given component.
12189 *
12190 * This function retrieves the host element of a component and
12191 * and then returns the `textContent` for that element. This implies
12192 * that the text returned will include re-projected content of
12193 * the component as well.
12194 *
12195 * @param component The component to return the content text for.
12196 */
12197function getRenderedText(component) {
12198 const hostElement = getHostElement(component);
12199 return hostElement.textContent || '';
12200}
12201/**
12202 * Retrieves a list of event listeners associated with a DOM element. The list does include host
12203 * listeners, but it does not include event listeners defined outside of the Angular context
12204 * (e.g. through `addEventListener`).
12205 *
12206 * @usageNotes
12207 * Given the following DOM structure:
12208 *
12209 * ```html
12210 * <app-root>
12211 * <div (click)="doSomething()"></div>
12212 * </app-root>
12213 * ```
12214 *
12215 * Calling `getListeners` on `<div>` will return an object that looks as follows:
12216 *
12217 * ```ts
12218 * {
12219 * name: 'click',
12220 * element: <div>,
12221 * callback: () => doSomething(),
12222 * useCapture: false
12223 * }
12224 * ```
12225 *
12226 * @param element Element for which the DOM listeners should be retrieved.
12227 * @returns Array of event listeners on the DOM element.
12228 *
12229 * @publicApi
12230 * @globalApi ng
12231 */
12232function getListeners(element) {
12233 assertDomElement(element);
12234 const lContext = getLContext(element);
12235 if (lContext === null)
12236 return [];
12237 const lView = lContext.lView;
12238 const tView = lView[TVIEW];
12239 const lCleanup = lView[CLEANUP];
12240 const tCleanup = tView.cleanup;
12241 const listeners = [];
12242 if (tCleanup && lCleanup) {
12243 for (let i = 0; i < tCleanup.length;) {
12244 const firstParam = tCleanup[i++];
12245 const secondParam = tCleanup[i++];
12246 if (typeof firstParam === 'string') {
12247 const name = firstParam;
12248 const listenerElement = unwrapRNode(lView[secondParam]);
12249 const callback = lCleanup[tCleanup[i++]];
12250 const useCaptureOrIndx = tCleanup[i++];
12251 // if useCaptureOrIndx is boolean then report it as is.
12252 // if useCaptureOrIndx is positive number then it in unsubscribe method
12253 // if useCaptureOrIndx is negative number then it is a Subscription
12254 const type = (typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0) ? 'dom' : 'output';
12255 const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
12256 if (element == listenerElement) {
12257 listeners.push({ element, name, callback, useCapture, type });
12258 }
12259 }
12260 }
12261 }
12262 listeners.sort(sortListeners);
12263 return listeners;
12264}
12265function sortListeners(a, b) {
12266 if (a.name == b.name)
12267 return 0;
12268 return a.name < b.name ? -1 : 1;
12269}
12270/**
12271 * This function should not exist because it is megamorphic and only mostly correct.
12272 *
12273 * See call site for more info.
12274 */
12275function isDirectiveDefHack(obj) {
12276 return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
12277}
12278/**
12279 * Returns the attached `DebugNode` instance for an element in the DOM.
12280 *
12281 * @param element DOM element which is owned by an existing component's view.
12282 */
12283function getDebugNode$1(element) {
12284 if (ngDevMode && !(element instanceof Node)) {
12285 throw new Error('Expecting instance of DOM Element');
12286 }
12287 const lContext = getLContext(element);
12288 if (lContext === null) {
12289 return null;
12290 }
12291 const lView = lContext.lView;
12292 const nodeIndex = lContext.nodeIndex;
12293 if (nodeIndex !== -1) {
12294 const valueInLView = lView[nodeIndex];
12295 // this means that value in the lView is a component with its own
12296 // data. In this situation the TNode is not accessed at the same spot.
12297 const tNode = isLView(valueInLView) ? valueInLView[T_HOST] : getTNode(lView[TVIEW], nodeIndex);
12298 ngDevMode &&
12299 assertEqual(tNode.index, nodeIndex, 'Expecting that TNode at index is same as index');
12300 return buildDebugNode(tNode, lView);
12301 }
12302 return null;
12303}
12304/**
12305 * Retrieve the component `LView` from component/element.
12306 *
12307 * NOTE: `LView` is a private and should not be leaked outside.
12308 * Don't export this method to `ng.*` on window.
12309 *
12310 * @param target DOM element or component instance for which to retrieve the LView.
12311 */
12312function getComponentLView(target) {
12313 const lContext = getLContext(target);
12314 const nodeIndx = lContext.nodeIndex;
12315 const lView = lContext.lView;
12316 const componentLView = lView[nodeIndx];
12317 ngDevMode && assertLView(componentLView);
12318 return componentLView;
12319}
12320/** Asserts that a value is a DOM Element. */
12321function assertDomElement(value) {
12322 if (typeof Element !== 'undefined' && !(value instanceof Element)) {
12323 throw new Error('Expecting instance of DOM Element');
12324 }
12325}
12326
12327/**
12328 * @license
12329 * Copyright Google LLC All Rights Reserved.
12330 *
12331 * Use of this source code is governed by an MIT-style license that can be
12332 * found in the LICENSE file at https://angular.io/license
12333 */
12334/**
12335 * Marks a component for check (in case of OnPush components) and synchronously
12336 * performs change detection on the application this component belongs to.
12337 *
12338 * @param component Component to {@link ChangeDetectorRef#markForCheck mark for check}.
12339 *
12340 * @publicApi
12341 * @globalApi ng
12342 */
12343function applyChanges(component) {
12344 markDirty(component);
12345 getRootComponents(component).forEach(rootComponent => detectChanges(rootComponent));
12346}
12347
12348/**
12349 * @license
12350 * Copyright Google LLC All Rights Reserved.
12351 *
12352 * Use of this source code is governed by an MIT-style license that can be
12353 * found in the LICENSE file at https://angular.io/license
12354 */
12355/**
12356 * This file introduces series of globally accessible debug tools
12357 * to allow for the Angular debugging story to function.
12358 *
12359 * To see this in action run the following command:
12360 *
12361 * bazel run //packages/core/test/bundling/todo:devserver
12362 *
12363 * Then load `localhost:5432` and start using the console tools.
12364 */
12365/**
12366 * This value reflects the property on the window where the dev
12367 * tools are patched (window.ng).
12368 * */
12369const GLOBAL_PUBLISH_EXPANDO_KEY = 'ng';
12370let _published = false;
12371/**
12372 * Publishes a collection of default debug tools onto`window.ng`.
12373 *
12374 * These functions are available globally when Angular is in development
12375 * mode and are automatically stripped away from prod mode is on.
12376 */
12377function publishDefaultGlobalUtils$1() {
12378 if (!_published) {
12379 _published = true;
12380 /**
12381 * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
12382 * The contract of the function might be changed in any release and/or the function can be
12383 * removed completely.
12384 */
12385 publishGlobalUtil('ɵsetProfiler', setProfiler);
12386 publishGlobalUtil('getDirectiveMetadata', getDirectiveMetadata$1);
12387 publishGlobalUtil('getComponent', getComponent$1);
12388 publishGlobalUtil('getContext', getContext);
12389 publishGlobalUtil('getListeners', getListeners);
12390 publishGlobalUtil('getOwningComponent', getOwningComponent);
12391 publishGlobalUtil('getHostElement', getHostElement);
12392 publishGlobalUtil('getInjector', getInjector);
12393 publishGlobalUtil('getRootComponents', getRootComponents);
12394 publishGlobalUtil('getDirectives', getDirectives);
12395 publishGlobalUtil('applyChanges', applyChanges);
12396 }
12397}
12398/**
12399 * Publishes the given function to `window.ng` so that it can be
12400 * used from the browser console when an application is not in production.
12401 */
12402function publishGlobalUtil(name, fn) {
12403 if (typeof COMPILED === 'undefined' || !COMPILED) {
12404 // Note: we can't export `ng` when using closure enhanced optimization as:
12405 // - closure declares globals itself for minified names, which sometimes clobber our `ng` global
12406 // - we can't declare a closure extern as the namespace `ng` is already used within Google
12407 // for typings for AngularJS (via `goog.provide('ng....')`).
12408 const w = _global;
12409 ngDevMode && assertDefined(fn, 'function not defined');
12410 if (w) {
12411 let container = w[GLOBAL_PUBLISH_EXPANDO_KEY];
12412 if (!container) {
12413 container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {};
12414 }
12415 container[name] = fn;
12416 }
12417 }
12418}
12419
12420/**
12421 * @license
12422 * Copyright Google LLC All Rights Reserved.
12423 *
12424 * Use of this source code is governed by an MIT-style license that can be
12425 * found in the LICENSE file at https://angular.io/license
12426 */
12427// TODO: A hack to not pull in the NullInjector from @angular/core.
12428const NULL_INJECTOR = {
12429 get: (token, notFoundValue) => {
12430 throwProviderNotFoundError(token, 'NullInjector');
12431 }
12432};
12433/**
12434 * Bootstraps a Component into an existing host element and returns an instance
12435 * of the component.
12436 *
12437 * Use this function to bootstrap a component into the DOM tree. Each invocation
12438 * of this function will create a separate tree of components, injectors and
12439 * change detection cycles and lifetimes. To dynamically insert a new component
12440 * into an existing tree such that it shares the same injection, change detection
12441 * and object lifetime, use {@link ViewContainer#createComponent}.
12442 *
12443 * @param componentType Component to bootstrap
12444 * @param options Optional parameters which control bootstrapping
12445 */
12446function renderComponent(componentType /* Type as workaround for: Microsoft/TypeScript/issues/4881 */, opts = {}) {
12447 ngDevMode && publishDefaultGlobalUtils$1();
12448 ngDevMode && assertComponentType(componentType);
12449 const rendererFactory = opts.rendererFactory || domRendererFactory3;
12450 const sanitizer = opts.sanitizer || null;
12451 const componentDef = getComponentDef(componentType);
12452 if (componentDef.type != componentType)
12453 componentDef.type = componentType;
12454 // The first index of the first selector is the tag name.
12455 const componentTag = componentDef.selectors[0][0];
12456 const hostRenderer = rendererFactory.createRenderer(null, null);
12457 const hostRNode = locateHostElement(hostRenderer, opts.host || componentTag, componentDef.encapsulation);
12458 const rootFlags = componentDef.onPush ? 64 /* Dirty */ | 512 /* IsRoot */ :
12459 16 /* CheckAlways */ | 512 /* IsRoot */;
12460 const rootContext = createRootContext(opts.scheduler, opts.playerHandler);
12461 const renderer = rendererFactory.createRenderer(hostRNode, componentDef);
12462 const rootTView = createTView(0 /* Root */, null, null, 1, 0, null, null, null, null, null);
12463 const rootView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, null, opts.injector || null);
12464 enterView(rootView);
12465 let component;
12466 try {
12467 if (rendererFactory.begin)
12468 rendererFactory.begin();
12469 const componentView = createRootComponentView(hostRNode, componentDef, rootView, rendererFactory, renderer, sanitizer);
12470 component = createRootComponent(componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
12471 // create mode pass
12472 renderView(rootTView, rootView, null);
12473 // update mode pass
12474 refreshView(rootTView, rootView, null, null);
12475 }
12476 finally {
12477 leaveView();
12478 if (rendererFactory.end)
12479 rendererFactory.end();
12480 }
12481 return component;
12482}
12483/**
12484 * Creates the root component view and the root component node.
12485 *
12486 * @param rNode Render host element.
12487 * @param def ComponentDef
12488 * @param rootView The parent view where the host node is stored
12489 * @param rendererFactory Factory to be used for creating child renderers.
12490 * @param hostRenderer The current renderer
12491 * @param sanitizer The sanitizer, if provided
12492 *
12493 * @returns Component view created
12494 */
12495function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) {
12496 const tView = rootView[TVIEW];
12497 const index = HEADER_OFFSET;
12498 ngDevMode && assertIndexInRange(rootView, index);
12499 rootView[index] = rNode;
12500 // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at
12501 // the same time we want to communicate the debug `TNode` that this is a special `TNode`
12502 // representing a host element.
12503 const tNode = getOrCreateTNode(tView, index, 2 /* Element */, '#host', null);
12504 const mergedAttrs = tNode.mergedAttrs = def.hostAttrs;
12505 if (mergedAttrs !== null) {
12506 computeStaticStyling(tNode, mergedAttrs, true);
12507 if (rNode !== null) {
12508 setUpAttributes(hostRenderer, rNode, mergedAttrs);
12509 if (tNode.classes !== null) {
12510 writeDirectClass(hostRenderer, rNode, tNode.classes);
12511 }
12512 if (tNode.styles !== null) {
12513 writeDirectStyle(hostRenderer, rNode, tNode.styles);
12514 }
12515 }
12516 }
12517 const viewRenderer = rendererFactory.createRenderer(rNode, def);
12518 const componentView = createLView(rootView, getOrCreateTComponentView(def), null, def.onPush ? 64 /* Dirty */ : 16 /* CheckAlways */, rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null);
12519 if (tView.firstCreatePass) {
12520 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
12521 markAsComponentHost(tView, tNode);
12522 initTNodeFlags(tNode, rootView.length, 1);
12523 }
12524 addToViewTree(rootView, componentView);
12525 // Store component view at node index, with node as the HOST
12526 return rootView[index] = componentView;
12527}
12528/**
12529 * Creates a root component and sets it up with features and host bindings. Shared by
12530 * renderComponent() and ViewContainerRef.createComponent().
12531 */
12532function createRootComponent(componentView, componentDef, rootLView, rootContext, hostFeatures) {
12533 const tView = rootLView[TVIEW];
12534 // Create directive instance with factory() and store at next index in viewData
12535 const component = instantiateRootComponent(tView, rootLView, componentDef);
12536 rootContext.components.push(component);
12537 componentView[CONTEXT] = component;
12538 hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
12539 // We want to generate an empty QueryList for root content queries for backwards
12540 // compatibility with ViewEngine.
12541 if (componentDef.contentQueries) {
12542 const tNode = getCurrentTNode();
12543 ngDevMode && assertDefined(tNode, 'TNode expected');
12544 componentDef.contentQueries(1 /* Create */, component, tNode.directiveStart);
12545 }
12546 const rootTNode = getCurrentTNode();
12547 ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');
12548 if (tView.firstCreatePass &&
12549 (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
12550 setSelectedIndex(rootTNode.index);
12551 const rootTView = rootLView[TVIEW];
12552 registerHostBindingOpCodes(rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, componentDef);
12553 invokeHostBindingsInCreationMode(componentDef, component);
12554 }
12555 return component;
12556}
12557function createRootContext(scheduler, playerHandler) {
12558 return {
12559 components: [],
12560 scheduler: scheduler || defaultScheduler,
12561 clean: CLEAN_PROMISE,
12562 playerHandler: playerHandler || null,
12563 flags: 0 /* Empty */
12564 };
12565}
12566/**
12567 * Used to enable lifecycle hooks on the root component.
12568 *
12569 * Include this feature when calling `renderComponent` if the root component
12570 * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't
12571 * be called properly.
12572 *
12573 * Example:
12574 *
12575 * ```
12576 * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
12577 * ```
12578 */
12579function LifecycleHooksFeature(component, def) {
12580 const lView = readPatchedLView(component);
12581 ngDevMode && assertDefined(lView, 'LView is required');
12582 const tView = lView[TVIEW];
12583 const tNode = getCurrentTNode();
12584 ngDevMode && assertDefined(tNode, 'TNode is required');
12585 registerPostOrderHooks(tView, tNode);
12586}
12587/**
12588 * Wait on component until it is rendered.
12589 *
12590 * This function returns a `Promise` which is resolved when the component's
12591 * change detection is executed. This is determined by finding the scheduler
12592 * associated with the `component`'s render tree and waiting until the scheduler
12593 * flushes. If nothing is scheduled, the function returns a resolved promise.
12594 *
12595 * Example:
12596 * ```
12597 * await whenRendered(myComponent);
12598 * ```
12599 *
12600 * @param component Component to wait upon
12601 * @returns Promise which resolves when the component is rendered.
12602 */
12603function whenRendered(component) {
12604 return getRootContext(component).clean;
12605}
12606
12607/**
12608 * @license
12609 * Copyright Google LLC All Rights Reserved.
12610 *
12611 * Use of this source code is governed by an MIT-style license that can be
12612 * found in the LICENSE file at https://angular.io/license
12613 */
12614function getSuperType(type) {
12615 return Object.getPrototypeOf(type.prototype).constructor;
12616}
12617/**
12618 * Merges the definition from a super class to a sub class.
12619 * @param definition The definition that is a SubClass of another directive of component
12620 *
12621 * @codeGenApi
12622 */
12623function ɵɵInheritDefinitionFeature(definition) {
12624 let superType = getSuperType(definition.type);
12625 let shouldInheritFields = true;
12626 const inheritanceChain = [definition];
12627 while (superType) {
12628 let superDef = undefined;
12629 if (isComponentDef(definition)) {
12630 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12631 superDef = superType.ɵcmp || superType.ɵdir;
12632 }
12633 else {
12634 if (superType.ɵcmp) {
12635 throw new Error('Directives cannot inherit Components');
12636 }
12637 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12638 superDef = superType.ɵdir;
12639 }
12640 if (superDef) {
12641 if (shouldInheritFields) {
12642 inheritanceChain.push(superDef);
12643 // Some fields in the definition may be empty, if there were no values to put in them that
12644 // would've justified object creation. Unwrap them if necessary.
12645 const writeableDef = definition;
12646 writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
12647 writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
12648 writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
12649 // Merge hostBindings
12650 const superHostBindings = superDef.hostBindings;
12651 superHostBindings && inheritHostBindings(definition, superHostBindings);
12652 // Merge queries
12653 const superViewQuery = superDef.viewQuery;
12654 const superContentQueries = superDef.contentQueries;
12655 superViewQuery && inheritViewQuery(definition, superViewQuery);
12656 superContentQueries && inheritContentQueries(definition, superContentQueries);
12657 // Merge inputs and outputs
12658 fillProperties(definition.inputs, superDef.inputs);
12659 fillProperties(definition.declaredInputs, superDef.declaredInputs);
12660 fillProperties(definition.outputs, superDef.outputs);
12661 // Merge animations metadata.
12662 // If `superDef` is a Component, the `data` field is present (defaults to an empty object).
12663 if (isComponentDef(superDef) && superDef.data.animation) {
12664 // If super def is a Component, the `definition` is also a Component, since Directives can
12665 // not inherit Components (we throw an error above and cannot reach this code).
12666 const defData = definition.data;
12667 defData.animation = (defData.animation || []).concat(superDef.data.animation);
12668 }
12669 }
12670 // Run parent features
12671 const features = superDef.features;
12672 if (features) {
12673 for (let i = 0; i < features.length; i++) {
12674 const feature = features[i];
12675 if (feature && feature.ngInherit) {
12676 feature(definition);
12677 }
12678 // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
12679 // def already has all the necessary information inherited from its super class(es), so we
12680 // can stop merging fields from super classes. However we need to iterate through the
12681 // prototype chain to look for classes that might contain other "features" (like
12682 // NgOnChanges), which we should invoke for the original `definition`. We set the
12683 // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
12684 // logic and only invoking functions from the "features" list.
12685 if (feature === ɵɵInheritDefinitionFeature) {
12686 shouldInheritFields = false;
12687 }
12688 }
12689 }
12690 }
12691 superType = Object.getPrototypeOf(superType);
12692 }
12693 mergeHostAttrsAcrossInheritance(inheritanceChain);
12694}
12695/**
12696 * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.
12697 *
12698 * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing
12699 * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child
12700 * type.
12701 */
12702function mergeHostAttrsAcrossInheritance(inheritanceChain) {
12703 let hostVars = 0;
12704 let hostAttrs = null;
12705 // We process the inheritance order from the base to the leaves here.
12706 for (let i = inheritanceChain.length - 1; i >= 0; i--) {
12707 const def = inheritanceChain[i];
12708 // For each `hostVars`, we need to add the superclass amount.
12709 def.hostVars = (hostVars += def.hostVars);
12710 // for each `hostAttrs` we need to merge it with superclass.
12711 def.hostAttrs =
12712 mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
12713 }
12714}
12715function maybeUnwrapEmpty(value) {
12716 if (value === EMPTY_OBJ) {
12717 return {};
12718 }
12719 else if (value === EMPTY_ARRAY) {
12720 return [];
12721 }
12722 else {
12723 return value;
12724 }
12725}
12726function inheritViewQuery(definition, superViewQuery) {
12727 const prevViewQuery = definition.viewQuery;
12728 if (prevViewQuery) {
12729 definition.viewQuery = (rf, ctx) => {
12730 superViewQuery(rf, ctx);
12731 prevViewQuery(rf, ctx);
12732 };
12733 }
12734 else {
12735 definition.viewQuery = superViewQuery;
12736 }
12737}
12738function inheritContentQueries(definition, superContentQueries) {
12739 const prevContentQueries = definition.contentQueries;
12740 if (prevContentQueries) {
12741 definition.contentQueries = (rf, ctx, directiveIndex) => {
12742 superContentQueries(rf, ctx, directiveIndex);
12743 prevContentQueries(rf, ctx, directiveIndex);
12744 };
12745 }
12746 else {
12747 definition.contentQueries = superContentQueries;
12748 }
12749}
12750function inheritHostBindings(definition, superHostBindings) {
12751 const prevHostBindings = definition.hostBindings;
12752 if (prevHostBindings) {
12753 definition.hostBindings = (rf, ctx) => {
12754 superHostBindings(rf, ctx);
12755 prevHostBindings(rf, ctx);
12756 };
12757 }
12758 else {
12759 definition.hostBindings = superHostBindings;
12760 }
12761}
12762
12763/**
12764 * @license
12765 * Copyright Google LLC All Rights Reserved.
12766 *
12767 * Use of this source code is governed by an MIT-style license that can be
12768 * found in the LICENSE file at https://angular.io/license
12769 */
12770/**
12771 * Fields which exist on either directive or component definitions, and need to be copied from
12772 * parent to child classes by the `ɵɵCopyDefinitionFeature`.
12773 */
12774const COPY_DIRECTIVE_FIELDS = [
12775 // The child class should use the providers of its parent.
12776 'providersResolver',
12777 // Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
12778 // as inputs, outputs, and host binding functions.
12779];
12780/**
12781 * Fields which exist only on component definitions, and need to be copied from parent to child
12782 * classes by the `ɵɵCopyDefinitionFeature`.
12783 *
12784 * The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
12785 * since those should go in `COPY_DIRECTIVE_FIELDS` above.
12786 */
12787const COPY_COMPONENT_FIELDS = [
12788 // The child class should use the template function of its parent, including all template
12789 // semantics.
12790 'template',
12791 'decls',
12792 'consts',
12793 'vars',
12794 'onPush',
12795 'ngContentSelectors',
12796 // The child class should use the CSS styles of its parent, including all styling semantics.
12797 'styles',
12798 'encapsulation',
12799 // The child class should be checked by the runtime in the same way as its parent.
12800 'schemas',
12801];
12802/**
12803 * Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a
12804 * definition.
12805 *
12806 * This exists primarily to support ngcc migration of an existing View Engine pattern, where an
12807 * entire decorator is inherited from a parent to a child class. When ngcc detects this case, it
12808 * generates a skeleton definition on the child class, and applies this feature.
12809 *
12810 * The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition,
12811 * including things like the component template function.
12812 *
12813 * @param definition The definition of a child class which inherits from a parent class with its
12814 * own definition.
12815 *
12816 * @codeGenApi
12817 */
12818function ɵɵCopyDefinitionFeature(definition) {
12819 let superType = getSuperType(definition.type);
12820 let superDef = undefined;
12821 if (isComponentDef(definition)) {
12822 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12823 superDef = superType.ɵcmp;
12824 }
12825 else {
12826 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12827 superDef = superType.ɵdir;
12828 }
12829 // Needed because `definition` fields are readonly.
12830 const defAny = definition;
12831 // Copy over any fields that apply to either directives or components.
12832 for (const field of COPY_DIRECTIVE_FIELDS) {
12833 defAny[field] = superDef[field];
12834 }
12835 if (isComponentDef(superDef)) {
12836 // Copy over any component-specific fields.
12837 for (const field of COPY_COMPONENT_FIELDS) {
12838 defAny[field] = superDef[field];
12839 }
12840 }
12841}
12842
12843/**
12844 * @license
12845 * Copyright Google LLC All Rights Reserved.
12846 *
12847 * Use of this source code is governed by an MIT-style license that can be
12848 * found in the LICENSE file at https://angular.io/license
12849 */
12850let _symbolIterator = null;
12851function getSymbolIterator() {
12852 if (!_symbolIterator) {
12853 const Symbol = _global['Symbol'];
12854 if (Symbol && Symbol.iterator) {
12855 _symbolIterator = Symbol.iterator;
12856 }
12857 else {
12858 // es6-shim specific logic
12859 const keys = Object.getOwnPropertyNames(Map.prototype);
12860 for (let i = 0; i < keys.length; ++i) {
12861 const key = keys[i];
12862 if (key !== 'entries' && key !== 'size' &&
12863 Map.prototype[key] === Map.prototype['entries']) {
12864 _symbolIterator = key;
12865 }
12866 }
12867 }
12868 }
12869 return _symbolIterator;
12870}
12871
12872/**
12873 * @license
12874 * Copyright Google LLC All Rights Reserved.
12875 *
12876 * Use of this source code is governed by an MIT-style license that can be
12877 * found in the LICENSE file at https://angular.io/license
12878 */
12879function devModeEqual(a, b) {
12880 const isListLikeIterableA = isListLikeIterable(a);
12881 const isListLikeIterableB = isListLikeIterable(b);
12882 if (isListLikeIterableA && isListLikeIterableB) {
12883 return areIterablesEqual(a, b, devModeEqual);
12884 }
12885 else {
12886 const isAObject = a && (typeof a === 'object' || typeof a === 'function');
12887 const isBObject = b && (typeof b === 'object' || typeof b === 'function');
12888 if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
12889 return true;
12890 }
12891 else {
12892 return Object.is(a, b);
12893 }
12894 }
12895}
12896function isListLikeIterable(obj) {
12897 if (!isJsObject(obj))
12898 return false;
12899 return Array.isArray(obj) ||
12900 (!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
12901 getSymbolIterator() in obj); // JS Iterable have a Symbol.iterator prop
12902}
12903function areIterablesEqual(a, b, comparator) {
12904 const iterator1 = a[getSymbolIterator()]();
12905 const iterator2 = b[getSymbolIterator()]();
12906 while (true) {
12907 const item1 = iterator1.next();
12908 const item2 = iterator2.next();
12909 if (item1.done && item2.done)
12910 return true;
12911 if (item1.done || item2.done)
12912 return false;
12913 if (!comparator(item1.value, item2.value))
12914 return false;
12915 }
12916}
12917function iterateListLike(obj, fn) {
12918 if (Array.isArray(obj)) {
12919 for (let i = 0; i < obj.length; i++) {
12920 fn(obj[i]);
12921 }
12922 }
12923 else {
12924 const iterator = obj[getSymbolIterator()]();
12925 let item;
12926 while (!((item = iterator.next()).done)) {
12927 fn(item.value);
12928 }
12929 }
12930}
12931function isJsObject(o) {
12932 return o !== null && (typeof o === 'function' || typeof o === 'object');
12933}
12934
12935/**
12936 * @license
12937 * Copyright Google LLC All Rights Reserved.
12938 *
12939 * Use of this source code is governed by an MIT-style license that can be
12940 * found in the LICENSE file at https://angular.io/license
12941 */
12942// TODO(misko): consider inlining
12943/** Updates binding and returns the value. */
12944function updateBinding(lView, bindingIndex, value) {
12945 return lView[bindingIndex] = value;
12946}
12947/** Gets the current binding value. */
12948function getBinding(lView, bindingIndex) {
12949 ngDevMode && assertIndexInRange(lView, bindingIndex);
12950 ngDevMode &&
12951 assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
12952 return lView[bindingIndex];
12953}
12954/**
12955 * Updates binding if changed, then returns whether it was updated.
12956 *
12957 * This function also checks the `CheckNoChangesMode` and throws if changes are made.
12958 * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
12959 * behavior.
12960 *
12961 * @param lView current `LView`
12962 * @param bindingIndex The binding in the `LView` to check
12963 * @param value New value to check against `lView[bindingIndex]`
12964 * @returns `true` if the bindings has changed. (Throws if binding has changed during
12965 * `CheckNoChangesMode`)
12966 */
12967function bindingUpdated(lView, bindingIndex, value) {
12968 ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
12969 ngDevMode &&
12970 assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
12971 const oldValue = lView[bindingIndex];
12972 if (Object.is(oldValue, value)) {
12973 return false;
12974 }
12975 else {
12976 if (ngDevMode && isInCheckNoChangesMode()) {
12977 // View engine didn't report undefined values as changed on the first checkNoChanges pass
12978 // (before the change detection was run).
12979 const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
12980 if (!devModeEqual(oldValueToCompare, value)) {
12981 const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
12982 throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);
12983 }
12984 // There was a change, but the `devModeEqual` decided that the change is exempt from an error.
12985 // For this reason we exit as if no change. The early exit is needed to prevent the changed
12986 // value to be written into `LView` (If we would write the new value that we would not see it
12987 // as change on next CD.)
12988 return false;
12989 }
12990 lView[bindingIndex] = value;
12991 return true;
12992 }
12993}
12994/** Updates 2 bindings if changed, then returns whether either was updated. */
12995function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
12996 const different = bindingUpdated(lView, bindingIndex, exp1);
12997 return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
12998}
12999/** Updates 3 bindings if changed, then returns whether any was updated. */
13000function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
13001 const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
13002 return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
13003}
13004/** Updates 4 bindings if changed, then returns whether any was updated. */
13005function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
13006 const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
13007 return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
13008}
13009
13010/**
13011 * @license
13012 * Copyright Google LLC All Rights Reserved.
13013 *
13014 * Use of this source code is governed by an MIT-style license that can be
13015 * found in the LICENSE file at https://angular.io/license
13016 */
13017/**
13018 * Updates the value of or removes a bound attribute on an Element.
13019 *
13020 * Used in the case of `[attr.title]="value"`
13021 *
13022 * @param name name The name of the attribute.
13023 * @param value value The attribute is removed when value is `null` or `undefined`.
13024 * Otherwise the attribute value is set to the stringified value.
13025 * @param sanitizer An optional function used to sanitize the value.
13026 * @param namespace Optional namespace to use when setting the attribute.
13027 *
13028 * @codeGenApi
13029 */
13030function ɵɵattribute(name, value, sanitizer, namespace) {
13031 const lView = getLView();
13032 const bindingIndex = nextBindingIndex();
13033 if (bindingUpdated(lView, bindingIndex, value)) {
13034 const tView = getTView();
13035 const tNode = getSelectedTNode();
13036 elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
13037 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
13038 }
13039 return ɵɵattribute;
13040}
13041
13042/**
13043 * @license
13044 * Copyright Google LLC All Rights Reserved.
13045 *
13046 * Use of this source code is governed by an MIT-style license that can be
13047 * found in the LICENSE file at https://angular.io/license
13048 */
13049/**
13050 * Create interpolation bindings with a variable number of expressions.
13051 *
13052 * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
13053 * Those are faster because there is no need to create an array of expressions and iterate over it.
13054 *
13055 * `values`:
13056 * - has static text at even indexes,
13057 * - has evaluated expressions at odd indexes.
13058 *
13059 * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
13060 */
13061function interpolationV(lView, values) {
13062 ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
13063 ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
13064 let isBindingUpdated = false;
13065 let bindingIndex = getBindingIndex();
13066 for (let i = 1; i < values.length; i += 2) {
13067 // Check if bindings (odd indexes) have changed
13068 isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
13069 }
13070 setBindingIndex(bindingIndex);
13071 if (!isBindingUpdated) {
13072 return NO_CHANGE;
13073 }
13074 // Build the updated content
13075 let content = values[0];
13076 for (let i = 1; i < values.length; i += 2) {
13077 content += renderStringify(values[i]) + values[i + 1];
13078 }
13079 return content;
13080}
13081/**
13082 * Creates an interpolation binding with 1 expression.
13083 *
13084 * @param prefix static value used for concatenation only.
13085 * @param v0 value checked for change.
13086 * @param suffix static value used for concatenation only.
13087 */
13088function interpolation1(lView, prefix, v0, suffix) {
13089 const different = bindingUpdated(lView, nextBindingIndex(), v0);
13090 return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
13091}
13092/**
13093 * Creates an interpolation binding with 2 expressions.
13094 */
13095function interpolation2(lView, prefix, v0, i0, v1, suffix) {
13096 const bindingIndex = getBindingIndex();
13097 const different = bindingUpdated2(lView, bindingIndex, v0, v1);
13098 incrementBindingIndex(2);
13099 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
13100}
13101/**
13102 * Creates an interpolation binding with 3 expressions.
13103 */
13104function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix) {
13105 const bindingIndex = getBindingIndex();
13106 const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
13107 incrementBindingIndex(3);
13108 return different ?
13109 prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :
13110 NO_CHANGE;
13111}
13112/**
13113 * Create an interpolation binding with 4 expressions.
13114 */
13115function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
13116 const bindingIndex = getBindingIndex();
13117 const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13118 incrementBindingIndex(4);
13119 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13120 renderStringify(v2) + i2 + renderStringify(v3) + suffix :
13121 NO_CHANGE;
13122}
13123/**
13124 * Creates an interpolation binding with 5 expressions.
13125 */
13126function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
13127 const bindingIndex = getBindingIndex();
13128 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13129 different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
13130 incrementBindingIndex(5);
13131 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13132 renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix :
13133 NO_CHANGE;
13134}
13135/**
13136 * Creates an interpolation binding with 6 expressions.
13137 */
13138function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
13139 const bindingIndex = getBindingIndex();
13140 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13141 different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
13142 incrementBindingIndex(6);
13143 return different ?
13144 prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
13145 renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix :
13146 NO_CHANGE;
13147}
13148/**
13149 * Creates an interpolation binding with 7 expressions.
13150 */
13151function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
13152 const bindingIndex = getBindingIndex();
13153 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13154 different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
13155 incrementBindingIndex(7);
13156 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13157 renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
13158 renderStringify(v5) + i5 + renderStringify(v6) + suffix :
13159 NO_CHANGE;
13160}
13161/**
13162 * Creates an interpolation binding with 8 expressions.
13163 */
13164function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
13165 const bindingIndex = getBindingIndex();
13166 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13167 different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
13168 incrementBindingIndex(8);
13169 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13170 renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
13171 renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix :
13172 NO_CHANGE;
13173}
13174
13175/**
13176 *
13177 * Update an interpolated attribute on an element with single bound value surrounded by text.
13178 *
13179 * Used when the value passed to a property has 1 interpolated value in it:
13180 *
13181 * ```html
13182 * <div attr.title="prefix{{v0}}suffix"></div>
13183 * ```
13184 *
13185 * Its compiled representation is::
13186 *
13187 * ```ts
13188 * ɵɵattributeInterpolate1('title', 'prefix', v0, 'suffix');
13189 * ```
13190 *
13191 * @param attrName The name of the attribute to update
13192 * @param prefix Static value used for concatenation only.
13193 * @param v0 Value checked for change.
13194 * @param suffix Static value used for concatenation only.
13195 * @param sanitizer An optional sanitizer function
13196 * @returns itself, so that it may be chained.
13197 * @codeGenApi
13198 */
13199function ɵɵattributeInterpolate1(attrName, prefix, v0, suffix, sanitizer, namespace) {
13200 const lView = getLView();
13201 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
13202 if (interpolatedValue !== NO_CHANGE) {
13203 const tNode = getSelectedTNode();
13204 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13205 ngDevMode &&
13206 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
13207 }
13208 return ɵɵattributeInterpolate1;
13209}
13210/**
13211 *
13212 * Update an interpolated attribute on an element with 2 bound values surrounded by text.
13213 *
13214 * Used when the value passed to a property has 2 interpolated values in it:
13215 *
13216 * ```html
13217 * <div attr.title="prefix{{v0}}-{{v1}}suffix"></div>
13218 * ```
13219 *
13220 * Its compiled representation is::
13221 *
13222 * ```ts
13223 * ɵɵattributeInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
13224 * ```
13225 *
13226 * @param attrName The name of the attribute to update
13227 * @param prefix Static value used for concatenation only.
13228 * @param v0 Value checked for change.
13229 * @param i0 Static value used for concatenation only.
13230 * @param v1 Value checked for change.
13231 * @param suffix Static value used for concatenation only.
13232 * @param sanitizer An optional sanitizer function
13233 * @returns itself, so that it may be chained.
13234 * @codeGenApi
13235 */
13236function ɵɵattributeInterpolate2(attrName, prefix, v0, i0, v1, suffix, sanitizer, namespace) {
13237 const lView = getLView();
13238 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
13239 if (interpolatedValue !== NO_CHANGE) {
13240 const tNode = getSelectedTNode();
13241 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13242 ngDevMode &&
13243 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
13244 }
13245 return ɵɵattributeInterpolate2;
13246}
13247/**
13248 *
13249 * Update an interpolated attribute on an element with 3 bound values surrounded by text.
13250 *
13251 * Used when the value passed to a property has 3 interpolated values in it:
13252 *
13253 * ```html
13254 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
13255 * ```
13256 *
13257 * Its compiled representation is::
13258 *
13259 * ```ts
13260 * ɵɵattributeInterpolate3(
13261 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
13262 * ```
13263 *
13264 * @param attrName The name of the attribute to update
13265 * @param prefix Static value used for concatenation only.
13266 * @param v0 Value checked for change.
13267 * @param i0 Static value used for concatenation only.
13268 * @param v1 Value checked for change.
13269 * @param i1 Static value used for concatenation only.
13270 * @param v2 Value checked for change.
13271 * @param suffix Static value used for concatenation only.
13272 * @param sanitizer An optional sanitizer function
13273 * @returns itself, so that it may be chained.
13274 * @codeGenApi
13275 */
13276function ɵɵattributeInterpolate3(attrName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer, namespace) {
13277 const lView = getLView();
13278 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
13279 if (interpolatedValue !== NO_CHANGE) {
13280 const tNode = getSelectedTNode();
13281 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13282 ngDevMode &&
13283 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, i1, suffix);
13284 }
13285 return ɵɵattributeInterpolate3;
13286}
13287/**
13288 *
13289 * Update an interpolated attribute on an element with 4 bound values surrounded by text.
13290 *
13291 * Used when the value passed to a property has 4 interpolated values in it:
13292 *
13293 * ```html
13294 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
13295 * ```
13296 *
13297 * Its compiled representation is::
13298 *
13299 * ```ts
13300 * ɵɵattributeInterpolate4(
13301 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
13302 * ```
13303 *
13304 * @param attrName The name of the attribute to update
13305 * @param prefix Static value used for concatenation only.
13306 * @param v0 Value checked for change.
13307 * @param i0 Static value used for concatenation only.
13308 * @param v1 Value checked for change.
13309 * @param i1 Static value used for concatenation only.
13310 * @param v2 Value checked for change.
13311 * @param i2 Static value used for concatenation only.
13312 * @param v3 Value checked for change.
13313 * @param suffix Static value used for concatenation only.
13314 * @param sanitizer An optional sanitizer function
13315 * @returns itself, so that it may be chained.
13316 * @codeGenApi
13317 */
13318function ɵɵattributeInterpolate4(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer, namespace) {
13319 const lView = getLView();
13320 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
13321 if (interpolatedValue !== NO_CHANGE) {
13322 const tNode = getSelectedTNode();
13323 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13324 ngDevMode &&
13325 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
13326 }
13327 return ɵɵattributeInterpolate4;
13328}
13329/**
13330 *
13331 * Update an interpolated attribute on an element with 5 bound values surrounded by text.
13332 *
13333 * Used when the value passed to a property has 5 interpolated values in it:
13334 *
13335 * ```html
13336 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
13337 * ```
13338 *
13339 * Its compiled representation is::
13340 *
13341 * ```ts
13342 * ɵɵattributeInterpolate5(
13343 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
13344 * ```
13345 *
13346 * @param attrName The name of the attribute to update
13347 * @param prefix Static value used for concatenation only.
13348 * @param v0 Value checked for change.
13349 * @param i0 Static value used for concatenation only.
13350 * @param v1 Value checked for change.
13351 * @param i1 Static value used for concatenation only.
13352 * @param v2 Value checked for change.
13353 * @param i2 Static value used for concatenation only.
13354 * @param v3 Value checked for change.
13355 * @param i3 Static value used for concatenation only.
13356 * @param v4 Value checked for change.
13357 * @param suffix Static value used for concatenation only.
13358 * @param sanitizer An optional sanitizer function
13359 * @returns itself, so that it may be chained.
13360 * @codeGenApi
13361 */
13362function ɵɵattributeInterpolate5(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer, namespace) {
13363 const lView = getLView();
13364 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
13365 if (interpolatedValue !== NO_CHANGE) {
13366 const tNode = getSelectedTNode();
13367 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13368 ngDevMode &&
13369 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
13370 }
13371 return ɵɵattributeInterpolate5;
13372}
13373/**
13374 *
13375 * Update an interpolated attribute on an element with 6 bound values surrounded by text.
13376 *
13377 * Used when the value passed to a property has 6 interpolated values in it:
13378 *
13379 * ```html
13380 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
13381 * ```
13382 *
13383 * Its compiled representation is::
13384 *
13385 * ```ts
13386 * ɵɵattributeInterpolate6(
13387 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
13388 * ```
13389 *
13390 * @param attrName The name of the attribute to update
13391 * @param prefix Static value used for concatenation only.
13392 * @param v0 Value checked for change.
13393 * @param i0 Static value used for concatenation only.
13394 * @param v1 Value checked for change.
13395 * @param i1 Static value used for concatenation only.
13396 * @param v2 Value checked for change.
13397 * @param i2 Static value used for concatenation only.
13398 * @param v3 Value checked for change.
13399 * @param i3 Static value used for concatenation only.
13400 * @param v4 Value checked for change.
13401 * @param i4 Static value used for concatenation only.
13402 * @param v5 Value checked for change.
13403 * @param suffix Static value used for concatenation only.
13404 * @param sanitizer An optional sanitizer function
13405 * @returns itself, so that it may be chained.
13406 * @codeGenApi
13407 */
13408function ɵɵattributeInterpolate6(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer, namespace) {
13409 const lView = getLView();
13410 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
13411 if (interpolatedValue !== NO_CHANGE) {
13412 const tNode = getSelectedTNode();
13413 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13414 ngDevMode &&
13415 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
13416 }
13417 return ɵɵattributeInterpolate6;
13418}
13419/**
13420 *
13421 * Update an interpolated attribute on an element with 7 bound values surrounded by text.
13422 *
13423 * Used when the value passed to a property has 7 interpolated values in it:
13424 *
13425 * ```html
13426 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
13427 * ```
13428 *
13429 * Its compiled representation is::
13430 *
13431 * ```ts
13432 * ɵɵattributeInterpolate7(
13433 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
13434 * ```
13435 *
13436 * @param attrName The name of the attribute to update
13437 * @param prefix Static value used for concatenation only.
13438 * @param v0 Value checked for change.
13439 * @param i0 Static value used for concatenation only.
13440 * @param v1 Value checked for change.
13441 * @param i1 Static value used for concatenation only.
13442 * @param v2 Value checked for change.
13443 * @param i2 Static value used for concatenation only.
13444 * @param v3 Value checked for change.
13445 * @param i3 Static value used for concatenation only.
13446 * @param v4 Value checked for change.
13447 * @param i4 Static value used for concatenation only.
13448 * @param v5 Value checked for change.
13449 * @param i5 Static value used for concatenation only.
13450 * @param v6 Value checked for change.
13451 * @param suffix Static value used for concatenation only.
13452 * @param sanitizer An optional sanitizer function
13453 * @returns itself, so that it may be chained.
13454 * @codeGenApi
13455 */
13456function ɵɵattributeInterpolate7(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer, namespace) {
13457 const lView = getLView();
13458 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
13459 if (interpolatedValue !== NO_CHANGE) {
13460 const tNode = getSelectedTNode();
13461 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13462 ngDevMode &&
13463 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix);
13464 }
13465 return ɵɵattributeInterpolate7;
13466}
13467/**
13468 *
13469 * Update an interpolated attribute on an element with 8 bound values surrounded by text.
13470 *
13471 * Used when the value passed to a property has 8 interpolated values in it:
13472 *
13473 * ```html
13474 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
13475 * ```
13476 *
13477 * Its compiled representation is::
13478 *
13479 * ```ts
13480 * ɵɵattributeInterpolate8(
13481 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
13482 * ```
13483 *
13484 * @param attrName The name of the attribute to update
13485 * @param prefix Static value used for concatenation only.
13486 * @param v0 Value checked for change.
13487 * @param i0 Static value used for concatenation only.
13488 * @param v1 Value checked for change.
13489 * @param i1 Static value used for concatenation only.
13490 * @param v2 Value checked for change.
13491 * @param i2 Static value used for concatenation only.
13492 * @param v3 Value checked for change.
13493 * @param i3 Static value used for concatenation only.
13494 * @param v4 Value checked for change.
13495 * @param i4 Static value used for concatenation only.
13496 * @param v5 Value checked for change.
13497 * @param i5 Static value used for concatenation only.
13498 * @param v6 Value checked for change.
13499 * @param i6 Static value used for concatenation only.
13500 * @param v7 Value checked for change.
13501 * @param suffix Static value used for concatenation only.
13502 * @param sanitizer An optional sanitizer function
13503 * @returns itself, so that it may be chained.
13504 * @codeGenApi
13505 */
13506function ɵɵattributeInterpolate8(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer, namespace) {
13507 const lView = getLView();
13508 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
13509 if (interpolatedValue !== NO_CHANGE) {
13510 const tNode = getSelectedTNode();
13511 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13512 ngDevMode &&
13513 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
13514 }
13515 return ɵɵattributeInterpolate8;
13516}
13517/**
13518 * Update an interpolated attribute on an element with 9 or more bound values surrounded by text.
13519 *
13520 * Used when the number of interpolated values exceeds 8.
13521 *
13522 * ```html
13523 * <div
13524 * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
13525 * ```
13526 *
13527 * Its compiled representation is::
13528 *
13529 * ```ts
13530 * ɵɵattributeInterpolateV(
13531 * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
13532 * 'suffix']);
13533 * ```
13534 *
13535 * @param attrName The name of the attribute to update.
13536 * @param values The collection of values and the strings in-between those values, beginning with
13537 * a string prefix and ending with a string suffix.
13538 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
13539 * @param sanitizer An optional sanitizer function
13540 * @returns itself, so that it may be chained.
13541 * @codeGenApi
13542 */
13543function ɵɵattributeInterpolateV(attrName, values, sanitizer, namespace) {
13544 const lView = getLView();
13545 const interpolated = interpolationV(lView, values);
13546 if (interpolated !== NO_CHANGE) {
13547 const tNode = getSelectedTNode();
13548 elementAttributeInternal(tNode, lView, attrName, interpolated, sanitizer, namespace);
13549 if (ngDevMode) {
13550 const interpolationInBetween = [values[0]]; // prefix
13551 for (let i = 2; i < values.length; i += 2) {
13552 interpolationInBetween.push(values[i]);
13553 }
13554 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
13555 }
13556 }
13557 return ɵɵattributeInterpolateV;
13558}
13559
13560/**
13561 * @license
13562 * Copyright Google LLC All Rights Reserved.
13563 *
13564 * Use of this source code is governed by an MIT-style license that can be
13565 * found in the LICENSE file at https://angular.io/license
13566 */
13567function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
13568 ngDevMode && assertFirstCreatePass(tView);
13569 ngDevMode && ngDevMode.firstCreatePass++;
13570 const tViewConsts = tView.consts;
13571 // TODO(pk): refactor getOrCreateTNode to have the "create" only version
13572 const tNode = getOrCreateTNode(tView, index, 4 /* Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
13573 resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
13574 registerPostOrderHooks(tView, tNode);
13575 const embeddedTView = tNode.tViews = createTView(2 /* Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
13576 if (tView.queries !== null) {
13577 tView.queries.template(tView, tNode);
13578 embeddedTView.queries = tView.queries.embeddedTView(tNode);
13579 }
13580 return tNode;
13581}
13582/**
13583 * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
13584 *
13585 * <ng-template #foo>
13586 * <div></div>
13587 * </ng-template>
13588 *
13589 * @param index The index of the container in the data array
13590 * @param templateFn Inline template
13591 * @param decls The number of nodes, local refs, and pipes for this template
13592 * @param vars The number of bindings for this template
13593 * @param tagName The name of the container element, if applicable
13594 * @param attrsIndex Index of template attributes in the `consts` array.
13595 * @param localRefs Index of the local references in the `consts` array.
13596 * @param localRefExtractor A function which extracts local-refs values from the template.
13597 * Defaults to the current element associated with the local-ref.
13598 *
13599 * @codeGenApi
13600 */
13601function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
13602 const lView = getLView();
13603 const tView = getTView();
13604 const adjustedIndex = index + HEADER_OFFSET;
13605 const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
13606 tView.data[adjustedIndex];
13607 setCurrentTNode(tNode, false);
13608 const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
13609 appendChild(tView, lView, comment, tNode);
13610 attachPatchData(comment, lView);
13611 addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));
13612 if (isDirectiveHost(tNode)) {
13613 createDirectivesInstances(tView, lView, tNode);
13614 }
13615 if (localRefsIndex != null) {
13616 saveResolvedLocalsInData(lView, tNode, localRefExtractor);
13617 }
13618}
13619
13620/**
13621 * @license
13622 * Copyright Google LLC All Rights Reserved.
13623 *
13624 * Use of this source code is governed by an MIT-style license that can be
13625 * found in the LICENSE file at https://angular.io/license
13626 */
13627/** Store a value in the `data` at a given `index`. */
13628function store(tView, lView, index, value) {
13629 // We don't store any static data for local variables, so the first time
13630 // we see the template, we should store as null to avoid a sparse array
13631 if (index >= tView.data.length) {
13632 tView.data[index] = null;
13633 tView.blueprint[index] = null;
13634 }
13635 lView[index] = value;
13636}
13637/**
13638 * Retrieves a local reference from the current contextViewData.
13639 *
13640 * If the reference to retrieve is in a parent view, this instruction is used in conjunction
13641 * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
13642 *
13643 * @param index The index of the local ref in contextViewData.
13644 *
13645 * @codeGenApi
13646 */
13647function ɵɵreference(index) {
13648 const contextLView = getContextLView();
13649 return load(contextLView, HEADER_OFFSET + index);
13650}
13651
13652/**
13653 * @license
13654 * Copyright Google LLC All Rights Reserved.
13655 *
13656 * Use of this source code is governed by an MIT-style license that can be
13657 * found in the LICENSE file at https://angular.io/license
13658 */
13659/**
13660 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
13661 *
13662 * This should be kept up to date with the public exports of @angular/core.
13663 */
13664const angularCoreDiEnv = {
13665 'ɵɵdefineInjectable': ɵɵdefineInjectable,
13666 'ɵɵdefineInjector': ɵɵdefineInjector,
13667 'ɵɵinject': ɵɵinject,
13668 'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
13669 'resolveForwardRef': resolveForwardRef,
13670};
13671
13672/**
13673 * @license
13674 * Copyright Google LLC All Rights Reserved.
13675 *
13676 * Use of this source code is governed by an MIT-style license that can be
13677 * found in the LICENSE file at https://angular.io/license
13678 */
13679/**
13680 * Compile an Angular injectable according to its `Injectable` metadata, and patch the resulting
13681 * injectable def (`ɵprov`) onto the injectable type.
13682 */
13683function compileInjectable(type, meta) {
13684 let ngInjectableDef = null;
13685 let ngFactoryDef = null;
13686 // if NG_PROV_DEF is already defined on this class then don't overwrite it
13687 if (!type.hasOwnProperty(NG_PROV_DEF)) {
13688 Object.defineProperty(type, NG_PROV_DEF, {
13689 get: () => {
13690 if (ngInjectableDef === null) {
13691 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'injectable', type });
13692 ngInjectableDef = compiler.compileInjectable(angularCoreDiEnv, `ng:///${type.name}/ɵprov.js`, getInjectableMetadata(type, meta));
13693 }
13694 return ngInjectableDef;
13695 },
13696 });
13697 }
13698 // if NG_FACTORY_DEF is already defined on this class then don't overwrite it
13699 if (!type.hasOwnProperty(NG_FACTORY_DEF)) {
13700 Object.defineProperty(type, NG_FACTORY_DEF, {
13701 get: () => {
13702 if (ngFactoryDef === null) {
13703 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'injectable', type });
13704 ngFactoryDef = compiler.compileFactory(angularCoreDiEnv, `ng:///${type.name}/ɵfac.js`, {
13705 name: type.name,
13706 type,
13707 typeArgumentCount: 0,
13708 deps: reflectDependencies(type),
13709 target: compiler.FactoryTarget.Injectable
13710 });
13711 }
13712 return ngFactoryDef;
13713 },
13714 // Leave this configurable so that the factories from directives or pipes can take precedence.
13715 configurable: true
13716 });
13717 }
13718}
13719const USE_VALUE$1 = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
13720function isUseClassProvider(meta) {
13721 return meta.useClass !== undefined;
13722}
13723function isUseValueProvider(meta) {
13724 return USE_VALUE$1 in meta;
13725}
13726function isUseFactoryProvider(meta) {
13727 return meta.useFactory !== undefined;
13728}
13729function isUseExistingProvider(meta) {
13730 return meta.useExisting !== undefined;
13731}
13732function getInjectableMetadata(type, srcMeta) {
13733 // Allow the compilation of a class with a `@Injectable()` decorator without parameters
13734 const meta = srcMeta || { providedIn: null };
13735 const compilerMeta = {
13736 name: type.name,
13737 type: type,
13738 typeArgumentCount: 0,
13739 providedIn: meta.providedIn,
13740 };
13741 if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
13742 compilerMeta.deps = convertDependencies(meta.deps);
13743 }
13744 // Check to see if the user explicitly provided a `useXxxx` property.
13745 if (isUseClassProvider(meta)) {
13746 compilerMeta.useClass = meta.useClass;
13747 }
13748 else if (isUseValueProvider(meta)) {
13749 compilerMeta.useValue = meta.useValue;
13750 }
13751 else if (isUseFactoryProvider(meta)) {
13752 compilerMeta.useFactory = meta.useFactory;
13753 }
13754 else if (isUseExistingProvider(meta)) {
13755 compilerMeta.useExisting = meta.useExisting;
13756 }
13757 return compilerMeta;
13758}
13759
13760/**
13761 * @license
13762 * Copyright Google LLC All Rights Reserved.
13763 *
13764 * Use of this source code is governed by an MIT-style license that can be
13765 * found in the LICENSE file at https://angular.io/license
13766 */
13767const USE_VALUE = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
13768function convertInjectableProviderToFactory(type, provider) {
13769 if (!provider) {
13770 const reflectionCapabilities = new ReflectionCapabilities();
13771 const deps = reflectionCapabilities.parameters(type);
13772 // TODO - convert to flags.
13773 return () => new type(...injectArgs(deps));
13774 }
13775 if (USE_VALUE in provider) {
13776 const valueProvider = provider;
13777 return () => valueProvider.useValue;
13778 }
13779 else if (provider.useExisting) {
13780 const existingProvider = provider;
13781 return () => ɵɵinject(resolveForwardRef(existingProvider.useExisting));
13782 }
13783 else if (provider.useFactory) {
13784 const factoryProvider = provider;
13785 return () => factoryProvider.useFactory(...injectArgs(factoryProvider.deps || EMPTY_ARRAY));
13786 }
13787 else if (provider.useClass) {
13788 const classProvider = provider;
13789 let deps = provider.deps;
13790 if (!deps) {
13791 const reflectionCapabilities = new ReflectionCapabilities();
13792 deps = reflectionCapabilities.parameters(type);
13793 }
13794 return () => new (resolveForwardRef(classProvider.useClass))(...injectArgs(deps));
13795 }
13796 else {
13797 let deps = provider.deps;
13798 if (!deps) {
13799 const reflectionCapabilities = new ReflectionCapabilities();
13800 deps = reflectionCapabilities.parameters(type);
13801 }
13802 return () => new type(...injectArgs(deps));
13803 }
13804}
13805
13806/**
13807 * Injectable decorator and metadata.
13808 *
13809 * @Annotation
13810 * @publicApi
13811 */
13812const Injectable = makeDecorator('Injectable', undefined, undefined, undefined, (type, meta) => SWITCH_COMPILE_INJECTABLE(type, meta));
13813/**
13814 * Supports @Injectable() in JIT mode for Render2.
13815 */
13816function render2CompileInjectable(injectableType, options) {
13817 if (options && options.providedIn !== undefined && !getInjectableDef(injectableType)) {
13818 injectableType.ɵprov = ɵɵdefineInjectable({
13819 token: injectableType,
13820 providedIn: options.providedIn,
13821 factory: convertInjectableProviderToFactory(injectableType, options),
13822 });
13823 }
13824}
13825const SWITCH_COMPILE_INJECTABLE__POST_R3__ = compileInjectable;
13826const SWITCH_COMPILE_INJECTABLE__PRE_R3__ = render2CompileInjectable;
13827const SWITCH_COMPILE_INJECTABLE = SWITCH_COMPILE_INJECTABLE__POST_R3__;
13828
13829/**
13830 * @license
13831 * Copyright Google LLC All Rights Reserved.
13832 *
13833 * Use of this source code is governed by an MIT-style license that can be
13834 * found in the LICENSE file at https://angular.io/license
13835 */
13836function findFirstClosedCycle(keys) {
13837 const res = [];
13838 for (let i = 0; i < keys.length; ++i) {
13839 if (res.indexOf(keys[i]) > -1) {
13840 res.push(keys[i]);
13841 return res;
13842 }
13843 res.push(keys[i]);
13844 }
13845 return res;
13846}
13847function constructResolvingPath(keys) {
13848 if (keys.length > 1) {
13849 const reversed = findFirstClosedCycle(keys.slice().reverse());
13850 const tokenStrs = reversed.map(k => stringify(k.token));
13851 return ' (' + tokenStrs.join(' -> ') + ')';
13852 }
13853 return '';
13854}
13855function injectionError(injector, key, constructResolvingMessage, originalError) {
13856 const keys = [key];
13857 const errMsg = constructResolvingMessage(keys);
13858 const error = (originalError ? wrappedError(errMsg, originalError) : Error(errMsg));
13859 error.addKey = addKey;
13860 error.keys = keys;
13861 error.injectors = [injector];
13862 error.constructResolvingMessage = constructResolvingMessage;
13863 error[ERROR_ORIGINAL_ERROR] = originalError;
13864 return error;
13865}
13866function addKey(injector, key) {
13867 this.injectors.push(injector);
13868 this.keys.push(key);
13869 // Note: This updated message won't be reflected in the `.stack` property
13870 this.message = this.constructResolvingMessage(this.keys);
13871}
13872/**
13873 * Thrown when trying to retrieve a dependency by key from {@link Injector}, but the
13874 * {@link Injector} does not have a {@link Provider} for the given key.
13875 *
13876 * @usageNotes
13877 * ### Example
13878 *
13879 * ```typescript
13880 * class A {
13881 * constructor(b:B) {}
13882 * }
13883 *
13884 * expect(() => Injector.resolveAndCreate([A])).toThrowError();
13885 * ```
13886 */
13887function noProviderError(injector, key) {
13888 return injectionError(injector, key, function (keys) {
13889 const first = stringify(keys[0].token);
13890 return `No provider for ${first}!${constructResolvingPath(keys)}`;
13891 });
13892}
13893/**
13894 * Thrown when dependencies form a cycle.
13895 *
13896 * @usageNotes
13897 * ### Example
13898 *
13899 * ```typescript
13900 * var injector = Injector.resolveAndCreate([
13901 * {provide: "one", useFactory: (two) => "two", deps: [[new Inject("two")]]},
13902 * {provide: "two", useFactory: (one) => "one", deps: [[new Inject("one")]]}
13903 * ]);
13904 *
13905 * expect(() => injector.get("one")).toThrowError();
13906 * ```
13907 *
13908 * Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed.
13909 */
13910function cyclicDependencyError(injector, key) {
13911 return injectionError(injector, key, function (keys) {
13912 return `Cannot instantiate cyclic dependency!${constructResolvingPath(keys)}`;
13913 });
13914}
13915/**
13916 * Thrown when a constructing type returns with an Error.
13917 *
13918 * The `InstantiationError` class contains the original error plus the dependency graph which caused
13919 * this object to be instantiated.
13920 *
13921 * @usageNotes
13922 * ### Example
13923 *
13924 * ```typescript
13925 * class A {
13926 * constructor() {
13927 * throw new Error('message');
13928 * }
13929 * }
13930 *
13931 * var injector = Injector.resolveAndCreate([A]);
13932
13933 * try {
13934 * injector.get(A);
13935 * } catch (e) {
13936 * expect(e instanceof InstantiationError).toBe(true);
13937 * expect(e.originalException.message).toEqual("message");
13938 * expect(e.originalStack).toBeDefined();
13939 * }
13940 * ```
13941 */
13942function instantiationError(injector, originalException, originalStack, key) {
13943 return injectionError(injector, key, function (keys) {
13944 const first = stringify(keys[0].token);
13945 return `${originalException.message}: Error during instantiation of ${first}!${constructResolvingPath(keys)}.`;
13946 }, originalException);
13947}
13948/**
13949 * Thrown when an object other then {@link Provider} (or `Type`) is passed to {@link Injector}
13950 * creation.
13951 *
13952 * @usageNotes
13953 * ### Example
13954 *
13955 * ```typescript
13956 * expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError();
13957 * ```
13958 */
13959function invalidProviderError(provider) {
13960 return Error(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`);
13961}
13962/**
13963 * Thrown when the class has no annotation information.
13964 *
13965 * Lack of annotation information prevents the {@link Injector} from determining which dependencies
13966 * need to be injected into the constructor.
13967 *
13968 * @usageNotes
13969 * ### Example
13970 *
13971 * ```typescript
13972 * class A {
13973 * constructor(b) {}
13974 * }
13975 *
13976 * expect(() => Injector.resolveAndCreate([A])).toThrowError();
13977 * ```
13978 *
13979 * This error is also thrown when the class not marked with {@link Injectable} has parameter types.
13980 *
13981 * ```typescript
13982 * class B {}
13983 *
13984 * class A {
13985 * constructor(b:B) {} // no information about the parameter types of A is available at runtime.
13986 * }
13987 *
13988 * expect(() => Injector.resolveAndCreate([A,B])).toThrowError();
13989 * ```
13990 *
13991 */
13992function noAnnotationError(typeOrFunc, params) {
13993 const signature = [];
13994 for (let i = 0, ii = params.length; i < ii; i++) {
13995 const parameter = params[i];
13996 if (!parameter || parameter.length == 0) {
13997 signature.push('?');
13998 }
13999 else {
14000 signature.push(parameter.map(stringify).join(' '));
14001 }
14002 }
14003 return Error('Cannot resolve all parameters for \'' + stringify(typeOrFunc) + '\'(' +
14004 signature.join(', ') + '). ' +
14005 'Make sure that all the parameters are decorated with Inject or have valid type annotations and that \'' +
14006 stringify(typeOrFunc) + '\' is decorated with Injectable.');
14007}
14008/**
14009 * Thrown when getting an object by index.
14010 *
14011 * @usageNotes
14012 * ### Example
14013 *
14014 * ```typescript
14015 * class A {}
14016 *
14017 * var injector = Injector.resolveAndCreate([A]);
14018 *
14019 * expect(() => injector.getAt(100)).toThrowError();
14020 * ```
14021 *
14022 */
14023function outOfBoundsError(index) {
14024 return Error(`Index ${index} is out-of-bounds.`);
14025}
14026// TODO: add a working example after alpha38 is released
14027/**
14028 * Thrown when a multi provider and a regular provider are bound to the same token.
14029 *
14030 * @usageNotes
14031 * ### Example
14032 *
14033 * ```typescript
14034 * expect(() => Injector.resolveAndCreate([
14035 * { provide: "Strings", useValue: "string1", multi: true},
14036 * { provide: "Strings", useValue: "string2", multi: false}
14037 * ])).toThrowError();
14038 * ```
14039 */
14040function mixingMultiProvidersWithRegularProvidersError(provider1, provider2) {
14041 return Error(`Cannot mix multi providers and regular providers, got: ${provider1} ${provider2}`);
14042}
14043
14044/**
14045 * @license
14046 * Copyright Google LLC All Rights Reserved.
14047 *
14048 * Use of this source code is governed by an MIT-style license that can be
14049 * found in the LICENSE file at https://angular.io/license
14050 */
14051/**
14052 * A unique object used for retrieving items from the {@link ReflectiveInjector}.
14053 *
14054 * Keys have:
14055 * - a system-wide unique `id`.
14056 * - a `token`.
14057 *
14058 * `Key` is used internally by {@link ReflectiveInjector} because its system-wide unique `id` allows
14059 * the
14060 * injector to store created objects in a more efficient way.
14061 *
14062 * `Key` should not be created directly. {@link ReflectiveInjector} creates keys automatically when
14063 * resolving
14064 * providers.
14065 *
14066 * @deprecated No replacement
14067 * @publicApi
14068 */
14069class ReflectiveKey {
14070 /**
14071 * Private
14072 */
14073 constructor(token, id) {
14074 this.token = token;
14075 this.id = id;
14076 if (!token) {
14077 throw new Error('Token must be defined!');
14078 }
14079 this.displayName = stringify(this.token);
14080 }
14081 /**
14082 * Retrieves a `Key` for a token.
14083 */
14084 static get(token) {
14085 return _globalKeyRegistry.get(resolveForwardRef(token));
14086 }
14087 /**
14088 * @returns the number of keys registered in the system.
14089 */
14090 static get numberOfKeys() {
14091 return _globalKeyRegistry.numberOfKeys;
14092 }
14093}
14094class KeyRegistry {
14095 constructor() {
14096 this._allKeys = new Map();
14097 }
14098 get(token) {
14099 if (token instanceof ReflectiveKey)
14100 return token;
14101 if (this._allKeys.has(token)) {
14102 return this._allKeys.get(token);
14103 }
14104 const newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys);
14105 this._allKeys.set(token, newKey);
14106 return newKey;
14107 }
14108 get numberOfKeys() {
14109 return this._allKeys.size;
14110 }
14111}
14112const _globalKeyRegistry = new KeyRegistry();
14113
14114/**
14115 * @license
14116 * Copyright Google LLC All Rights Reserved.
14117 *
14118 * Use of this source code is governed by an MIT-style license that can be
14119 * found in the LICENSE file at https://angular.io/license
14120 */
14121/**
14122 * Provides access to reflection data about symbols. Used internally by Angular
14123 * to power dependency injection and compilation.
14124 */
14125class Reflector {
14126 constructor(reflectionCapabilities) {
14127 this.reflectionCapabilities = reflectionCapabilities;
14128 }
14129 updateCapabilities(caps) {
14130 this.reflectionCapabilities = caps;
14131 }
14132 factory(type) {
14133 return this.reflectionCapabilities.factory(type);
14134 }
14135 parameters(typeOrFunc) {
14136 return this.reflectionCapabilities.parameters(typeOrFunc);
14137 }
14138 annotations(typeOrFunc) {
14139 return this.reflectionCapabilities.annotations(typeOrFunc);
14140 }
14141 propMetadata(typeOrFunc) {
14142 return this.reflectionCapabilities.propMetadata(typeOrFunc);
14143 }
14144 hasLifecycleHook(type, lcProperty) {
14145 return this.reflectionCapabilities.hasLifecycleHook(type, lcProperty);
14146 }
14147 getter(name) {
14148 return this.reflectionCapabilities.getter(name);
14149 }
14150 setter(name) {
14151 return this.reflectionCapabilities.setter(name);
14152 }
14153 method(name) {
14154 return this.reflectionCapabilities.method(name);
14155 }
14156 importUri(type) {
14157 return this.reflectionCapabilities.importUri(type);
14158 }
14159 resourceUri(type) {
14160 return this.reflectionCapabilities.resourceUri(type);
14161 }
14162 resolveIdentifier(name, moduleUrl, members, runtime) {
14163 return this.reflectionCapabilities.resolveIdentifier(name, moduleUrl, members, runtime);
14164 }
14165 resolveEnum(identifier, name) {
14166 return this.reflectionCapabilities.resolveEnum(identifier, name);
14167 }
14168}
14169
14170/**
14171 * @license
14172 * Copyright Google LLC All Rights Reserved.
14173 *
14174 * Use of this source code is governed by an MIT-style license that can be
14175 * found in the LICENSE file at https://angular.io/license
14176 */
14177/**
14178 * The {@link Reflector} used internally in Angular to access metadata
14179 * about symbols.
14180 */
14181const reflector = new Reflector(new ReflectionCapabilities());
14182
14183/**
14184 * @license
14185 * Copyright Google LLC All Rights Reserved.
14186 *
14187 * Use of this source code is governed by an MIT-style license that can be
14188 * found in the LICENSE file at https://angular.io/license
14189 */
14190/**
14191 * `Dependency` is used by the framework to extend DI.
14192 * This is internal to Angular and should not be used directly.
14193 */
14194class ReflectiveDependency {
14195 constructor(key, optional, visibility) {
14196 this.key = key;
14197 this.optional = optional;
14198 this.visibility = visibility;
14199 }
14200 static fromKey(key) {
14201 return new ReflectiveDependency(key, false, null);
14202 }
14203}
14204const _EMPTY_LIST = [];
14205class ResolvedReflectiveProvider_ {
14206 constructor(key, resolvedFactories, multiProvider) {
14207 this.key = key;
14208 this.resolvedFactories = resolvedFactories;
14209 this.multiProvider = multiProvider;
14210 this.resolvedFactory = this.resolvedFactories[0];
14211 }
14212}
14213/**
14214 * An internal resolved representation of a factory function created by resolving `Provider`.
14215 * @publicApi
14216 */
14217class ResolvedReflectiveFactory {
14218 constructor(
14219 /**
14220 * Factory function which can return an instance of an object represented by a key.
14221 */
14222 factory,
14223 /**
14224 * Arguments (dependencies) to the `factory` function.
14225 */
14226 dependencies) {
14227 this.factory = factory;
14228 this.dependencies = dependencies;
14229 }
14230}
14231/**
14232 * Resolve a single provider.
14233 */
14234function resolveReflectiveFactory(provider) {
14235 let factoryFn;
14236 let resolvedDeps;
14237 if (provider.useClass) {
14238 const useClass = resolveForwardRef(provider.useClass);
14239 factoryFn = reflector.factory(useClass);
14240 resolvedDeps = _dependenciesFor(useClass);
14241 }
14242 else if (provider.useExisting) {
14243 factoryFn = (aliasInstance) => aliasInstance;
14244 resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))];
14245 }
14246 else if (provider.useFactory) {
14247 factoryFn = provider.useFactory;
14248 resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
14249 }
14250 else {
14251 factoryFn = () => provider.useValue;
14252 resolvedDeps = _EMPTY_LIST;
14253 }
14254 return new ResolvedReflectiveFactory(factoryFn, resolvedDeps);
14255}
14256/**
14257 * Converts the `Provider` into `ResolvedProvider`.
14258 *
14259 * `Injector` internally only uses `ResolvedProvider`, `Provider` contains convenience provider
14260 * syntax.
14261 */
14262function resolveReflectiveProvider(provider) {
14263 return new ResolvedReflectiveProvider_(ReflectiveKey.get(provider.provide), [resolveReflectiveFactory(provider)], provider.multi || false);
14264}
14265/**
14266 * Resolve a list of Providers.
14267 */
14268function resolveReflectiveProviders(providers) {
14269 const normalized = _normalizeProviders(providers, []);
14270 const resolved = normalized.map(resolveReflectiveProvider);
14271 const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map());
14272 return Array.from(resolvedProviderMap.values());
14273}
14274/**
14275 * Merges a list of ResolvedProviders into a list where each key is contained exactly once and
14276 * multi providers have been merged.
14277 */
14278function mergeResolvedReflectiveProviders(providers, normalizedProvidersMap) {
14279 for (let i = 0; i < providers.length; i++) {
14280 const provider = providers[i];
14281 const existing = normalizedProvidersMap.get(provider.key.id);
14282 if (existing) {
14283 if (provider.multiProvider !== existing.multiProvider) {
14284 throw mixingMultiProvidersWithRegularProvidersError(existing, provider);
14285 }
14286 if (provider.multiProvider) {
14287 for (let j = 0; j < provider.resolvedFactories.length; j++) {
14288 existing.resolvedFactories.push(provider.resolvedFactories[j]);
14289 }
14290 }
14291 else {
14292 normalizedProvidersMap.set(provider.key.id, provider);
14293 }
14294 }
14295 else {
14296 let resolvedProvider;
14297 if (provider.multiProvider) {
14298 resolvedProvider = new ResolvedReflectiveProvider_(provider.key, provider.resolvedFactories.slice(), provider.multiProvider);
14299 }
14300 else {
14301 resolvedProvider = provider;
14302 }
14303 normalizedProvidersMap.set(provider.key.id, resolvedProvider);
14304 }
14305 }
14306 return normalizedProvidersMap;
14307}
14308function _normalizeProviders(providers, res) {
14309 providers.forEach(b => {
14310 if (b instanceof Type) {
14311 res.push({ provide: b, useClass: b });
14312 }
14313 else if (b && typeof b == 'object' && b.provide !== undefined) {
14314 res.push(b);
14315 }
14316 else if (Array.isArray(b)) {
14317 _normalizeProviders(b, res);
14318 }
14319 else {
14320 throw invalidProviderError(b);
14321 }
14322 });
14323 return res;
14324}
14325function constructDependencies(typeOrFunc, dependencies) {
14326 if (!dependencies) {
14327 return _dependenciesFor(typeOrFunc);
14328 }
14329 else {
14330 const params = dependencies.map(t => [t]);
14331 return dependencies.map(t => _extractToken(typeOrFunc, t, params));
14332 }
14333}
14334function _dependenciesFor(typeOrFunc) {
14335 const params = reflector.parameters(typeOrFunc);
14336 if (!params)
14337 return [];
14338 if (params.some(p => p == null)) {
14339 throw noAnnotationError(typeOrFunc, params);
14340 }
14341 return params.map(p => _extractToken(typeOrFunc, p, params));
14342}
14343function _extractToken(typeOrFunc, metadata, params) {
14344 let token = null;
14345 let optional = false;
14346 if (!Array.isArray(metadata)) {
14347 if (metadata instanceof Inject) {
14348 return _createDependency(metadata.token, optional, null);
14349 }
14350 else {
14351 return _createDependency(metadata, optional, null);
14352 }
14353 }
14354 let visibility = null;
14355 for (let i = 0; i < metadata.length; ++i) {
14356 const paramMetadata = metadata[i];
14357 if (paramMetadata instanceof Type) {
14358 token = paramMetadata;
14359 }
14360 else if (paramMetadata instanceof Inject) {
14361 token = paramMetadata.token;
14362 }
14363 else if (paramMetadata instanceof Optional) {
14364 optional = true;
14365 }
14366 else if (paramMetadata instanceof Self || paramMetadata instanceof SkipSelf) {
14367 visibility = paramMetadata;
14368 }
14369 else if (paramMetadata instanceof InjectionToken) {
14370 token = paramMetadata;
14371 }
14372 }
14373 token = resolveForwardRef(token);
14374 if (token != null) {
14375 return _createDependency(token, optional, visibility);
14376 }
14377 else {
14378 throw noAnnotationError(typeOrFunc, params);
14379 }
14380}
14381function _createDependency(token, optional, visibility) {
14382 return new ReflectiveDependency(ReflectiveKey.get(token), optional, visibility);
14383}
14384
14385/**
14386 * @license
14387 * Copyright Google LLC All Rights Reserved.
14388 *
14389 * Use of this source code is governed by an MIT-style license that can be
14390 * found in the LICENSE file at https://angular.io/license
14391 */
14392// Threshold for the dynamic version
14393const UNDEFINED = {};
14394/**
14395 * A ReflectiveDependency injection container used for instantiating objects and resolving
14396 * dependencies.
14397 *
14398 * An `Injector` is a replacement for a `new` operator, which can automatically resolve the
14399 * constructor dependencies.
14400 *
14401 * In typical use, application code asks for the dependencies in the constructor and they are
14402 * resolved by the `Injector`.
14403 *
14404 * @usageNotes
14405 * ### Example
14406 *
14407 * The following example creates an `Injector` configured to create `Engine` and `Car`.
14408 *
14409 * ```typescript
14410 * @Injectable()
14411 * class Engine {
14412 * }
14413 *
14414 * @Injectable()
14415 * class Car {
14416 * constructor(public engine:Engine) {}
14417 * }
14418 *
14419 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
14420 * var car = injector.get(Car);
14421 * expect(car instanceof Car).toBe(true);
14422 * expect(car.engine instanceof Engine).toBe(true);
14423 * ```
14424 *
14425 * Notice, we don't use the `new` operator because we explicitly want to have the `Injector`
14426 * resolve all of the object's dependencies automatically.
14427 *
14428 * @deprecated from v5 - slow and brings in a lot of code, Use `Injector.create` instead.
14429 * @publicApi
14430 */
14431class ReflectiveInjector {
14432 /**
14433 * Turns an array of provider definitions into an array of resolved providers.
14434 *
14435 * A resolution is a process of flattening multiple nested arrays and converting individual
14436 * providers into an array of `ResolvedReflectiveProvider`s.
14437 *
14438 * @usageNotes
14439 * ### Example
14440 *
14441 * ```typescript
14442 * @Injectable()
14443 * class Engine {
14444 * }
14445 *
14446 * @Injectable()
14447 * class Car {
14448 * constructor(public engine:Engine) {}
14449 * }
14450 *
14451 * var providers = ReflectiveInjector.resolve([Car, [[Engine]]]);
14452 *
14453 * expect(providers.length).toEqual(2);
14454 *
14455 * expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true);
14456 * expect(providers[0].key.displayName).toBe("Car");
14457 * expect(providers[0].dependencies.length).toEqual(1);
14458 * expect(providers[0].factory).toBeDefined();
14459 *
14460 * expect(providers[1].key.displayName).toBe("Engine");
14461 * });
14462 * ```
14463 *
14464 */
14465 static resolve(providers) {
14466 return resolveReflectiveProviders(providers);
14467 }
14468 /**
14469 * Resolves an array of providers and creates an injector from those providers.
14470 *
14471 * The passed-in providers can be an array of `Type`, `Provider`,
14472 * or a recursive array of more providers.
14473 *
14474 * @usageNotes
14475 * ### Example
14476 *
14477 * ```typescript
14478 * @Injectable()
14479 * class Engine {
14480 * }
14481 *
14482 * @Injectable()
14483 * class Car {
14484 * constructor(public engine:Engine) {}
14485 * }
14486 *
14487 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
14488 * expect(injector.get(Car) instanceof Car).toBe(true);
14489 * ```
14490 */
14491 static resolveAndCreate(providers, parent) {
14492 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
14493 return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
14494 }
14495 /**
14496 * Creates an injector from previously resolved providers.
14497 *
14498 * This API is the recommended way to construct injectors in performance-sensitive parts.
14499 *
14500 * @usageNotes
14501 * ### Example
14502 *
14503 * ```typescript
14504 * @Injectable()
14505 * class Engine {
14506 * }
14507 *
14508 * @Injectable()
14509 * class Car {
14510 * constructor(public engine:Engine) {}
14511 * }
14512 *
14513 * var providers = ReflectiveInjector.resolve([Car, Engine]);
14514 * var injector = ReflectiveInjector.fromResolvedProviders(providers);
14515 * expect(injector.get(Car) instanceof Car).toBe(true);
14516 * ```
14517 */
14518 static fromResolvedProviders(providers, parent) {
14519 return new ReflectiveInjector_(providers, parent);
14520 }
14521}
14522class ReflectiveInjector_ {
14523 /**
14524 * Private
14525 */
14526 constructor(_providers, _parent) {
14527 /** @internal */
14528 this._constructionCounter = 0;
14529 this._providers = _providers;
14530 this.parent = _parent || null;
14531 const len = _providers.length;
14532 this.keyIds = [];
14533 this.objs = [];
14534 for (let i = 0; i < len; i++) {
14535 this.keyIds[i] = _providers[i].key.id;
14536 this.objs[i] = UNDEFINED;
14537 }
14538 }
14539 get(token, notFoundValue = THROW_IF_NOT_FOUND) {
14540 return this._getByKey(ReflectiveKey.get(token), null, notFoundValue);
14541 }
14542 resolveAndCreateChild(providers) {
14543 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
14544 return this.createChildFromResolved(ResolvedReflectiveProviders);
14545 }
14546 createChildFromResolved(providers) {
14547 const inj = new ReflectiveInjector_(providers);
14548 inj.parent = this;
14549 return inj;
14550 }
14551 resolveAndInstantiate(provider) {
14552 return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]);
14553 }
14554 instantiateResolved(provider) {
14555 return this._instantiateProvider(provider);
14556 }
14557 getProviderAtIndex(index) {
14558 if (index < 0 || index >= this._providers.length) {
14559 throw outOfBoundsError(index);
14560 }
14561 return this._providers[index];
14562 }
14563 /** @internal */
14564 _new(provider) {
14565 if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
14566 throw cyclicDependencyError(this, provider.key);
14567 }
14568 return this._instantiateProvider(provider);
14569 }
14570 _getMaxNumberOfObjects() {
14571 return this.objs.length;
14572 }
14573 _instantiateProvider(provider) {
14574 if (provider.multiProvider) {
14575 const res = [];
14576 for (let i = 0; i < provider.resolvedFactories.length; ++i) {
14577 res[i] = this._instantiate(provider, provider.resolvedFactories[i]);
14578 }
14579 return res;
14580 }
14581 else {
14582 return this._instantiate(provider, provider.resolvedFactories[0]);
14583 }
14584 }
14585 _instantiate(provider, ResolvedReflectiveFactory) {
14586 const factory = ResolvedReflectiveFactory.factory;
14587 let deps;
14588 try {
14589 deps =
14590 ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
14591 }
14592 catch (e) {
14593 if (e.addKey) {
14594 e.addKey(this, provider.key);
14595 }
14596 throw e;
14597 }
14598 let obj;
14599 try {
14600 obj = factory(...deps);
14601 }
14602 catch (e) {
14603 throw instantiationError(this, e, e.stack, provider.key);
14604 }
14605 return obj;
14606 }
14607 _getByReflectiveDependency(dep) {
14608 return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND);
14609 }
14610 _getByKey(key, visibility, notFoundValue) {
14611 if (key === ReflectiveInjector_.INJECTOR_KEY) {
14612 return this;
14613 }
14614 if (visibility instanceof Self) {
14615 return this._getByKeySelf(key, notFoundValue);
14616 }
14617 else {
14618 return this._getByKeyDefault(key, notFoundValue, visibility);
14619 }
14620 }
14621 _getObjByKeyId(keyId) {
14622 for (let i = 0; i < this.keyIds.length; i++) {
14623 if (this.keyIds[i] === keyId) {
14624 if (this.objs[i] === UNDEFINED) {
14625 this.objs[i] = this._new(this._providers[i]);
14626 }
14627 return this.objs[i];
14628 }
14629 }
14630 return UNDEFINED;
14631 }
14632 /** @internal */
14633 _throwOrNull(key, notFoundValue) {
14634 if (notFoundValue !== THROW_IF_NOT_FOUND) {
14635 return notFoundValue;
14636 }
14637 else {
14638 throw noProviderError(this, key);
14639 }
14640 }
14641 /** @internal */
14642 _getByKeySelf(key, notFoundValue) {
14643 const obj = this._getObjByKeyId(key.id);
14644 return (obj !== UNDEFINED) ? obj : this._throwOrNull(key, notFoundValue);
14645 }
14646 /** @internal */
14647 _getByKeyDefault(key, notFoundValue, visibility) {
14648 let inj;
14649 if (visibility instanceof SkipSelf) {
14650 inj = this.parent;
14651 }
14652 else {
14653 inj = this;
14654 }
14655 while (inj instanceof ReflectiveInjector_) {
14656 const inj_ = inj;
14657 const obj = inj_._getObjByKeyId(key.id);
14658 if (obj !== UNDEFINED)
14659 return obj;
14660 inj = inj_.parent;
14661 }
14662 if (inj !== null) {
14663 return inj.get(key.token, notFoundValue);
14664 }
14665 else {
14666 return this._throwOrNull(key, notFoundValue);
14667 }
14668 }
14669 get displayName() {
14670 const providers = _mapProviders(this, (b) => ' "' + b.key.displayName + '" ')
14671 .join(', ');
14672 return `ReflectiveInjector(providers: [${providers}])`;
14673 }
14674 toString() {
14675 return this.displayName;
14676 }
14677}
14678ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
14679function _mapProviders(injector, fn) {
14680 const res = [];
14681 for (let i = 0; i < injector._providers.length; ++i) {
14682 res[i] = fn(injector.getProviderAtIndex(i));
14683 }
14684 return res;
14685}
14686
14687/**
14688 * @license
14689 * Copyright Google LLC All Rights Reserved.
14690 *
14691 * Use of this source code is governed by an MIT-style license that can be
14692 * found in the LICENSE file at https://angular.io/license
14693 */
14694
14695/**
14696 * @license
14697 * Copyright Google LLC All Rights Reserved.
14698 *
14699 * Use of this source code is governed by an MIT-style license that can be
14700 * found in the LICENSE file at https://angular.io/license
14701 */
14702
14703/**
14704 * @license
14705 * Copyright Google LLC All Rights Reserved.
14706 *
14707 * Use of this source code is governed by an MIT-style license that can be
14708 * found in the LICENSE file at https://angular.io/license
14709 */
14710function ɵɵdirectiveInject(token, flags = InjectFlags.Default) {
14711 const lView = getLView();
14712 // Fall back to inject() if view hasn't been created. This situation can happen in tests
14713 // if inject utilities are used before bootstrapping.
14714 if (lView === null) {
14715 // Verify that we will not get into infinite loop.
14716 ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
14717 return ɵɵinject(token, flags);
14718 }
14719 const tNode = getCurrentTNode();
14720 return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
14721}
14722/**
14723 * Throws an error indicating that a factory function could not be generated by the compiler for a
14724 * particular class.
14725 *
14726 * This instruction allows the actual error message to be optimized away when ngDevMode is turned
14727 * off, saving bytes of generated code while still providing a good experience in dev mode.
14728 *
14729 * The name of the class is not mentioned here, but will be in the generated factory function name
14730 * and thus in the stack trace.
14731 *
14732 * @codeGenApi
14733 */
14734function ɵɵinvalidFactory() {
14735 const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';
14736 throw new Error(msg);
14737}
14738
14739/**
14740 * @license
14741 * Copyright Google LLC All Rights Reserved.
14742 *
14743 * Use of this source code is governed by an MIT-style license that can be
14744 * found in the LICENSE file at https://angular.io/license
14745 */
14746/**
14747 * Update a property on a selected element.
14748 *
14749 * Operates on the element selected by index via the {@link select} instruction.
14750 *
14751 * If the property name also exists as an input property on one of the element's directives,
14752 * the component property will be set instead of the element property. This check must
14753 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled
14754 *
14755 * @param propName Name of property. Because it is going to DOM, this is not subject to
14756 * renaming as part of minification.
14757 * @param value New value to write.
14758 * @param sanitizer An optional function used to sanitize the value.
14759 * @returns This function returns itself so that it may be chained
14760 * (e.g. `property('name', ctx.name)('title', ctx.title)`)
14761 *
14762 * @codeGenApi
14763 */
14764function ɵɵproperty(propName, value, sanitizer) {
14765 const lView = getLView();
14766 const bindingIndex = nextBindingIndex();
14767 if (bindingUpdated(lView, bindingIndex, value)) {
14768 const tView = getTView();
14769 const tNode = getSelectedTNode();
14770 elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, false);
14771 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
14772 }
14773 return ɵɵproperty;
14774}
14775/**
14776 * Given `<div style="..." my-dir>` and `MyDir` with `@Input('style')` we need to write to
14777 * directive input.
14778 */
14779function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) {
14780 const inputs = tNode.inputs;
14781 const property = isClassBased ? 'class' : 'style';
14782 // We support both 'class' and `className` hence the fallback.
14783 setInputsForProperty(tView, lView, inputs[property], property, value);
14784}
14785
14786/**
14787 * @license
14788 * Copyright Google LLC All Rights Reserved.
14789 *
14790 * Use of this source code is governed by an MIT-style license that can be
14791 * found in the LICENSE file at https://angular.io/license
14792 */
14793function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) {
14794 ngDevMode && assertFirstCreatePass(tView);
14795 ngDevMode && ngDevMode.firstCreatePass++;
14796 const tViewConsts = tView.consts;
14797 const attrs = getConstant(tViewConsts, attrsIndex);
14798 const tNode = getOrCreateTNode(tView, index, 2 /* Element */, name, attrs);
14799 const hasDirectives = resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
14800 ngDevMode && logUnknownElementError(tView, native, tNode, hasDirectives);
14801 if (tNode.attrs !== null) {
14802 computeStaticStyling(tNode, tNode.attrs, false);
14803 }
14804 if (tNode.mergedAttrs !== null) {
14805 computeStaticStyling(tNode, tNode.mergedAttrs, true);
14806 }
14807 if (tView.queries !== null) {
14808 tView.queries.elementStart(tView, tNode);
14809 }
14810 return tNode;
14811}
14812/**
14813 * Create DOM element. The instruction must later be followed by `elementEnd()` call.
14814 *
14815 * @param index Index of the element in the LView array
14816 * @param name Name of the DOM Node
14817 * @param attrsIndex Index of the element's attributes in the `consts` array.
14818 * @param localRefsIndex Index of the element's local references in the `consts` array.
14819 *
14820 * Attributes and localRefs are passed as an array of strings where elements with an even index
14821 * hold an attribute name and elements with an odd index hold an attribute value, ex.:
14822 * ['id', 'warning5', 'class', 'alert']
14823 *
14824 * @codeGenApi
14825 */
14826function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
14827 const lView = getLView();
14828 const tView = getTView();
14829 const adjustedIndex = HEADER_OFFSET + index;
14830 ngDevMode &&
14831 assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
14832 ngDevMode && assertIndexInRange(lView, adjustedIndex);
14833 const renderer = lView[RENDERER];
14834 const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace$1());
14835 const tNode = tView.firstCreatePass ?
14836 elementStartFirstCreatePass(adjustedIndex, tView, lView, native, name, attrsIndex, localRefsIndex) :
14837 tView.data[adjustedIndex];
14838 setCurrentTNode(tNode, true);
14839 const mergedAttrs = tNode.mergedAttrs;
14840 if (mergedAttrs !== null) {
14841 setUpAttributes(renderer, native, mergedAttrs);
14842 }
14843 const classes = tNode.classes;
14844 if (classes !== null) {
14845 writeDirectClass(renderer, native, classes);
14846 }
14847 const styles = tNode.styles;
14848 if (styles !== null) {
14849 writeDirectStyle(renderer, native, styles);
14850 }
14851 if ((tNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
14852 // In the i18n case, the translation may have removed this element, so only add it if it is not
14853 // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
14854 appendChild(tView, lView, native, tNode);
14855 }
14856 // any immediate children of a component or template container must be pre-emptively
14857 // monkey-patched with the component view data so that the element can be inspected
14858 // later on using any element discovery utility methods (see `element_discovery.ts`)
14859 if (getElementDepthCount() === 0) {
14860 attachPatchData(native, lView);
14861 }
14862 increaseElementDepthCount();
14863 if (isDirectiveHost(tNode)) {
14864 createDirectivesInstances(tView, lView, tNode);
14865 executeContentQueries(tView, tNode, lView);
14866 }
14867 if (localRefsIndex !== null) {
14868 saveResolvedLocalsInData(lView, tNode);
14869 }
14870}
14871/**
14872 * Mark the end of the element.
14873 *
14874 * @codeGenApi
14875 */
14876function ɵɵelementEnd() {
14877 let currentTNode = getCurrentTNode();
14878 ngDevMode && assertDefined(currentTNode, 'No parent node to close.');
14879 if (isCurrentTNodeParent()) {
14880 setCurrentTNodeAsNotParent();
14881 }
14882 else {
14883 ngDevMode && assertHasParent(getCurrentTNode());
14884 currentTNode = currentTNode.parent;
14885 setCurrentTNode(currentTNode, false);
14886 }
14887 const tNode = currentTNode;
14888 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */);
14889 decreaseElementDepthCount();
14890 const tView = getTView();
14891 if (tView.firstCreatePass) {
14892 registerPostOrderHooks(tView, currentTNode);
14893 if (isContentQueryHost(currentTNode)) {
14894 tView.queries.elementEnd(currentTNode);
14895 }
14896 }
14897 if (tNode.classesWithoutHost != null && hasClassInput(tNode)) {
14898 setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true);
14899 }
14900 if (tNode.stylesWithoutHost != null && hasStyleInput(tNode)) {
14901 setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.stylesWithoutHost, false);
14902 }
14903}
14904/**
14905 * Creates an empty element using {@link elementStart} and {@link elementEnd}
14906 *
14907 * @param index Index of the element in the data array
14908 * @param name Name of the DOM Node
14909 * @param attrsIndex Index of the element's attributes in the `consts` array.
14910 * @param localRefsIndex Index of the element's local references in the `consts` array.
14911 *
14912 * @codeGenApi
14913 */
14914function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
14915 ɵɵelementStart(index, name, attrsIndex, localRefsIndex);
14916 ɵɵelementEnd();
14917}
14918function logUnknownElementError(tView, element, tNode, hasDirectives) {
14919 const schemas = tView.schemas;
14920 // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
14921 // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
14922 // defined as an array (as an empty array in case `schemas` field is not defined) and we should
14923 // execute the check below.
14924 if (schemas === null)
14925 return;
14926 const tagName = tNode.value;
14927 // If the element matches any directive, it's considered as valid.
14928 if (!hasDirectives && tagName !== null) {
14929 // The element is unknown if it's an instance of HTMLUnknownElement or it isn't registered
14930 // as a custom element. Note that unknown elements with a dash in their name won't be instances
14931 // of HTMLUnknownElement in browsers that support web components.
14932 const isUnknown =
14933 // Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
14934 // because while most browsers return 'function', IE returns 'object'.
14935 (typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&
14936 element instanceof HTMLUnknownElement) ||
14937 (typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
14938 !customElements.get(tagName));
14939 if (isUnknown && !matchingSchemas(tView, tagName)) {
14940 let message = `'${tagName}' is not a known element:\n`;
14941 message += `1. If '${tagName}' is an Angular component, then verify that it is part of this module.\n`;
14942 if (tagName && tagName.indexOf('-') > -1) {
14943 message += `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`;
14944 }
14945 else {
14946 message +=
14947 `2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
14948 }
14949 console.error(formatRuntimeError("304" /* UNKNOWN_ELEMENT */, message));
14950 }
14951 }
14952}
14953
14954/**
14955 * @license
14956 * Copyright Google LLC All Rights Reserved.
14957 *
14958 * Use of this source code is governed by an MIT-style license that can be
14959 * found in the LICENSE file at https://angular.io/license
14960 */
14961function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
14962 ngDevMode && ngDevMode.firstCreatePass++;
14963 const tViewConsts = tView.consts;
14964 const attrs = getConstant(tViewConsts, attrsIndex);
14965 const tNode = getOrCreateTNode(tView, index, 8 /* ElementContainer */, 'ng-container', attrs);
14966 // While ng-container doesn't necessarily support styling, we use the style context to identify
14967 // and execute directives on the ng-container.
14968 if (attrs !== null) {
14969 computeStaticStyling(tNode, attrs, true);
14970 }
14971 const localRefs = getConstant(tViewConsts, localRefsIndex);
14972 resolveDirectives(tView, lView, tNode, localRefs);
14973 if (tView.queries !== null) {
14974 tView.queries.elementStart(tView, tNode);
14975 }
14976 return tNode;
14977}
14978/**
14979 * Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.
14980 * The instruction must later be followed by `elementContainerEnd()` call.
14981 *
14982 * @param index Index of the element in the LView array
14983 * @param attrsIndex Index of the container attributes in the `consts` array.
14984 * @param localRefsIndex Index of the container's local references in the `consts` array.
14985 *
14986 * Even if this instruction accepts a set of attributes no actual attribute values are propagated to
14987 * the DOM (as a comment node can't have attributes). Attributes are here only for directive
14988 * matching purposes and setting initial inputs of directives.
14989 *
14990 * @codeGenApi
14991 */
14992function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
14993 const lView = getLView();
14994 const tView = getTView();
14995 const adjustedIndex = index + HEADER_OFFSET;
14996 ngDevMode && assertIndexInRange(lView, adjustedIndex);
14997 ngDevMode &&
14998 assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings');
14999 const tNode = tView.firstCreatePass ?
15000 elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex) :
15001 tView.data[adjustedIndex];
15002 setCurrentTNode(tNode, true);
15003 ngDevMode && ngDevMode.rendererCreateComment++;
15004 const native = lView[adjustedIndex] =
15005 lView[RENDERER].createComment(ngDevMode ? 'ng-container' : '');
15006 appendChild(tView, lView, native, tNode);
15007 attachPatchData(native, lView);
15008 if (isDirectiveHost(tNode)) {
15009 createDirectivesInstances(tView, lView, tNode);
15010 executeContentQueries(tView, tNode, lView);
15011 }
15012 if (localRefsIndex != null) {
15013 saveResolvedLocalsInData(lView, tNode);
15014 }
15015}
15016/**
15017 * Mark the end of the <ng-container>.
15018 *
15019 * @codeGenApi
15020 */
15021function ɵɵelementContainerEnd() {
15022 let currentTNode = getCurrentTNode();
15023 const tView = getTView();
15024 if (isCurrentTNodeParent()) {
15025 setCurrentTNodeAsNotParent();
15026 }
15027 else {
15028 ngDevMode && assertHasParent(currentTNode);
15029 currentTNode = currentTNode.parent;
15030 setCurrentTNode(currentTNode, false);
15031 }
15032 ngDevMode && assertTNodeType(currentTNode, 8 /* ElementContainer */);
15033 if (tView.firstCreatePass) {
15034 registerPostOrderHooks(tView, currentTNode);
15035 if (isContentQueryHost(currentTNode)) {
15036 tView.queries.elementEnd(currentTNode);
15037 }
15038 }
15039}
15040/**
15041 * Creates an empty logical container using {@link elementContainerStart}
15042 * and {@link elementContainerEnd}
15043 *
15044 * @param index Index of the element in the LView array
15045 * @param attrsIndex Index of the container attributes in the `consts` array.
15046 * @param localRefsIndex Index of the container's local references in the `consts` array.
15047 *
15048 * @codeGenApi
15049 */
15050function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
15051 ɵɵelementContainerStart(index, attrsIndex, localRefsIndex);
15052 ɵɵelementContainerEnd();
15053}
15054
15055/**
15056 * Returns the current OpaqueViewState instance.
15057 *
15058 * Used in conjunction with the restoreView() instruction to save a snapshot
15059 * of the current view and restore it when listeners are invoked. This allows
15060 * walking the declaration view tree in listeners to get vars from parent views.
15061 *
15062 * @codeGenApi
15063 */
15064function ɵɵgetCurrentView() {
15065 return getLView();
15066}
15067
15068/**
15069 * @license
15070 * Copyright Google LLC All Rights Reserved.
15071 *
15072 * Use of this source code is governed by an MIT-style license that can be
15073 * found in the LICENSE file at https://angular.io/license
15074 */
15075/**
15076 * Determine if the argument is shaped like a Promise
15077 */
15078function isPromise(obj) {
15079 // allow any Promise/A+ compliant thenable.
15080 // It's up to the caller to ensure that obj.then conforms to the spec
15081 return !!obj && typeof obj.then === 'function';
15082}
15083/**
15084 * Determine if the argument is a Subscribable
15085 */
15086function isSubscribable(obj) {
15087 return !!obj && typeof obj.subscribe === 'function';
15088}
15089/**
15090 * Determine if the argument is an Observable
15091 *
15092 * Strictly this tests that the `obj` is `Subscribable`, since `Observable`
15093 * types need additional methods, such as `lift()`. But it is adequate for our
15094 * needs since within the Angular framework code we only ever need to use the
15095 * `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects
15096 * into `Observable` as needed.
15097 */
15098const isObservable = isSubscribable;
15099
15100/**
15101 * @license
15102 * Copyright Google LLC All Rights Reserved.
15103 *
15104 * Use of this source code is governed by an MIT-style license that can be
15105 * found in the LICENSE file at https://angular.io/license
15106 */
15107/**
15108 * Adds an event listener to the current node.
15109 *
15110 * If an output exists on one of the node's directives, it also subscribes to the output
15111 * and saves the subscription for later cleanup.
15112 *
15113 * @param eventName Name of the event
15114 * @param listenerFn The function to be called when event emits
15115 * @param useCapture Whether or not to use capture in event listener
15116 * @param eventTargetResolver Function that returns global target information in case this listener
15117 * should be attached to a global object like window, document or body
15118 *
15119 * @codeGenApi
15120 */
15121function ɵɵlistener(eventName, listenerFn, useCapture, eventTargetResolver) {
15122 const lView = getLView();
15123 const tView = getTView();
15124 const tNode = getCurrentTNode();
15125 listenerInternal(tView, lView, lView[RENDERER], tNode, eventName, listenerFn, !!useCapture, eventTargetResolver);
15126 return ɵɵlistener;
15127}
15128/**
15129 * Registers a synthetic host listener (e.g. `(@foo.start)`) on a component or directive.
15130 *
15131 * This instruction is for compatibility purposes and is designed to ensure that a
15132 * synthetic host listener (e.g. `@HostListener('@foo.start')`) properly gets rendered
15133 * in the component's renderer. Normally all host listeners are evaluated with the
15134 * parent component's renderer, but, in the case of animation @triggers, they need
15135 * to be evaluated with the sub component's renderer (because that's where the
15136 * animation triggers are defined).
15137 *
15138 * Do not use this instruction as a replacement for `listener`. This instruction
15139 * only exists to ensure compatibility with the ViewEngine's host binding behavior.
15140 *
15141 * @param eventName Name of the event
15142 * @param listenerFn The function to be called when event emits
15143 * @param useCapture Whether or not to use capture in event listener
15144 * @param eventTargetResolver Function that returns global target information in case this listener
15145 * should be attached to a global object like window, document or body
15146 *
15147 * @codeGenApi
15148 */
15149function ɵɵsyntheticHostListener(eventName, listenerFn) {
15150 const tNode = getCurrentTNode();
15151 const lView = getLView();
15152 const tView = getTView();
15153 const currentDef = getCurrentDirectiveDef(tView.data);
15154 const renderer = loadComponentRenderer(currentDef, tNode, lView);
15155 listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, false);
15156 return ɵɵsyntheticHostListener;
15157}
15158/**
15159 * A utility function that checks if a given element has already an event handler registered for an
15160 * event with a specified name. The TView.cleanup data structure is used to find out which events
15161 * are registered for a given element.
15162 */
15163function findExistingListener(tView, lView, eventName, tNodeIdx) {
15164 const tCleanup = tView.cleanup;
15165 if (tCleanup != null) {
15166 for (let i = 0; i < tCleanup.length - 1; i += 2) {
15167 const cleanupEventName = tCleanup[i];
15168 if (cleanupEventName === eventName && tCleanup[i + 1] === tNodeIdx) {
15169 // We have found a matching event name on the same node but it might not have been
15170 // registered yet, so we must explicitly verify entries in the LView cleanup data
15171 // structures.
15172 const lCleanup = lView[CLEANUP];
15173 const listenerIdxInLCleanup = tCleanup[i + 2];
15174 return lCleanup.length > listenerIdxInLCleanup ? lCleanup[listenerIdxInLCleanup] : null;
15175 }
15176 // TView.cleanup can have a mix of 4-elements entries (for event handler cleanups) or
15177 // 2-element entries (for directive and queries destroy hooks). As such we can encounter
15178 // blocks of 4 or 2 items in the tView.cleanup and this is why we iterate over 2 elements
15179 // first and jump another 2 elements if we detect listeners cleanup (4 elements). Also check
15180 // documentation of TView.cleanup for more details of this data structure layout.
15181 if (typeof cleanupEventName === 'string') {
15182 i += 2;
15183 }
15184 }
15185 }
15186 return null;
15187}
15188function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver) {
15189 const isTNodeDirectiveHost = isDirectiveHost(tNode);
15190 const firstCreatePass = tView.firstCreatePass;
15191 const tCleanup = firstCreatePass && getOrCreateTViewCleanup(tView);
15192 const context = lView[CONTEXT];
15193 // When the ɵɵlistener instruction was generated and is executed we know that there is either a
15194 // native listener or a directive output on this element. As such we we know that we will have to
15195 // register a listener and store its cleanup function on LView.
15196 const lCleanup = getOrCreateLViewCleanup(lView);
15197 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
15198 let processOutputs = true;
15199 // Adding a native event listener is applicable when:
15200 // - The corresponding TNode represents a DOM element.
15201 // - The event target has a resolver (usually resulting in a global object,
15202 // such as `window` or `document`).
15203 if ((tNode.type & 3 /* AnyRNode */) || eventTargetResolver) {
15204 const native = getNativeByTNode(tNode, lView);
15205 const target = eventTargetResolver ? eventTargetResolver(native) : native;
15206 const lCleanupIndex = lCleanup.length;
15207 const idxOrTargetGetter = eventTargetResolver ?
15208 (_lView) => eventTargetResolver(unwrapRNode(_lView[tNode.index])) :
15209 tNode.index;
15210 // In order to match current behavior, native DOM event listeners must be added for all
15211 // events (including outputs).
15212 if (isProceduralRenderer(renderer)) {
15213 // There might be cases where multiple directives on the same element try to register an event
15214 // handler function for the same event. In this situation we want to avoid registration of
15215 // several native listeners as each registration would be intercepted by NgZone and
15216 // trigger change detection. This would mean that a single user action would result in several
15217 // change detections being invoked. To avoid this situation we want to have only one call to
15218 // native handler registration (for the same element and same type of event).
15219 //
15220 // In order to have just one native event handler in presence of multiple handler functions,
15221 // we just register a first handler function as a native event listener and then chain
15222 // (coalesce) other handler functions on top of the first native handler function.
15223 let existingListener = null;
15224 // Please note that the coalescing described here doesn't happen for events specifying an
15225 // alternative target (ex. (document:click)) - this is to keep backward compatibility with the
15226 // view engine.
15227 // Also, we don't have to search for existing listeners is there are no directives
15228 // matching on a given node as we can't register multiple event handlers for the same event in
15229 // a template (this would mean having duplicate attributes).
15230 if (!eventTargetResolver && isTNodeDirectiveHost) {
15231 existingListener = findExistingListener(tView, lView, eventName, tNode.index);
15232 }
15233 if (existingListener !== null) {
15234 // Attach a new listener to coalesced listeners list, maintaining the order in which
15235 // listeners are registered. For performance reasons, we keep a reference to the last
15236 // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through
15237 // the entire set each time we need to add a new listener.
15238 const lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener;
15239 lastListenerFn.__ngNextListenerFn__ = listenerFn;
15240 existingListener.__ngLastListenerFn__ = listenerFn;
15241 processOutputs = false;
15242 }
15243 else {
15244 listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
15245 const cleanupFn = renderer.listen(target, eventName, listenerFn);
15246 ngDevMode && ngDevMode.rendererAddEventListener++;
15247 lCleanup.push(listenerFn, cleanupFn);
15248 tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
15249 }
15250 }
15251 else {
15252 listenerFn = wrapListener(tNode, lView, context, listenerFn, true /** preventDefault */);
15253 target.addEventListener(eventName, listenerFn, useCapture);
15254 ngDevMode && ngDevMode.rendererAddEventListener++;
15255 lCleanup.push(listenerFn);
15256 tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, useCapture);
15257 }
15258 }
15259 else {
15260 // Even if there is no native listener to add, we still need to wrap the listener so that OnPush
15261 // ancestors are marked dirty when an event occurs.
15262 listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
15263 }
15264 // subscribe to directive outputs
15265 const outputs = tNode.outputs;
15266 let props;
15267 if (processOutputs && outputs !== null && (props = outputs[eventName])) {
15268 const propsLength = props.length;
15269 if (propsLength) {
15270 for (let i = 0; i < propsLength; i += 2) {
15271 const index = props[i];
15272 ngDevMode && assertIndexInRange(lView, index);
15273 const minifiedName = props[i + 1];
15274 const directiveInstance = lView[index];
15275 const output = directiveInstance[minifiedName];
15276 if (ngDevMode && !isObservable(output)) {
15277 throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`);
15278 }
15279 const subscription = output.subscribe(listenerFn);
15280 const idx = lCleanup.length;
15281 lCleanup.push(listenerFn, subscription);
15282 tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));
15283 }
15284 }
15285 }
15286}
15287function executeListenerWithErrorHandling(lView, context, listenerFn, e) {
15288 try {
15289 profiler(6 /* OutputStart */, context, listenerFn);
15290 // Only explicitly returning false from a listener should preventDefault
15291 return listenerFn(e) !== false;
15292 }
15293 catch (error) {
15294 handleError(lView, error);
15295 return false;
15296 }
15297 finally {
15298 profiler(7 /* OutputEnd */, context, listenerFn);
15299 }
15300}
15301/**
15302 * Wraps an event listener with a function that marks ancestors dirty and prevents default behavior,
15303 * if applicable.
15304 *
15305 * @param tNode The TNode associated with this listener
15306 * @param lView The LView that contains this listener
15307 * @param listenerFn The listener function to call
15308 * @param wrapWithPreventDefault Whether or not to prevent default behavior
15309 * (the procedural renderer does this already, so in those cases, we should skip)
15310 */
15311function wrapListener(tNode, lView, context, listenerFn, wrapWithPreventDefault) {
15312 // Note: we are performing most of the work in the listener function itself
15313 // to optimize listener registration.
15314 return function wrapListenerIn_markDirtyAndPreventDefault(e) {
15315 // Ivy uses `Function` as a special token that allows us to unwrap the function
15316 // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`.
15317 if (e === Function) {
15318 return listenerFn;
15319 }
15320 // In order to be backwards compatible with View Engine, events on component host nodes
15321 // must also mark the component view itself dirty (i.e. the view that it owns).
15322 const startView = tNode.flags & 2 /* isComponentHost */ ?
15323 getComponentLViewByIndex(tNode.index, lView) :
15324 lView;
15325 // See interfaces/view.ts for more on LViewFlags.ManualOnPush
15326 if ((lView[FLAGS] & 32 /* ManualOnPush */) === 0) {
15327 markViewDirty(startView);
15328 }
15329 let result = executeListenerWithErrorHandling(lView, context, listenerFn, e);
15330 // A just-invoked listener function might have coalesced listeners so we need to check for
15331 // their presence and invoke as needed.
15332 let nextListenerFn = wrapListenerIn_markDirtyAndPreventDefault.__ngNextListenerFn__;
15333 while (nextListenerFn) {
15334 // We should prevent default if any of the listeners explicitly return false
15335 result = executeListenerWithErrorHandling(lView, context, nextListenerFn, e) && result;
15336 nextListenerFn = nextListenerFn.__ngNextListenerFn__;
15337 }
15338 if (wrapWithPreventDefault && result === false) {
15339 e.preventDefault();
15340 // Necessary for legacy browsers that don't support preventDefault (e.g. IE)
15341 e.returnValue = false;
15342 }
15343 return result;
15344 };
15345}
15346
15347/**
15348 * @license
15349 * Copyright Google LLC All Rights Reserved.
15350 *
15351 * Use of this source code is governed by an MIT-style license that can be
15352 * found in the LICENSE file at https://angular.io/license
15353 */
15354
15355/**
15356 * @license
15357 * Copyright Google LLC All Rights Reserved.
15358 *
15359 * Use of this source code is governed by an MIT-style license that can be
15360 * found in the LICENSE file at https://angular.io/license
15361 */
15362/**
15363 * Retrieves a context at the level specified and saves it as the global, contextViewData.
15364 * Will get the next level up if level is not specified.
15365 *
15366 * This is used to save contexts of parent views so they can be bound in embedded views, or
15367 * in conjunction with reference() to bind a ref from a parent view.
15368 *
15369 * @param level The relative level of the view from which to grab context compared to contextVewData
15370 * @returns context
15371 *
15372 * @codeGenApi
15373 */
15374function ɵɵnextContext(level = 1) {
15375 return nextContextImpl(level);
15376}
15377
15378/**
15379 * @license
15380 * Copyright Google LLC All Rights Reserved.
15381 *
15382 * Use of this source code is governed by an MIT-style license that can be
15383 * found in the LICENSE file at https://angular.io/license
15384 */
15385/**
15386 * Checks a given node against matching projection slots and returns the
15387 * determined slot index. Returns "null" if no slot matched the given node.
15388 *
15389 * This function takes into account the parsed ngProjectAs selector from the
15390 * node's attributes. If present, it will check whether the ngProjectAs selector
15391 * matches any of the projection slot selectors.
15392 */
15393function matchingProjectionSlotIndex(tNode, projectionSlots) {
15394 let wildcardNgContentIndex = null;
15395 const ngProjectAsAttrVal = getProjectAsAttrValue(tNode);
15396 for (let i = 0; i < projectionSlots.length; i++) {
15397 const slotValue = projectionSlots[i];
15398 // The last wildcard projection slot should match all nodes which aren't matching
15399 // any selector. This is necessary to be backwards compatible with view engine.
15400 if (slotValue === '*') {
15401 wildcardNgContentIndex = i;
15402 continue;
15403 }
15404 // If we ran into an `ngProjectAs` attribute, we should match its parsed selector
15405 // to the list of selectors, otherwise we fall back to matching against the node.
15406 if (ngProjectAsAttrVal === null ?
15407 isNodeMatchingSelectorList(tNode, slotValue, /* isProjectionMode */ true) :
15408 isSelectorInSelectorList(ngProjectAsAttrVal, slotValue)) {
15409 return i; // first matching selector "captures" a given node
15410 }
15411 }
15412 return wildcardNgContentIndex;
15413}
15414/**
15415 * Instruction to distribute projectable nodes among <ng-content> occurrences in a given template.
15416 * It takes all the selectors from the entire component's template and decides where
15417 * each projected node belongs (it re-distributes nodes among "buckets" where each "bucket" is
15418 * backed by a selector).
15419 *
15420 * This function requires CSS selectors to be provided in 2 forms: parsed (by a compiler) and text,
15421 * un-parsed form.
15422 *
15423 * The parsed form is needed for efficient matching of a node against a given CSS selector.
15424 * The un-parsed, textual form is needed for support of the ngProjectAs attribute.
15425 *
15426 * Having a CSS selector in 2 different formats is not ideal, but alternatives have even more
15427 * drawbacks:
15428 * - having only a textual form would require runtime parsing of CSS selectors;
15429 * - we can't have only a parsed as we can't re-construct textual form from it (as entered by a
15430 * template author).
15431 *
15432 * @param projectionSlots? A collection of projection slots. A projection slot can be based
15433 * on a parsed CSS selectors or set to the wildcard selector ("*") in order to match
15434 * all nodes which do not match any selector. If not specified, a single wildcard
15435 * selector projection slot will be defined.
15436 *
15437 * @codeGenApi
15438 */
15439function ɵɵprojectionDef(projectionSlots) {
15440 const componentNode = getLView()[DECLARATION_COMPONENT_VIEW][T_HOST];
15441 if (!componentNode.projection) {
15442 // If no explicit projection slots are defined, fall back to a single
15443 // projection slot with the wildcard selector.
15444 const numProjectionSlots = projectionSlots ? projectionSlots.length : 1;
15445 const projectionHeads = componentNode.projection =
15446 newArray(numProjectionSlots, null);
15447 const tails = projectionHeads.slice();
15448 let componentChild = componentNode.child;
15449 while (componentChild !== null) {
15450 const slotIndex = projectionSlots ? matchingProjectionSlotIndex(componentChild, projectionSlots) : 0;
15451 if (slotIndex !== null) {
15452 if (tails[slotIndex]) {
15453 tails[slotIndex].projectionNext = componentChild;
15454 }
15455 else {
15456 projectionHeads[slotIndex] = componentChild;
15457 }
15458 tails[slotIndex] = componentChild;
15459 }
15460 componentChild = componentChild.next;
15461 }
15462 }
15463}
15464/**
15465 * Inserts previously re-distributed projected nodes. This instruction must be preceded by a call
15466 * to the projectionDef instruction.
15467 *
15468 * @param nodeIndex
15469 * @param selectorIndex:
15470 * - 0 when the selector is `*` (or unspecified as this is the default value),
15471 * - 1 based index of the selector from the {@link projectionDef}
15472 *
15473 * @codeGenApi
15474 */
15475function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
15476 const lView = getLView();
15477 const tView = getTView();
15478 const tProjectionNode = getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, 16 /* Projection */, null, attrs || null);
15479 // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
15480 if (tProjectionNode.projection === null)
15481 tProjectionNode.projection = selectorIndex;
15482 // `<ng-content>` has no content
15483 setCurrentTNodeAsNotParent();
15484 if ((tProjectionNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
15485 // re-distribution of projectable nodes is stored on a component's view level
15486 applyProjection(tView, lView, tProjectionNode);
15487 }
15488}
15489
15490/**
15491 *
15492 * Update an interpolated property on an element with a lone bound value
15493 *
15494 * Used when the value passed to a property has 1 interpolated value in it, an no additional text
15495 * surrounds that interpolated value:
15496 *
15497 * ```html
15498 * <div title="{{v0}}"></div>
15499 * ```
15500 *
15501 * Its compiled representation is::
15502 *
15503 * ```ts
15504 * ɵɵpropertyInterpolate('title', v0);
15505 * ```
15506 *
15507 * If the property name also exists as an input property on one of the element's directives,
15508 * the component property will be set instead of the element property. This check must
15509 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15510 *
15511 * @param propName The name of the property to update
15512 * @param prefix Static value used for concatenation only.
15513 * @param v0 Value checked for change.
15514 * @param suffix Static value used for concatenation only.
15515 * @param sanitizer An optional sanitizer function
15516 * @returns itself, so that it may be chained.
15517 * @codeGenApi
15518 */
15519function ɵɵpropertyInterpolate(propName, v0, sanitizer) {
15520 ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer);
15521 return ɵɵpropertyInterpolate;
15522}
15523/**
15524 *
15525 * Update an interpolated property on an element with single bound value surrounded by text.
15526 *
15527 * Used when the value passed to a property has 1 interpolated value in it:
15528 *
15529 * ```html
15530 * <div title="prefix{{v0}}suffix"></div>
15531 * ```
15532 *
15533 * Its compiled representation is::
15534 *
15535 * ```ts
15536 * ɵɵpropertyInterpolate1('title', 'prefix', v0, 'suffix');
15537 * ```
15538 *
15539 * If the property name also exists as an input property on one of the element's directives,
15540 * the component property will be set instead of the element property. This check must
15541 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15542 *
15543 * @param propName The name of the property to update
15544 * @param prefix Static value used for concatenation only.
15545 * @param v0 Value checked for change.
15546 * @param suffix Static value used for concatenation only.
15547 * @param sanitizer An optional sanitizer function
15548 * @returns itself, so that it may be chained.
15549 * @codeGenApi
15550 */
15551function ɵɵpropertyInterpolate1(propName, prefix, v0, suffix, sanitizer) {
15552 const lView = getLView();
15553 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
15554 if (interpolatedValue !== NO_CHANGE) {
15555 const tView = getTView();
15556 const tNode = getSelectedTNode();
15557 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15558 ngDevMode &&
15559 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix);
15560 }
15561 return ɵɵpropertyInterpolate1;
15562}
15563/**
15564 *
15565 * Update an interpolated property on an element with 2 bound values surrounded by text.
15566 *
15567 * Used when the value passed to a property has 2 interpolated values in it:
15568 *
15569 * ```html
15570 * <div title="prefix{{v0}}-{{v1}}suffix"></div>
15571 * ```
15572 *
15573 * Its compiled representation is::
15574 *
15575 * ```ts
15576 * ɵɵpropertyInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
15577 * ```
15578 *
15579 * If the property name also exists as an input property on one of the element's directives,
15580 * the component property will be set instead of the element property. This check must
15581 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15582 *
15583 * @param propName The name of the property to update
15584 * @param prefix Static value used for concatenation only.
15585 * @param v0 Value checked for change.
15586 * @param i0 Static value used for concatenation only.
15587 * @param v1 Value checked for change.
15588 * @param suffix Static value used for concatenation only.
15589 * @param sanitizer An optional sanitizer function
15590 * @returns itself, so that it may be chained.
15591 * @codeGenApi
15592 */
15593function ɵɵpropertyInterpolate2(propName, prefix, v0, i0, v1, suffix, sanitizer) {
15594 const lView = getLView();
15595 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
15596 if (interpolatedValue !== NO_CHANGE) {
15597 const tView = getTView();
15598 const tNode = getSelectedTNode();
15599 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15600 ngDevMode &&
15601 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix);
15602 }
15603 return ɵɵpropertyInterpolate2;
15604}
15605/**
15606 *
15607 * Update an interpolated property on an element with 3 bound values surrounded by text.
15608 *
15609 * Used when the value passed to a property has 3 interpolated values in it:
15610 *
15611 * ```html
15612 * <div title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
15613 * ```
15614 *
15615 * Its compiled representation is::
15616 *
15617 * ```ts
15618 * ɵɵpropertyInterpolate3(
15619 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
15620 * ```
15621 *
15622 * If the property name also exists as an input property on one of the element's directives,
15623 * the component property will be set instead of the element property. This check must
15624 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15625 *
15626 * @param propName The name of the property to update
15627 * @param prefix Static value used for concatenation only.
15628 * @param v0 Value checked for change.
15629 * @param i0 Static value used for concatenation only.
15630 * @param v1 Value checked for change.
15631 * @param i1 Static value used for concatenation only.
15632 * @param v2 Value checked for change.
15633 * @param suffix Static value used for concatenation only.
15634 * @param sanitizer An optional sanitizer function
15635 * @returns itself, so that it may be chained.
15636 * @codeGenApi
15637 */
15638function ɵɵpropertyInterpolate3(propName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer) {
15639 const lView = getLView();
15640 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
15641 if (interpolatedValue !== NO_CHANGE) {
15642 const tView = getTView();
15643 const tNode = getSelectedTNode();
15644 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15645 ngDevMode &&
15646 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
15647 }
15648 return ɵɵpropertyInterpolate3;
15649}
15650/**
15651 *
15652 * Update an interpolated property on an element with 4 bound values surrounded by text.
15653 *
15654 * Used when the value passed to a property has 4 interpolated values in it:
15655 *
15656 * ```html
15657 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
15658 * ```
15659 *
15660 * Its compiled representation is::
15661 *
15662 * ```ts
15663 * ɵɵpropertyInterpolate4(
15664 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
15665 * ```
15666 *
15667 * If the property name also exists as an input property on one of the element's directives,
15668 * the component property will be set instead of the element property. This check must
15669 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15670 *
15671 * @param propName The name of the property to update
15672 * @param prefix Static value used for concatenation only.
15673 * @param v0 Value checked for change.
15674 * @param i0 Static value used for concatenation only.
15675 * @param v1 Value checked for change.
15676 * @param i1 Static value used for concatenation only.
15677 * @param v2 Value checked for change.
15678 * @param i2 Static value used for concatenation only.
15679 * @param v3 Value checked for change.
15680 * @param suffix Static value used for concatenation only.
15681 * @param sanitizer An optional sanitizer function
15682 * @returns itself, so that it may be chained.
15683 * @codeGenApi
15684 */
15685function ɵɵpropertyInterpolate4(propName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer) {
15686 const lView = getLView();
15687 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
15688 if (interpolatedValue !== NO_CHANGE) {
15689 const tView = getTView();
15690 const tNode = getSelectedTNode();
15691 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15692 ngDevMode &&
15693 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
15694 }
15695 return ɵɵpropertyInterpolate4;
15696}
15697/**
15698 *
15699 * Update an interpolated property on an element with 5 bound values surrounded by text.
15700 *
15701 * Used when the value passed to a property has 5 interpolated values in it:
15702 *
15703 * ```html
15704 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
15705 * ```
15706 *
15707 * Its compiled representation is::
15708 *
15709 * ```ts
15710 * ɵɵpropertyInterpolate5(
15711 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
15712 * ```
15713 *
15714 * If the property name also exists as an input property on one of the element's directives,
15715 * the component property will be set instead of the element property. This check must
15716 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15717 *
15718 * @param propName The name of the property to update
15719 * @param prefix Static value used for concatenation only.
15720 * @param v0 Value checked for change.
15721 * @param i0 Static value used for concatenation only.
15722 * @param v1 Value checked for change.
15723 * @param i1 Static value used for concatenation only.
15724 * @param v2 Value checked for change.
15725 * @param i2 Static value used for concatenation only.
15726 * @param v3 Value checked for change.
15727 * @param i3 Static value used for concatenation only.
15728 * @param v4 Value checked for change.
15729 * @param suffix Static value used for concatenation only.
15730 * @param sanitizer An optional sanitizer function
15731 * @returns itself, so that it may be chained.
15732 * @codeGenApi
15733 */
15734function ɵɵpropertyInterpolate5(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer) {
15735 const lView = getLView();
15736 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
15737 if (interpolatedValue !== NO_CHANGE) {
15738 const tView = getTView();
15739 const tNode = getSelectedTNode();
15740 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15741 ngDevMode &&
15742 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
15743 }
15744 return ɵɵpropertyInterpolate5;
15745}
15746/**
15747 *
15748 * Update an interpolated property on an element with 6 bound values surrounded by text.
15749 *
15750 * Used when the value passed to a property has 6 interpolated values in it:
15751 *
15752 * ```html
15753 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
15754 * ```
15755 *
15756 * Its compiled representation is::
15757 *
15758 * ```ts
15759 * ɵɵpropertyInterpolate6(
15760 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
15761 * ```
15762 *
15763 * If the property name also exists as an input property on one of the element's directives,
15764 * the component property will be set instead of the element property. This check must
15765 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15766 *
15767 * @param propName The name of the property to update
15768 * @param prefix Static value used for concatenation only.
15769 * @param v0 Value checked for change.
15770 * @param i0 Static value used for concatenation only.
15771 * @param v1 Value checked for change.
15772 * @param i1 Static value used for concatenation only.
15773 * @param v2 Value checked for change.
15774 * @param i2 Static value used for concatenation only.
15775 * @param v3 Value checked for change.
15776 * @param i3 Static value used for concatenation only.
15777 * @param v4 Value checked for change.
15778 * @param i4 Static value used for concatenation only.
15779 * @param v5 Value checked for change.
15780 * @param suffix Static value used for concatenation only.
15781 * @param sanitizer An optional sanitizer function
15782 * @returns itself, so that it may be chained.
15783 * @codeGenApi
15784 */
15785function ɵɵpropertyInterpolate6(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer) {
15786 const lView = getLView();
15787 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
15788 if (interpolatedValue !== NO_CHANGE) {
15789 const tView = getTView();
15790 const tNode = getSelectedTNode();
15791 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15792 ngDevMode &&
15793 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
15794 }
15795 return ɵɵpropertyInterpolate6;
15796}
15797/**
15798 *
15799 * Update an interpolated property on an element with 7 bound values surrounded by text.
15800 *
15801 * Used when the value passed to a property has 7 interpolated values in it:
15802 *
15803 * ```html
15804 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
15805 * ```
15806 *
15807 * Its compiled representation is::
15808 *
15809 * ```ts
15810 * ɵɵpropertyInterpolate7(
15811 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
15812 * ```
15813 *
15814 * If the property name also exists as an input property on one of the element's directives,
15815 * the component property will be set instead of the element property. This check must
15816 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15817 *
15818 * @param propName The name of the property to update
15819 * @param prefix Static value used for concatenation only.
15820 * @param v0 Value checked for change.
15821 * @param i0 Static value used for concatenation only.
15822 * @param v1 Value checked for change.
15823 * @param i1 Static value used for concatenation only.
15824 * @param v2 Value checked for change.
15825 * @param i2 Static value used for concatenation only.
15826 * @param v3 Value checked for change.
15827 * @param i3 Static value used for concatenation only.
15828 * @param v4 Value checked for change.
15829 * @param i4 Static value used for concatenation only.
15830 * @param v5 Value checked for change.
15831 * @param i5 Static value used for concatenation only.
15832 * @param v6 Value checked for change.
15833 * @param suffix Static value used for concatenation only.
15834 * @param sanitizer An optional sanitizer function
15835 * @returns itself, so that it may be chained.
15836 * @codeGenApi
15837 */
15838function ɵɵpropertyInterpolate7(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer) {
15839 const lView = getLView();
15840 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
15841 if (interpolatedValue !== NO_CHANGE) {
15842 const tView = getTView();
15843 const tNode = getSelectedTNode();
15844 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15845 ngDevMode &&
15846 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix);
15847 }
15848 return ɵɵpropertyInterpolate7;
15849}
15850/**
15851 *
15852 * Update an interpolated property on an element with 8 bound values surrounded by text.
15853 *
15854 * Used when the value passed to a property has 8 interpolated values in it:
15855 *
15856 * ```html
15857 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
15858 * ```
15859 *
15860 * Its compiled representation is::
15861 *
15862 * ```ts
15863 * ɵɵpropertyInterpolate8(
15864 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
15865 * ```
15866 *
15867 * If the property name also exists as an input property on one of the element's directives,
15868 * the component property will be set instead of the element property. This check must
15869 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15870 *
15871 * @param propName The name of the property to update
15872 * @param prefix Static value used for concatenation only.
15873 * @param v0 Value checked for change.
15874 * @param i0 Static value used for concatenation only.
15875 * @param v1 Value checked for change.
15876 * @param i1 Static value used for concatenation only.
15877 * @param v2 Value checked for change.
15878 * @param i2 Static value used for concatenation only.
15879 * @param v3 Value checked for change.
15880 * @param i3 Static value used for concatenation only.
15881 * @param v4 Value checked for change.
15882 * @param i4 Static value used for concatenation only.
15883 * @param v5 Value checked for change.
15884 * @param i5 Static value used for concatenation only.
15885 * @param v6 Value checked for change.
15886 * @param i6 Static value used for concatenation only.
15887 * @param v7 Value checked for change.
15888 * @param suffix Static value used for concatenation only.
15889 * @param sanitizer An optional sanitizer function
15890 * @returns itself, so that it may be chained.
15891 * @codeGenApi
15892 */
15893function ɵɵpropertyInterpolate8(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer) {
15894 const lView = getLView();
15895 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
15896 if (interpolatedValue !== NO_CHANGE) {
15897 const tView = getTView();
15898 const tNode = getSelectedTNode();
15899 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15900 ngDevMode &&
15901 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
15902 }
15903 return ɵɵpropertyInterpolate8;
15904}
15905/**
15906 * Update an interpolated property on an element with 9 or more bound values surrounded by text.
15907 *
15908 * Used when the number of interpolated values exceeds 8.
15909 *
15910 * ```html
15911 * <div
15912 * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
15913 * ```
15914 *
15915 * Its compiled representation is::
15916 *
15917 * ```ts
15918 * ɵɵpropertyInterpolateV(
15919 * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
15920 * 'suffix']);
15921 * ```
15922 *
15923 * If the property name also exists as an input property on one of the element's directives,
15924 * the component property will be set instead of the element property. This check must
15925 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15926 *
15927 * @param propName The name of the property to update.
15928 * @param values The collection of values and the strings inbetween those values, beginning with a
15929 * string prefix and ending with a string suffix.
15930 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
15931 * @param sanitizer An optional sanitizer function
15932 * @returns itself, so that it may be chained.
15933 * @codeGenApi
15934 */
15935function ɵɵpropertyInterpolateV(propName, values, sanitizer) {
15936 const lView = getLView();
15937 const interpolatedValue = interpolationV(lView, values);
15938 if (interpolatedValue !== NO_CHANGE) {
15939 const tView = getTView();
15940 const tNode = getSelectedTNode();
15941 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15942 if (ngDevMode) {
15943 const interpolationInBetween = [values[0]]; // prefix
15944 for (let i = 2; i < values.length; i += 2) {
15945 interpolationInBetween.push(values[i]);
15946 }
15947 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
15948 }
15949 }
15950 return ɵɵpropertyInterpolateV;
15951}
15952
15953/**
15954 * @license
15955 * Copyright Google LLC All Rights Reserved.
15956 *
15957 * Use of this source code is governed by an MIT-style license that can be
15958 * found in the LICENSE file at https://angular.io/license
15959 */
15960/**
15961 * NOTE: The word `styling` is used interchangeably as style or class styling.
15962 *
15963 * This file contains code to link styling instructions together so that they can be replayed in
15964 * priority order. The file exists because Ivy styling instruction execution order does not match
15965 * that of the priority order. The purpose of this code is to create a linked list so that the
15966 * instructions can be traversed in priority order when computing the styles.
15967 *
15968 * Assume we are dealing with the following code:
15969 * ```
15970 * @Component({
15971 * template: `
15972 * <my-cmp [style]=" {color: '#001'} "
15973 * [style.color]=" #002 "
15974 * dir-style-color-1
15975 * dir-style-color-2> `
15976 * })
15977 * class ExampleComponent {
15978 * static ngComp = ... {
15979 * ...
15980 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
15981 * ɵɵstyleMap({color: '#001'});
15982 * ɵɵstyleProp('color', '#002');
15983 * ...
15984 * }
15985 * }
15986 *
15987 * @Directive({
15988 * selector: `[dir-style-color-1]',
15989 * })
15990 * class Style1Directive {
15991 * @HostBinding('style') style = {color: '#005'};
15992 * @HostBinding('style.color') color = '#006';
15993 *
15994 * static ngDir = ... {
15995 * ...
15996 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
15997 * ɵɵstyleMap({color: '#005'});
15998 * ɵɵstyleProp('color', '#006');
15999 * ...
16000 * }
16001 * }
16002 *
16003 * @Directive({
16004 * selector: `[dir-style-color-2]',
16005 * })
16006 * class Style2Directive {
16007 * @HostBinding('style') style = {color: '#007'};
16008 * @HostBinding('style.color') color = '#008';
16009 *
16010 * static ngDir = ... {
16011 * ...
16012 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
16013 * ɵɵstyleMap({color: '#007'});
16014 * ɵɵstyleProp('color', '#008');
16015 * ...
16016 * }
16017 * }
16018 *
16019 * @Directive({
16020 * selector: `my-cmp',
16021 * })
16022 * class MyComponent {
16023 * @HostBinding('style') style = {color: '#003'};
16024 * @HostBinding('style.color') color = '#004';
16025 *
16026 * static ngComp = ... {
16027 * ...
16028 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
16029 * ɵɵstyleMap({color: '#003'});
16030 * ɵɵstyleProp('color', '#004');
16031 * ...
16032 * }
16033 * }
16034 * ```
16035 *
16036 * The Order of instruction execution is:
16037 *
16038 * NOTE: the comment binding location is for illustrative purposes only.
16039 *
16040 * ```
16041 * // Template: (ExampleComponent)
16042 * ɵɵstyleMap({color: '#001'}); // Binding index: 10
16043 * ɵɵstyleProp('color', '#002'); // Binding index: 12
16044 * // MyComponent
16045 * ɵɵstyleMap({color: '#003'}); // Binding index: 20
16046 * ɵɵstyleProp('color', '#004'); // Binding index: 22
16047 * // Style1Directive
16048 * ɵɵstyleMap({color: '#005'}); // Binding index: 24
16049 * ɵɵstyleProp('color', '#006'); // Binding index: 26
16050 * // Style2Directive
16051 * ɵɵstyleMap({color: '#007'}); // Binding index: 28
16052 * ɵɵstyleProp('color', '#008'); // Binding index: 30
16053 * ```
16054 *
16055 * The correct priority order of concatenation is:
16056 *
16057 * ```
16058 * // MyComponent
16059 * ɵɵstyleMap({color: '#003'}); // Binding index: 20
16060 * ɵɵstyleProp('color', '#004'); // Binding index: 22
16061 * // Style1Directive
16062 * ɵɵstyleMap({color: '#005'}); // Binding index: 24
16063 * ɵɵstyleProp('color', '#006'); // Binding index: 26
16064 * // Style2Directive
16065 * ɵɵstyleMap({color: '#007'}); // Binding index: 28
16066 * ɵɵstyleProp('color', '#008'); // Binding index: 30
16067 * // Template: (ExampleComponent)
16068 * ɵɵstyleMap({color: '#001'}); // Binding index: 10
16069 * ɵɵstyleProp('color', '#002'); // Binding index: 12
16070 * ```
16071 *
16072 * What color should be rendered?
16073 *
16074 * Once the items are correctly sorted in the list, the answer is simply the last item in the
16075 * concatenation list which is `#002`.
16076 *
16077 * To do so we keep a linked list of all of the bindings which pertain to this element.
16078 * Notice that the bindings are inserted in the order of execution, but the `TView.data` allows
16079 * us to traverse them in the order of priority.
16080 *
16081 * |Idx|`TView.data`|`LView` | Notes
16082 * |---|------------|-----------------|--------------
16083 * |...| | |
16084 * |10 |`null` |`{color: '#001'}`| `ɵɵstyleMap('color', {color: '#001'})`
16085 * |11 |`30 | 12` | ... |
16086 * |12 |`color` |`'#002'` | `ɵɵstyleProp('color', '#002')`
16087 * |13 |`10 | 0` | ... |
16088 * |...| | |
16089 * |20 |`null` |`{color: '#003'}`| `ɵɵstyleMap('color', {color: '#003'})`
16090 * |21 |`0 | 22` | ... |
16091 * |22 |`color` |`'#004'` | `ɵɵstyleProp('color', '#004')`
16092 * |23 |`20 | 24` | ... |
16093 * |24 |`null` |`{color: '#005'}`| `ɵɵstyleMap('color', {color: '#005'})`
16094 * |25 |`22 | 26` | ... |
16095 * |26 |`color` |`'#006'` | `ɵɵstyleProp('color', '#006')`
16096 * |27 |`24 | 28` | ... |
16097 * |28 |`null` |`{color: '#007'}`| `ɵɵstyleMap('color', {color: '#007'})`
16098 * |29 |`26 | 30` | ... |
16099 * |30 |`color` |`'#008'` | `ɵɵstyleProp('color', '#008')`
16100 * |31 |`28 | 10` | ... |
16101 *
16102 * The above data structure allows us to re-concatenate the styling no matter which data binding
16103 * changes.
16104 *
16105 * NOTE: in addition to keeping track of next/previous index the `TView.data` also stores prev/next
16106 * duplicate bit. The duplicate bit if true says there either is a binding with the same name or
16107 * there is a map (which may contain the name). This information is useful in knowing if other
16108 * styles with higher priority need to be searched for overwrites.
16109 *
16110 * NOTE: See `should support example in 'tnode_linked_list.ts' documentation` in
16111 * `tnode_linked_list_spec.ts` for working example.
16112 */
16113let __unused_const_as_closure_does_not_like_standalone_comment_blocks__;
16114/**
16115 * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked
16116 * list of styles and compute the duplicate flag.
16117 *
16118 * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.
16119 *
16120 * The function works by keeping track of `tStylingRange` which contains two pointers pointing to
16121 * the head/tail of the template portion of the styles.
16122 * - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`
16123 * - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`
16124 *
16125 * @param tData The `TData` to insert into.
16126 * @param tNode `TNode` associated with the styling element.
16127 * @param tStylingKey See `TStylingKey`.
16128 * @param index location of where `tStyleValue` should be stored (and linked into list.)
16129 * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of
16130 * template.)
16131 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
16132 * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
16133 */
16134function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) {
16135 ngDevMode && assertFirstUpdatePass(getTView());
16136 let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
16137 let tmplHead = getTStylingRangePrev(tBindings);
16138 let tmplTail = getTStylingRangeNext(tBindings);
16139 tData[index] = tStylingKeyWithStatic;
16140 let isKeyDuplicateOfStatic = false;
16141 let tStylingKey;
16142 if (Array.isArray(tStylingKeyWithStatic)) {
16143 // We are case when the `TStylingKey` contains static fields as well.
16144 const staticKeyValueArray = tStylingKeyWithStatic;
16145 tStylingKey = staticKeyValueArray[1]; // unwrap.
16146 // We need to check if our key is present in the static so that we can mark it as duplicate.
16147 if (tStylingKey === null ||
16148 keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) {
16149 // tStylingKey is present in the statics, need to mark it as duplicate.
16150 isKeyDuplicateOfStatic = true;
16151 }
16152 }
16153 else {
16154 tStylingKey = tStylingKeyWithStatic;
16155 }
16156 if (isHostBinding) {
16157 // We are inserting host bindings
16158 // If we don't have template bindings then `tail` is 0.
16159 const hasTemplateBindings = tmplTail !== 0;
16160 // This is important to know because that means that the `head` can't point to the first
16161 // template bindings (there are none.) Instead the head points to the tail of the template.
16162 if (hasTemplateBindings) {
16163 // template head's "prev" will point to last host binding or to 0 if no host bindings yet
16164 const previousNode = getTStylingRangePrev(tData[tmplHead + 1]);
16165 tData[index + 1] = toTStylingRange(previousNode, tmplHead);
16166 // if a host binding has already been registered, we need to update the next of that host
16167 // binding to point to this one
16168 if (previousNode !== 0) {
16169 // We need to update the template-tail value to point to us.
16170 tData[previousNode + 1] =
16171 setTStylingRangeNext(tData[previousNode + 1], index);
16172 }
16173 // The "previous" of the template binding head should point to this host binding
16174 tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index);
16175 }
16176 else {
16177 tData[index + 1] = toTStylingRange(tmplHead, 0);
16178 // if a host binding has already been registered, we need to update the next of that host
16179 // binding to point to this one
16180 if (tmplHead !== 0) {
16181 // We need to update the template-tail value to point to us.
16182 tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index);
16183 }
16184 // if we don't have template, the head points to template-tail, and needs to be advanced.
16185 tmplHead = index;
16186 }
16187 }
16188 else {
16189 // We are inserting in template section.
16190 // We need to set this binding's "previous" to the current template tail
16191 tData[index + 1] = toTStylingRange(tmplTail, 0);
16192 ngDevMode &&
16193 assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.');
16194 if (tmplHead === 0) {
16195 tmplHead = index;
16196 }
16197 else {
16198 // We need to update the previous value "next" to point to this binding
16199 tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index);
16200 }
16201 tmplTail = index;
16202 }
16203 // Now we need to update / compute the duplicates.
16204 // Starting with our location search towards head (least priority)
16205 if (isKeyDuplicateOfStatic) {
16206 tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]);
16207 }
16208 markDuplicates(tData, tStylingKey, index, true, isClassBinding);
16209 markDuplicates(tData, tStylingKey, index, false, isClassBinding);
16210 markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);
16211 tBindings = toTStylingRange(tmplHead, tmplTail);
16212 if (isClassBinding) {
16213 tNode.classBindings = tBindings;
16214 }
16215 else {
16216 tNode.styleBindings = tBindings;
16217 }
16218}
16219/**
16220 * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.
16221 *
16222 * @param tNode `TNode` where the residual is stored.
16223 * @param tStylingKey `TStylingKey` to store.
16224 * @param tData `TData` associated with the current `LView`.
16225 * @param index location of where `tStyleValue` should be stored (and linked into list.)
16226 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
16227 * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
16228 */
16229function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) {
16230 const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;
16231 if (residual != null /* or undefined */ && typeof tStylingKey == 'string' &&
16232 keyValueArrayIndexOf(residual, tStylingKey) >= 0) {
16233 // We have duplicate in the residual so mark ourselves as duplicate.
16234 tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]);
16235 }
16236}
16237/**
16238 * Marks `TStyleValue`s as duplicates if another style binding in the list has the same
16239 * `TStyleValue`.
16240 *
16241 * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once
16242 * with it set to `false` to search both the previous as well as next items in the list.
16243 *
16244 * No duplicate case
16245 * ```
16246 * [style.color]
16247 * [style.width.px] <<- index
16248 * [style.height.px]
16249 * ```
16250 *
16251 * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no
16252 * duplicates because `width` is not found in any other part of the linked list.
16253 *
16254 * Duplicate case
16255 * ```
16256 * [style.color]
16257 * [style.width.em]
16258 * [style.width.px] <<- index
16259 * ```
16260 * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`
16261 * because `width` is found in the chain.
16262 *
16263 * Map case 1
16264 * ```
16265 * [style.width.px]
16266 * [style.color]
16267 * [style] <<- index
16268 * ```
16269 * In the above case adding `[style]` will produce a duplicate with any other bindings because
16270 * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.
16271 *
16272 * Map case 2
16273 * ```
16274 * [style]
16275 * [style.width.px]
16276 * [style.color] <<- index
16277 * ```
16278 * In the above case adding `[style.color]` will produce a duplicate because there is already a
16279 * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or
16280 * `width`.
16281 *
16282 * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.
16283 * NOTE: We use `style` as example, but same logic is applied to `class`es as well.
16284 *
16285 * @param tData `TData` where the linked list is stored.
16286 * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in
16287 * the linked list.
16288 * @param index Starting location in the linked list to search from
16289 * @param isPrevDir Direction.
16290 * - `true` for previous (lower priority);
16291 * - `false` for next (higher priority).
16292 */
16293function markDuplicates(tData, tStylingKey, index, isPrevDir, isClassBinding) {
16294 const tStylingAtIndex = tData[index + 1];
16295 const isMap = tStylingKey === null;
16296 let cursor = isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex);
16297 let foundDuplicate = false;
16298 // We keep iterating as long as we have a cursor
16299 // AND either:
16300 // - we found what we are looking for, OR
16301 // - we are a map in which case we have to continue searching even after we find what we were
16302 // looking for since we are a wild card and everything needs to be flipped to duplicate.
16303 while (cursor !== 0 && (foundDuplicate === false || isMap)) {
16304 ngDevMode && assertIndexInRange(tData, cursor);
16305 const tStylingValueAtCursor = tData[cursor];
16306 const tStyleRangeAtCursor = tData[cursor + 1];
16307 if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
16308 foundDuplicate = true;
16309 tData[cursor + 1] = isPrevDir ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor) :
16310 setTStylingRangePrevDuplicate(tStyleRangeAtCursor);
16311 }
16312 cursor = isPrevDir ? getTStylingRangePrev(tStyleRangeAtCursor) :
16313 getTStylingRangeNext(tStyleRangeAtCursor);
16314 }
16315 if (foundDuplicate) {
16316 // if we found a duplicate, than mark ourselves.
16317 tData[index + 1] = isPrevDir ? setTStylingRangePrevDuplicate(tStylingAtIndex) :
16318 setTStylingRangeNextDuplicate(tStylingAtIndex);
16319 }
16320}
16321/**
16322 * Determines if two `TStylingKey`s are a match.
16323 *
16324 * When computing whether a binding contains a duplicate, we need to compare if the instruction
16325 * `TStylingKey` has a match.
16326 *
16327 * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:
16328 * - `color`
16329 * - `color` // Match another color
16330 * - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction
16331 * - `['', 'color', 'other', true]` // wrapped `color` so match
16332 * - `['', null, 'other', true]` // wrapped `null` so match
16333 * - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`
16334 * - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction
16335 *
16336 * @param tStylingKeyCursor
16337 * @param tStylingKey
16338 */
16339function isStylingMatch(tStylingKeyCursor, tStylingKey) {
16340 ngDevMode &&
16341 assertNotEqual(Array.isArray(tStylingKey), true, 'Expected that \'tStylingKey\' has been unwrapped');
16342 if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that
16343 // location so we must assume that we have a match.
16344 tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it
16345 // contains a match.
16346 (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) ===
16347 tStylingKey // If the keys match explicitly than we are a match.
16348 ) {
16349 return true;
16350 }
16351 else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {
16352 // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has
16353 // statics and we need to check those as well.
16354 return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >=
16355 0; // see if we are matching the key
16356 }
16357 return false;
16358}
16359
16360/**
16361 * @license
16362 * Copyright Google LLC All Rights Reserved.
16363 *
16364 * Use of this source code is governed by an MIT-style license that can be
16365 * found in the LICENSE file at https://angular.io/license
16366 */
16367// Global state of the parser. (This makes parser non-reentrant, but that is not an issue)
16368const parserState = {
16369 textEnd: 0,
16370 key: 0,
16371 keyEnd: 0,
16372 value: 0,
16373 valueEnd: 0,
16374};
16375/**
16376 * Retrieves the last parsed `key` of style.
16377 * @param text the text to substring the key from.
16378 */
16379function getLastParsedKey(text) {
16380 return text.substring(parserState.key, parserState.keyEnd);
16381}
16382/**
16383 * Retrieves the last parsed `value` of style.
16384 * @param text the text to substring the key from.
16385 */
16386function getLastParsedValue(text) {
16387 return text.substring(parserState.value, parserState.valueEnd);
16388}
16389/**
16390 * Initializes `className` string for parsing and parses the first token.
16391 *
16392 * This function is intended to be used in this format:
16393 * ```
16394 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
16395 * const key = getLastParsedKey();
16396 * ...
16397 * }
16398 * ```
16399 * @param text `className` to parse
16400 * @returns index where the next invocation of `parseClassNameNext` should resume.
16401 */
16402function parseClassName(text) {
16403 resetParserState(text);
16404 return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd));
16405}
16406/**
16407 * Parses next `className` token.
16408 *
16409 * This function is intended to be used in this format:
16410 * ```
16411 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
16412 * const key = getLastParsedKey();
16413 * ...
16414 * }
16415 * ```
16416 *
16417 * @param text `className` to parse
16418 * @param index where the parsing should resume.
16419 * @returns index where the next invocation of `parseClassNameNext` should resume.
16420 */
16421function parseClassNameNext(text, index) {
16422 const end = parserState.textEnd;
16423 if (end === index) {
16424 return -1;
16425 }
16426 index = parserState.keyEnd = consumeClassToken(text, parserState.key = index, end);
16427 return consumeWhitespace(text, index, end);
16428}
16429/**
16430 * Initializes `cssText` string for parsing and parses the first key/values.
16431 *
16432 * This function is intended to be used in this format:
16433 * ```
16434 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
16435 * const key = getLastParsedKey();
16436 * const value = getLastParsedValue();
16437 * ...
16438 * }
16439 * ```
16440 * @param text `cssText` to parse
16441 * @returns index where the next invocation of `parseStyleNext` should resume.
16442 */
16443function parseStyle(text) {
16444 resetParserState(text);
16445 return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd));
16446}
16447/**
16448 * Parses the next `cssText` key/values.
16449 *
16450 * This function is intended to be used in this format:
16451 * ```
16452 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
16453 * const key = getLastParsedKey();
16454 * const value = getLastParsedValue();
16455 * ...
16456 * }
16457 *
16458 * @param text `cssText` to parse
16459 * @param index where the parsing should resume.
16460 * @returns index where the next invocation of `parseStyleNext` should resume.
16461 */
16462function parseStyleNext(text, startIndex) {
16463 const end = parserState.textEnd;
16464 let index = parserState.key = consumeWhitespace(text, startIndex, end);
16465 if (end === index) {
16466 // we reached an end so just quit
16467 return -1;
16468 }
16469 index = parserState.keyEnd = consumeStyleKey(text, index, end);
16470 index = consumeSeparator(text, index, end, 58 /* COLON */);
16471 index = parserState.value = consumeWhitespace(text, index, end);
16472 index = parserState.valueEnd = consumeStyleValue(text, index, end);
16473 return consumeSeparator(text, index, end, 59 /* SEMI_COLON */);
16474}
16475/**
16476 * Reset the global state of the styling parser.
16477 * @param text The styling text to parse.
16478 */
16479function resetParserState(text) {
16480 parserState.key = 0;
16481 parserState.keyEnd = 0;
16482 parserState.value = 0;
16483 parserState.valueEnd = 0;
16484 parserState.textEnd = text.length;
16485}
16486/**
16487 * Returns index of next non-whitespace character.
16488 *
16489 * @param text Text to scan
16490 * @param startIndex Starting index of character where the scan should start.
16491 * @param endIndex Ending index of character where the scan should end.
16492 * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at
16493 * that location.)
16494 */
16495function consumeWhitespace(text, startIndex, endIndex) {
16496 while (startIndex < endIndex && text.charCodeAt(startIndex) <= 32 /* SPACE */) {
16497 startIndex++;
16498 }
16499 return startIndex;
16500}
16501/**
16502 * Returns index of last char in class token.
16503 *
16504 * @param text Text to scan
16505 * @param startIndex Starting index of character where the scan should start.
16506 * @param endIndex Ending index of character where the scan should end.
16507 * @returns Index after last char in class token.
16508 */
16509function consumeClassToken(text, startIndex, endIndex) {
16510 while (startIndex < endIndex && text.charCodeAt(startIndex) > 32 /* SPACE */) {
16511 startIndex++;
16512 }
16513 return startIndex;
16514}
16515/**
16516 * Consumes all of the characters belonging to style key and token.
16517 *
16518 * @param text Text to scan
16519 * @param startIndex Starting index of character where the scan should start.
16520 * @param endIndex Ending index of character where the scan should end.
16521 * @returns Index after last style key character.
16522 */
16523function consumeStyleKey(text, startIndex, endIndex) {
16524 let ch;
16525 while (startIndex < endIndex &&
16526 ((ch = text.charCodeAt(startIndex)) === 45 /* DASH */ || ch === 95 /* UNDERSCORE */ ||
16527 ((ch & -33 /* UPPER_CASE */) >= 65 /* A */ && (ch & -33 /* UPPER_CASE */) <= 90 /* Z */) ||
16528 (ch >= 48 /* ZERO */ && ch <= 57 /* NINE */))) {
16529 startIndex++;
16530 }
16531 return startIndex;
16532}
16533/**
16534 * Consumes all whitespace and the separator `:` after the style key.
16535 *
16536 * @param text Text to scan
16537 * @param startIndex Starting index of character where the scan should start.
16538 * @param endIndex Ending index of character where the scan should end.
16539 * @returns Index after separator and surrounding whitespace.
16540 */
16541function consumeSeparator(text, startIndex, endIndex, separator) {
16542 startIndex = consumeWhitespace(text, startIndex, endIndex);
16543 if (startIndex < endIndex) {
16544 if (ngDevMode && text.charCodeAt(startIndex) !== separator) {
16545 malformedStyleError(text, String.fromCharCode(separator), startIndex);
16546 }
16547 startIndex++;
16548 }
16549 return startIndex;
16550}
16551/**
16552 * Consumes style value honoring `url()` and `""` text.
16553 *
16554 * @param text Text to scan
16555 * @param startIndex Starting index of character where the scan should start.
16556 * @param endIndex Ending index of character where the scan should end.
16557 * @returns Index after last style value character.
16558 */
16559function consumeStyleValue(text, startIndex, endIndex) {
16560 let ch1 = -1; // 1st previous character
16561 let ch2 = -1; // 2nd previous character
16562 let ch3 = -1; // 3rd previous character
16563 let i = startIndex;
16564 let lastChIndex = i;
16565 while (i < endIndex) {
16566 const ch = text.charCodeAt(i++);
16567 if (ch === 59 /* SEMI_COLON */) {
16568 return lastChIndex;
16569 }
16570 else if (ch === 34 /* DOUBLE_QUOTE */ || ch === 39 /* SINGLE_QUOTE */) {
16571 lastChIndex = i = consumeQuotedText(text, ch, i, endIndex);
16572 }
16573 else if (startIndex ===
16574 i - 4 && // We have seen only 4 characters so far "URL(" (Ignore "foo_URL()")
16575 ch3 === 85 /* U */ &&
16576 ch2 === 82 /* R */ && ch1 === 76 /* L */ && ch === 40 /* OPEN_PAREN */) {
16577 lastChIndex = i = consumeQuotedText(text, 41 /* CLOSE_PAREN */, i, endIndex);
16578 }
16579 else if (ch > 32 /* SPACE */) {
16580 // if we have a non-whitespace character then capture its location
16581 lastChIndex = i;
16582 }
16583 ch3 = ch2;
16584 ch2 = ch1;
16585 ch1 = ch & -33 /* UPPER_CASE */;
16586 }
16587 return lastChIndex;
16588}
16589/**
16590 * Consumes all of the quoted characters.
16591 *
16592 * @param text Text to scan
16593 * @param quoteCharCode CharCode of either `"` or `'` quote or `)` for `url(...)`.
16594 * @param startIndex Starting index of character where the scan should start.
16595 * @param endIndex Ending index of character where the scan should end.
16596 * @returns Index after quoted characters.
16597 */
16598function consumeQuotedText(text, quoteCharCode, startIndex, endIndex) {
16599 let ch1 = -1; // 1st previous character
16600 let index = startIndex;
16601 while (index < endIndex) {
16602 const ch = text.charCodeAt(index++);
16603 if (ch == quoteCharCode && ch1 !== 92 /* BACK_SLASH */) {
16604 return index;
16605 }
16606 if (ch == 92 /* BACK_SLASH */ && ch1 === 92 /* BACK_SLASH */) {
16607 // two back slashes cancel each other out. For example `"\\"` should properly end the
16608 // quotation. (It should not assume that the last `"` is escaped.)
16609 ch1 = 0;
16610 }
16611 else {
16612 ch1 = ch;
16613 }
16614 }
16615 throw ngDevMode ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex) :
16616 new Error();
16617}
16618function malformedStyleError(text, expecting, index) {
16619 ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here');
16620 throw throwError(`Malformed style at location ${index} in string '` + text.substring(0, index) + '[>>' +
16621 text.substring(index, index + 1) + '<<]' + text.substr(index + 1) +
16622 `'. Expecting '${expecting}'.`);
16623}
16624
16625/**
16626 * @license
16627 * Copyright Google LLC All Rights Reserved.
16628 *
16629 * Use of this source code is governed by an MIT-style license that can be
16630 * found in the LICENSE file at https://angular.io/license
16631 */
16632/**
16633 * Update a style binding on an element with the provided value.
16634 *
16635 * If the style value is falsy then it will be removed from the element
16636 * (or assigned a different value depending if there are any styles placed
16637 * on the element with `styleMap` or any static styles that are
16638 * present from when the element was created with `styling`).
16639 *
16640 * Note that the styling element is updated as part of `stylingApply`.
16641 *
16642 * @param prop A valid CSS property.
16643 * @param value New value to write (`null` or an empty string to remove).
16644 * @param suffix Optional suffix. Used with scalar values to add unit such as `px`.
16645 *
16646 * Note that this will apply the provided style value to the host element if this function is called
16647 * within a host binding function.
16648 *
16649 * @codeGenApi
16650 */
16651function ɵɵstyleProp(prop, value, suffix) {
16652 checkStylingProperty(prop, value, suffix, false);
16653 return ɵɵstyleProp;
16654}
16655/**
16656 * Update a class binding on an element with the provided value.
16657 *
16658 * This instruction is meant to handle the `[class.foo]="exp"` case and,
16659 * therefore, the class binding itself must already be allocated using
16660 * `styling` within the creation block.
16661 *
16662 * @param prop A valid CSS class (only one).
16663 * @param value A true/false value which will turn the class on or off.
16664 *
16665 * Note that this will apply the provided class value to the host element if this function
16666 * is called within a host binding function.
16667 *
16668 * @codeGenApi
16669 */
16670function ɵɵclassProp(className, value) {
16671 checkStylingProperty(className, value, null, true);
16672 return ɵɵclassProp;
16673}
16674/**
16675 * Update style bindings using an object literal on an element.
16676 *
16677 * This instruction is meant to apply styling via the `[style]="exp"` template bindings.
16678 * When styles are applied to the element they will then be updated with respect to
16679 * any styles/classes set via `styleProp`. If any styles are set to falsy
16680 * then they will be removed from the element.
16681 *
16682 * Note that the styling instruction will not be applied until `stylingApply` is called.
16683 *
16684 * @param styles A key/value style map of the styles that will be applied to the given element.
16685 * Any missing styles (that have already been applied to the element beforehand) will be
16686 * removed (unset) from the element's styling.
16687 *
16688 * Note that this will apply the provided styleMap value to the host element if this function
16689 * is called within a host binding.
16690 *
16691 * @codeGenApi
16692 */
16693function ɵɵstyleMap(styles) {
16694 checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false);
16695}
16696/**
16697 * Parse text as style and add values to KeyValueArray.
16698 *
16699 * This code is pulled out to a separate function so that it can be tree shaken away if it is not
16700 * needed. It is only referenced from `ɵɵstyleMap`.
16701 *
16702 * @param keyValueArray KeyValueArray to add parsed values to.
16703 * @param text text to parse.
16704 */
16705function styleStringParser(keyValueArray, text) {
16706 for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) {
16707 styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text));
16708 }
16709}
16710/**
16711 * Update class bindings using an object literal or class-string on an element.
16712 *
16713 * This instruction is meant to apply styling via the `[class]="exp"` template bindings.
16714 * When classes are applied to the element they will then be updated with
16715 * respect to any styles/classes set via `classProp`. If any
16716 * classes are set to falsy then they will be removed from the element.
16717 *
16718 * Note that the styling instruction will not be applied until `stylingApply` is called.
16719 * Note that this will the provided classMap value to the host element if this function is called
16720 * within a host binding.
16721 *
16722 * @param classes A key/value map or string of CSS classes that will be added to the
16723 * given element. Any missing classes (that have already been applied to the element
16724 * beforehand) will be removed (unset) from the element's list of CSS classes.
16725 *
16726 * @codeGenApi
16727 */
16728function ɵɵclassMap(classes) {
16729 checkStylingMap(keyValueArraySet, classStringParser, classes, true);
16730}
16731/**
16732 * Parse text as class and add values to KeyValueArray.
16733 *
16734 * This code is pulled out to a separate function so that it can be tree shaken away if it is not
16735 * needed. It is only referenced from `ɵɵclassMap`.
16736 *
16737 * @param keyValueArray KeyValueArray to add parsed values to.
16738 * @param text text to parse.
16739 */
16740function classStringParser(keyValueArray, text) {
16741 for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
16742 keyValueArraySet(keyValueArray, getLastParsedKey(text), true);
16743 }
16744}
16745/**
16746 * Common code between `ɵɵclassProp` and `ɵɵstyleProp`.
16747 *
16748 * @param prop property name.
16749 * @param value binding value.
16750 * @param suffix suffix for the property (e.g. `em` or `px`)
16751 * @param isClassBased `true` if `class` change (`false` if `style`)
16752 */
16753function checkStylingProperty(prop, value, suffix, isClassBased) {
16754 const lView = getLView();
16755 const tView = getTView();
16756 // Styling instructions use 2 slots per binding.
16757 // 1. one for the value / TStylingKey
16758 // 2. one for the intermittent-value / TStylingRange
16759 const bindingIndex = incrementBindingIndex(2);
16760 if (tView.firstUpdatePass) {
16761 stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);
16762 }
16763 if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
16764 const tNode = tView.data[getSelectedIndex()];
16765 updateStyling(tView, tNode, lView, lView[RENDERER], prop, lView[bindingIndex + 1] = normalizeSuffix(value, suffix), isClassBased, bindingIndex);
16766 }
16767}
16768/**
16769 * Common code between `ɵɵclassMap` and `ɵɵstyleMap`.
16770 *
16771 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
16772 * function so that `style` can be processed. This is done for tree shaking purposes.
16773 * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class`
16774 * have different parsers.)
16775 * @param value bound value from application
16776 * @param isClassBased `true` if `class` change (`false` if `style`)
16777 */
16778function checkStylingMap(keyValueArraySet, stringParser, value, isClassBased) {
16779 const tView = getTView();
16780 const bindingIndex = incrementBindingIndex(2);
16781 if (tView.firstUpdatePass) {
16782 stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
16783 }
16784 const lView = getLView();
16785 if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
16786 // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
16787 // if so as not to read unnecessarily.
16788 const tNode = tView.data[getSelectedIndex()];
16789 if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) {
16790 if (ngDevMode) {
16791 // verify that if we are shadowing then `TData` is appropriately marked so that we skip
16792 // processing this binding in styling resolution.
16793 const tStylingKey = tView.data[bindingIndex];
16794 assertEqual(Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false, 'Styling linked list shadow input should be marked as \'false\'');
16795 }
16796 // VE does not concatenate the static portion like we are doing here.
16797 // Instead VE just ignores the static completely if dynamic binding is present.
16798 // Because of locality we have already set the static portion because we don't know if there
16799 // is a dynamic portion until later. If we would ignore the static portion it would look like
16800 // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong
16801 // thing as it would think that the static portion was removed. For this reason we
16802 // concatenate it so that `[ngStyle]`/`[ngClass]` can continue to work on changed.
16803 let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost;
16804 ngDevMode && isClassBased === false && staticPrefix !== null &&
16805 assertEqual(staticPrefix.endsWith(';'), true, 'Expecting static portion to end with \';\'');
16806 if (staticPrefix !== null) {
16807 // We want to make sure that falsy values of `value` become empty strings.
16808 value = concatStringsWithSpace(staticPrefix, value ? value : '');
16809 }
16810 // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.
16811 // This takes over the `[style]` binding. (Same for `[class]`)
16812 setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);
16813 }
16814 else {
16815 updateStylingMap(tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1], lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value), isClassBased, bindingIndex);
16816 }
16817 }
16818}
16819/**
16820 * Determines when the binding is in `hostBindings` section
16821 *
16822 * @param tView Current `TView`
16823 * @param bindingIndex index of binding which we would like if it is in `hostBindings`
16824 */
16825function isInHostBindings(tView, bindingIndex) {
16826 // All host bindings are placed after the expando section.
16827 return bindingIndex >= tView.expandoStartIndex;
16828}
16829/**
16830 * Collects the necessary information to insert the binding into a linked list of style bindings
16831 * using `insertTStylingBinding`.
16832 *
16833 * @param tView `TView` where the binding linked list will be stored.
16834 * @param tStylingKey Property/key of the binding.
16835 * @param bindingIndex Index of binding associated with the `prop`
16836 * @param isClassBased `true` if `class` change (`false` if `style`)
16837 */
16838function stylingFirstUpdatePass(tView, tStylingKey, bindingIndex, isClassBased) {
16839 ngDevMode && assertFirstUpdatePass(tView);
16840 const tData = tView.data;
16841 if (tData[bindingIndex + 1] === null) {
16842 // The above check is necessary because we don't clear first update pass until first successful
16843 // (no exception) template execution. This prevents the styling instruction from double adding
16844 // itself to the list.
16845 // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
16846 // if so as not to read unnecessarily.
16847 const tNode = tData[getSelectedIndex()];
16848 ngDevMode && assertDefined(tNode, 'TNode expected');
16849 const isHostBindings = isInHostBindings(tView, bindingIndex);
16850 if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) {
16851 // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding.
16852 // If there is a directive which uses `@Input('style')` or `@Input('class')` than
16853 // we need to neutralize this binding since that directive is shadowing it.
16854 // We turn this into a noop by setting the key to `false`
16855 tStylingKey = false;
16856 }
16857 tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased);
16858 insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased);
16859 }
16860}
16861/**
16862 * Adds static styling information to the binding if applicable.
16863 *
16864 * The linked list of styles not only stores the list and keys, but also stores static styling
16865 * information on some of the keys. This function determines if the key should contain the styling
16866 * information and computes it.
16867 *
16868 * See `TStylingStatic` for more details.
16869 *
16870 * @param tData `TData` where the linked list is stored.
16871 * @param tNode `TNode` for which the styling is being computed.
16872 * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey`
16873 * @param isClassBased `true` if `class` (`false` if `style`)
16874 */
16875function wrapInStaticStylingKey(tData, tNode, stylingKey, isClassBased) {
16876 const hostDirectiveDef = getCurrentDirectiveDef(tData);
16877 let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
16878 if (hostDirectiveDef === null) {
16879 // We are in template node.
16880 // If template node already had styling instruction then it has already collected the static
16881 // styling and there is no need to collect them again. We know that we are the first styling
16882 // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet).
16883 const isFirstStylingInstructionInTemplate = (isClassBased ? tNode.classBindings : tNode.styleBindings) === 0;
16884 if (isFirstStylingInstructionInTemplate) {
16885 // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point
16886 // they are already merged and it would not be possible to figure which property belongs where
16887 // in the priority.
16888 stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased);
16889 stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased);
16890 // We know that if we have styling binding in template we can't have residual.
16891 residual = null;
16892 }
16893 }
16894 else {
16895 // We are in host binding node and there was no binding instruction in template node.
16896 // This means that we need to compute the residual.
16897 const directiveStylingLast = tNode.directiveStylingLast;
16898 const isFirstStylingInstructionInHostBinding = directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef;
16899 if (isFirstStylingInstructionInHostBinding) {
16900 stylingKey =
16901 collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased);
16902 if (residual === null) {
16903 // - If `null` than either:
16904 // - Template styling instruction already ran and it has consumed the static
16905 // styling into its `TStylingKey` and so there is no need to update residual. Instead
16906 // we need to update the `TStylingKey` associated with the first template node
16907 // instruction. OR
16908 // - Some other styling instruction ran and determined that there are no residuals
16909 let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased);
16910 if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) {
16911 // Only recompute if `templateStylingKey` had static values. (If no static value found
16912 // then there is nothing to do since this operation can only produce less static keys, not
16913 // more.)
16914 templateStylingKey = collectStylingFromDirectives(null, tData, tNode, templateStylingKey[1] /* unwrap previous statics */, isClassBased);
16915 templateStylingKey =
16916 collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased);
16917 setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey);
16918 }
16919 }
16920 else {
16921 // We only need to recompute residual if it is not `null`.
16922 // - If existing residual (implies there was no template styling). This means that some of
16923 // the statics may have moved from the residual to the `stylingKey` and so we have to
16924 // recompute.
16925 // - If `undefined` this is the first time we are running.
16926 residual = collectResidual(tData, tNode, isClassBased);
16927 }
16928 }
16929 }
16930 if (residual !== undefined) {
16931 isClassBased ? (tNode.residualClasses = residual) : (tNode.residualStyles = residual);
16932 }
16933 return stylingKey;
16934}
16935/**
16936 * Retrieve the `TStylingKey` for the template styling instruction.
16937 *
16938 * This is needed since `hostBinding` styling instructions are inserted after the template
16939 * instruction. While the template instruction needs to update the residual in `TNode` the
16940 * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because
16941 * the template instruction is downstream from the `hostBindings` instructions.
16942 *
16943 * @param tData `TData` where the linked list is stored.
16944 * @param tNode `TNode` for which the styling is being computed.
16945 * @param isClassBased `true` if `class` (`false` if `style`)
16946 * @return `TStylingKey` if found or `undefined` if not found.
16947 */
16948function getTemplateHeadTStylingKey(tData, tNode, isClassBased) {
16949 const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
16950 if (getTStylingRangeNext(bindings) === 0) {
16951 // There does not seem to be a styling instruction in the `template`.
16952 return undefined;
16953 }
16954 return tData[getTStylingRangePrev(bindings)];
16955}
16956/**
16957 * Update the `TStylingKey` of the first template instruction in `TNode`.
16958 *
16959 * Logically `hostBindings` styling instructions are of lower priority than that of the template.
16960 * However, they execute after the template styling instructions. This means that they get inserted
16961 * in front of the template styling instructions.
16962 *
16963 * If we have a template styling instruction and a new `hostBindings` styling instruction is
16964 * executed it means that it may need to steal static fields from the template instruction. This
16965 * method allows us to update the first template instruction `TStylingKey` with a new value.
16966 *
16967 * Assume:
16968 * ```
16969 * <div my-dir style="color: red" [style.color]="tmplExp"></div>
16970 *
16971 * @Directive({
16972 * host: {
16973 * 'style': 'width: 100px',
16974 * '[style.color]': 'dirExp',
16975 * }
16976 * })
16977 * class MyDir {}
16978 * ```
16979 *
16980 * when `[style.color]="tmplExp"` executes it creates this data structure.
16981 * ```
16982 * ['', 'color', 'color', 'red', 'width', '100px'],
16983 * ```
16984 *
16985 * The reason for this is that the template instruction does not know if there are styling
16986 * instructions and must assume that there are none and must collect all of the static styling.
16987 * (both
16988 * `color' and 'width`)
16989 *
16990 * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list.
16991 * ```
16992 * ['', 'color', 'width', '100px'], // newly inserted
16993 * ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong
16994 * ```
16995 *
16996 * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to
16997 * update it like so:
16998 * ```
16999 * ['', 'color', 'width', '100px'],
17000 * ['', 'color', 'color', 'red'], // UPDATE
17001 * ```
17002 *
17003 * @param tData `TData` where the linked list is stored.
17004 * @param tNode `TNode` for which the styling is being computed.
17005 * @param isClassBased `true` if `class` (`false` if `style`)
17006 * @param tStylingKey New `TStylingKey` which is replacing the old one.
17007 */
17008function setTemplateHeadTStylingKey(tData, tNode, isClassBased, tStylingKey) {
17009 const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
17010 ngDevMode &&
17011 assertNotEqual(getTStylingRangeNext(bindings), 0, 'Expecting to have at least one template styling binding.');
17012 tData[getTStylingRangePrev(bindings)] = tStylingKey;
17013}
17014/**
17015 * Collect all static values after the current `TNode.directiveStylingLast` index.
17016 *
17017 * Collect the remaining styling information which has not yet been collected by an existing
17018 * styling instruction.
17019 *
17020 * @param tData `TData` where the `DirectiveDefs` are stored.
17021 * @param tNode `TNode` which contains the directive range.
17022 * @param isClassBased `true` if `class` (`false` if `style`)
17023 */
17024function collectResidual(tData, tNode, isClassBased) {
17025 let residual = undefined;
17026 const directiveEnd = tNode.directiveEnd;
17027 ngDevMode &&
17028 assertNotEqual(tNode.directiveStylingLast, -1, 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.');
17029 // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are
17030 // collecting things after the last `hostBindings` directive which had a styling instruction.)
17031 for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {
17032 const attrs = tData[i].hostAttrs;
17033 residual = collectStylingFromTAttrs(residual, attrs, isClassBased);
17034 }
17035 return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased);
17036}
17037/**
17038 * Collect the static styling information with lower priority than `hostDirectiveDef`.
17039 *
17040 * (This is opposite of residual styling.)
17041 *
17042 * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static
17043 * styling. (Or `null` if template styling)
17044 * @param tData `TData` where the linked list is stored.
17045 * @param tNode `TNode` for which the styling is being computed.
17046 * @param stylingKey Existing `TStylingKey` to update or wrap.
17047 * @param isClassBased `true` if `class` (`false` if `style`)
17048 */
17049function collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased) {
17050 // We need to loop because there can be directives which have `hostAttrs` but don't have
17051 // `hostBindings` so this loop catches up to the current directive..
17052 let currentDirective = null;
17053 const directiveEnd = tNode.directiveEnd;
17054 let directiveStylingLast = tNode.directiveStylingLast;
17055 if (directiveStylingLast === -1) {
17056 directiveStylingLast = tNode.directiveStart;
17057 }
17058 else {
17059 directiveStylingLast++;
17060 }
17061 while (directiveStylingLast < directiveEnd) {
17062 currentDirective = tData[directiveStylingLast];
17063 ngDevMode && assertDefined(currentDirective, 'expected to be defined');
17064 stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased);
17065 if (currentDirective === hostDirectiveDef)
17066 break;
17067 directiveStylingLast++;
17068 }
17069 if (hostDirectiveDef !== null) {
17070 // we only advance the styling cursor if we are collecting data from host bindings.
17071 // Template executes before host bindings and so if we would update the index,
17072 // host bindings would not get their statics.
17073 tNode.directiveStylingLast = directiveStylingLast;
17074 }
17075 return stylingKey;
17076}
17077/**
17078 * Convert `TAttrs` into `TStylingStatic`.
17079 *
17080 * @param stylingKey existing `TStylingKey` to update or wrap.
17081 * @param attrs `TAttributes` to process.
17082 * @param isClassBased `true` if `class` (`false` if `style`)
17083 */
17084function collectStylingFromTAttrs(stylingKey, attrs, isClassBased) {
17085 const desiredMarker = isClassBased ? 1 /* Classes */ : 2 /* Styles */;
17086 let currentMarker = -1 /* ImplicitAttributes */;
17087 if (attrs !== null) {
17088 for (let i = 0; i < attrs.length; i++) {
17089 const item = attrs[i];
17090 if (typeof item === 'number') {
17091 currentMarker = item;
17092 }
17093 else {
17094 if (currentMarker === desiredMarker) {
17095 if (!Array.isArray(stylingKey)) {
17096 stylingKey = stylingKey === undefined ? [] : ['', stylingKey];
17097 }
17098 keyValueArraySet(stylingKey, item, isClassBased ? true : attrs[++i]);
17099 }
17100 }
17101 }
17102 }
17103 return stylingKey === undefined ? null : stylingKey;
17104}
17105/**
17106 * Convert user input to `KeyValueArray`.
17107 *
17108 * This function takes user input which could be `string`, Object literal, or iterable and converts
17109 * it into a consistent representation. The output of this is `KeyValueArray` (which is an array
17110 * where
17111 * even indexes contain keys and odd indexes contain values for those keys).
17112 *
17113 * The advantage of converting to `KeyValueArray` is that we can perform diff in an input
17114 * independent
17115 * way.
17116 * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be
17117 * applied)
17118 *
17119 * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the
17120 * difference in linear fashion without the need to allocate any additional data.
17121 *
17122 * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine
17123 * which values need to be deleted, over the new `Map` to determine additions, and we would have to
17124 * keep additional `Map` to keep track of duplicates or items which have not yet been visited.
17125 *
17126 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
17127 * function so that `style` can be processed. This is done
17128 * for tree shaking purposes.
17129 * @param stringParser The parser is passed in so that it will be tree shakable. See
17130 * `styleStringParser` and `classStringParser`
17131 * @param value The value to parse/convert to `KeyValueArray`
17132 */
17133function toStylingKeyValueArray(keyValueArraySet, stringParser, value) {
17134 if (value == null /*|| value === undefined */ || value === '')
17135 return EMPTY_ARRAY;
17136 const styleKeyValueArray = [];
17137 const unwrappedValue = unwrapSafeValue(value);
17138 if (Array.isArray(unwrappedValue)) {
17139 for (let i = 0; i < unwrappedValue.length; i++) {
17140 keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
17141 }
17142 }
17143 else if (typeof unwrappedValue === 'object') {
17144 for (const key in unwrappedValue) {
17145 if (unwrappedValue.hasOwnProperty(key)) {
17146 keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);
17147 }
17148 }
17149 }
17150 else if (typeof unwrappedValue === 'string') {
17151 stringParser(styleKeyValueArray, unwrappedValue);
17152 }
17153 else {
17154 ngDevMode &&
17155 throwError('Unsupported styling type ' + typeof unwrappedValue + ': ' + unwrappedValue);
17156 }
17157 return styleKeyValueArray;
17158}
17159/**
17160 * Set a `value` for a `key`.
17161 *
17162 * See: `keyValueArraySet` for details
17163 *
17164 * @param keyValueArray KeyValueArray to add to.
17165 * @param key Style key to add.
17166 * @param value The value to set.
17167 */
17168function styleKeyValueArraySet(keyValueArray, key, value) {
17169 keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));
17170}
17171/**
17172 * Update map based styling.
17173 *
17174 * Map based styling could be anything which contains more than one binding. For example `string`,
17175 * or object literal. Dealing with all of these types would complicate the logic so
17176 * instead this function expects that the complex input is first converted into normalized
17177 * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it
17178 * very cheap to compute deltas between the previous and current value.
17179 *
17180 * @param tView Associated `TView.data` contains the linked list of binding priorities.
17181 * @param tNode `TNode` where the binding is located.
17182 * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
17183 * @param renderer Renderer to use if any updates.
17184 * @param oldKeyValueArray Previous value represented as `KeyValueArray`
17185 * @param newKeyValueArray Current value represented as `KeyValueArray`
17186 * @param isClassBased `true` if `class` (`false` if `style`)
17187 * @param bindingIndex Binding index of the binding.
17188 */
17189function updateStylingMap(tView, tNode, lView, renderer, oldKeyValueArray, newKeyValueArray, isClassBased, bindingIndex) {
17190 if (oldKeyValueArray === NO_CHANGE) {
17191 // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray.
17192 oldKeyValueArray = EMPTY_ARRAY;
17193 }
17194 let oldIndex = 0;
17195 let newIndex = 0;
17196 let oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;
17197 let newKey = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null;
17198 while (oldKey !== null || newKey !== null) {
17199 ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?');
17200 ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?');
17201 const oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;
17202 const newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;
17203 let setKey = null;
17204 let setValue = undefined;
17205 if (oldKey === newKey) {
17206 // UPDATE: Keys are equal => new value is overwriting old value.
17207 oldIndex += 2;
17208 newIndex += 2;
17209 if (oldValue !== newValue) {
17210 setKey = newKey;
17211 setValue = newValue;
17212 }
17213 }
17214 else if (newKey === null || oldKey !== null && oldKey < newKey) {
17215 // DELETE: oldKey key is missing or we did not find the oldKey in the newValue
17216 // (because the keyValueArray is sorted and `newKey` is found later alphabetically).
17217 // `"background" < "color"` so we need to delete `"background"` because it is not found in the
17218 // new array.
17219 oldIndex += 2;
17220 setKey = oldKey;
17221 }
17222 else {
17223 // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key.
17224 // `"color" > "background"` so we need to add `color` because it is in new array but not in
17225 // old array.
17226 ngDevMode && assertDefined(newKey, 'Expecting to have a valid key');
17227 newIndex += 2;
17228 setKey = newKey;
17229 setValue = newValue;
17230 }
17231 if (setKey !== null) {
17232 updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex);
17233 }
17234 oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null;
17235 newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null;
17236 }
17237}
17238/**
17239 * Update a simple (property name) styling.
17240 *
17241 * This function takes `prop` and updates the DOM to that value. The function takes the binding
17242 * value as well as binding priority into consideration to determine which value should be written
17243 * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks
17244 * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.)
17245 *
17246 * @param tView Associated `TView.data` contains the linked list of binding priorities.
17247 * @param tNode `TNode` where the binding is located.
17248 * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
17249 * @param renderer Renderer to use if any updates.
17250 * @param prop Either style property name or a class name.
17251 * @param value Either style value for `prop` or `true`/`false` if `prop` is class.
17252 * @param isClassBased `true` if `class` (`false` if `style`)
17253 * @param bindingIndex Binding index of the binding.
17254 */
17255function updateStyling(tView, tNode, lView, renderer, prop, value, isClassBased, bindingIndex) {
17256 if (!(tNode.type & 3 /* AnyRNode */)) {
17257 // It is possible to have styling on non-elements (such as ng-container).
17258 // This is rare, but it does happen. In such a case, just ignore the binding.
17259 return;
17260 }
17261 const tData = tView.data;
17262 const tRange = tData[bindingIndex + 1];
17263 const higherPriorityValue = getTStylingRangeNextDuplicate(tRange) ?
17264 findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased) :
17265 undefined;
17266 if (!isStylingValuePresent(higherPriorityValue)) {
17267 // We don't have a next duplicate, or we did not find a duplicate value.
17268 if (!isStylingValuePresent(value)) {
17269 // We should delete current value or restore to lower priority value.
17270 if (getTStylingRangePrevDuplicate(tRange)) {
17271 // We have a possible prev duplicate, let's retrieve it.
17272 value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased);
17273 }
17274 }
17275 const rNode = getNativeByIndex(getSelectedIndex(), lView);
17276 applyStyling(renderer, isClassBased, rNode, prop, value);
17277 }
17278}
17279/**
17280 * Search for styling value with higher priority which is overwriting current value, or a
17281 * value of lower priority to which we should fall back if the value is `undefined`.
17282 *
17283 * When value is being applied at a location, related values need to be consulted.
17284 * - If there is a higher priority binding, we should be using that one instead.
17285 * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp1`
17286 * requires that we check `exp2` to see if it is set to value other than `undefined`.
17287 * - If there is a lower priority binding and we are changing to `undefined`
17288 * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp2` to
17289 * `undefined` requires that we check `exp1` (and static values) and use that as new value.
17290 *
17291 * NOTE: The styling stores two values.
17292 * 1. The raw value which came from the application is stored at `index + 0` location. (This value
17293 * is used for dirty checking).
17294 * 2. The normalized value is stored at `index + 1`.
17295 *
17296 * @param tData `TData` used for traversing the priority.
17297 * @param tNode `TNode` to use for resolving static styling. Also controls search direction.
17298 * - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
17299 * If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
17300 * - `null` search prev and go all the way to end. Return last value where
17301 * `isStylingValuePresent(value)` is true.
17302 * @param lView `LView` used for retrieving the actual values.
17303 * @param prop Property which we are interested in.
17304 * @param index Starting index in the linked list of styling bindings where the search should start.
17305 * @param isClassBased `true` if `class` (`false` if `style`)
17306 */
17307function findStylingValue(tData, tNode, lView, prop, index, isClassBased) {
17308 // `TNode` to use for resolving static styling. Also controls search direction.
17309 // - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
17310 // If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
17311 // - `null` search prev and go all the way to end. Return last value where
17312 // `isStylingValuePresent(value)` is true.
17313 const isPrevDirection = tNode === null;
17314 let value = undefined;
17315 while (index > 0) {
17316 const rawKey = tData[index];
17317 const containsStatics = Array.isArray(rawKey);
17318 // Unwrap the key if we contain static values.
17319 const key = containsStatics ? rawKey[1] : rawKey;
17320 const isStylingMap = key === null;
17321 let valueAtLViewIndex = lView[index + 1];
17322 if (valueAtLViewIndex === NO_CHANGE) {
17323 // In firstUpdatePass the styling instructions create a linked list of styling.
17324 // On subsequent passes it is possible for a styling instruction to try to read a binding
17325 // which
17326 // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that
17327 // we have `undefined` (or empty array in case of styling-map instruction) instead. This
17328 // allows the resolution to apply the value (which may later be overwritten when the
17329 // binding actually executes.)
17330 valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;
17331 }
17332 let currentValue = isStylingMap ? keyValueArrayGet(valueAtLViewIndex, prop) :
17333 key === prop ? valueAtLViewIndex : undefined;
17334 if (containsStatics && !isStylingValuePresent(currentValue)) {
17335 currentValue = keyValueArrayGet(rawKey, prop);
17336 }
17337 if (isStylingValuePresent(currentValue)) {
17338 value = currentValue;
17339 if (isPrevDirection) {
17340 return value;
17341 }
17342 }
17343 const tRange = tData[index + 1];
17344 index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange);
17345 }
17346 if (tNode !== null) {
17347 // in case where we are going in next direction AND we did not find anything, we need to
17348 // consult residual styling
17349 let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
17350 if (residual != null /** OR residual !=== undefined */) {
17351 value = keyValueArrayGet(residual, prop);
17352 }
17353 }
17354 return value;
17355}
17356/**
17357 * Determines if the binding value should be used (or if the value is 'undefined' and hence priority
17358 * resolution should be used.)
17359 *
17360 * @param value Binding style value.
17361 */
17362function isStylingValuePresent(value) {
17363 // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't
17364 // have an opinion as to what this binding should be and you should consult other bindings by
17365 // priority to determine the valid value.
17366 // This is extracted into a single function so that we have a single place to control this.
17367 return value !== undefined;
17368}
17369/**
17370 * Normalizes and/or adds a suffix to the value.
17371 *
17372 * If value is `null`/`undefined` no suffix is added
17373 * @param value
17374 * @param suffix
17375 */
17376function normalizeSuffix(value, suffix) {
17377 if (value == null /** || value === undefined */) {
17378 // do nothing
17379 }
17380 else if (typeof suffix === 'string') {
17381 value = value + suffix;
17382 }
17383 else if (typeof value === 'object') {
17384 value = stringify(unwrapSafeValue(value));
17385 }
17386 return value;
17387}
17388/**
17389 * Tests if the `TNode` has input shadow.
17390 *
17391 * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or
17392 * `@Input('class')` as input.
17393 *
17394 * @param tNode `TNode` which we would like to see if it has shadow.
17395 * @param isClassBased `true` if `class` (`false` if `style`)
17396 */
17397function hasStylingInputShadow(tNode, isClassBased) {
17398 return (tNode.flags & (isClassBased ? 16 /* hasClassInput */ : 32 /* hasStyleInput */)) !== 0;
17399}
17400
17401/**
17402 * @license
17403 * Copyright Google LLC All Rights Reserved.
17404 *
17405 * Use of this source code is governed by an MIT-style license that can be
17406 * found in the LICENSE file at https://angular.io/license
17407 */
17408/**
17409 * Create static text node
17410 *
17411 * @param index Index of the node in the data array
17412 * @param value Static string value to write.
17413 *
17414 * @codeGenApi
17415 */
17416function ɵɵtext(index, value = '') {
17417 const lView = getLView();
17418 const tView = getTView();
17419 const adjustedIndex = index + HEADER_OFFSET;
17420 ngDevMode &&
17421 assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings');
17422 ngDevMode && assertIndexInRange(lView, adjustedIndex);
17423 const tNode = tView.firstCreatePass ?
17424 getOrCreateTNode(tView, adjustedIndex, 1 /* Text */, value, null) :
17425 tView.data[adjustedIndex];
17426 const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value);
17427 appendChild(tView, lView, textNative, tNode);
17428 // Text nodes are self closing.
17429 setCurrentTNode(tNode, false);
17430}
17431
17432/**
17433 * @license
17434 * Copyright Google LLC All Rights Reserved.
17435 *
17436 * Use of this source code is governed by an MIT-style license that can be
17437 * found in the LICENSE file at https://angular.io/license
17438 */
17439/**
17440 *
17441 * Update text content with a lone bound value
17442 *
17443 * Used when a text node has 1 interpolated value in it, an no additional text
17444 * surrounds that interpolated value:
17445 *
17446 * ```html
17447 * <div>{{v0}}</div>
17448 * ```
17449 *
17450 * Its compiled representation is:
17451 *
17452 * ```ts
17453 * ɵɵtextInterpolate(v0);
17454 * ```
17455 * @returns itself, so that it may be chained.
17456 * @see textInterpolateV
17457 * @codeGenApi
17458 */
17459function ɵɵtextInterpolate(v0) {
17460 ɵɵtextInterpolate1('', v0, '');
17461 return ɵɵtextInterpolate;
17462}
17463/**
17464 *
17465 * Update text content with single bound value surrounded by other text.
17466 *
17467 * Used when a text node has 1 interpolated value in it:
17468 *
17469 * ```html
17470 * <div>prefix{{v0}}suffix</div>
17471 * ```
17472 *
17473 * Its compiled representation is:
17474 *
17475 * ```ts
17476 * ɵɵtextInterpolate1('prefix', v0, 'suffix');
17477 * ```
17478 * @returns itself, so that it may be chained.
17479 * @see textInterpolateV
17480 * @codeGenApi
17481 */
17482function ɵɵtextInterpolate1(prefix, v0, suffix) {
17483 const lView = getLView();
17484 const interpolated = interpolation1(lView, prefix, v0, suffix);
17485 if (interpolated !== NO_CHANGE) {
17486 textBindingInternal(lView, getSelectedIndex(), interpolated);
17487 }
17488 return ɵɵtextInterpolate1;
17489}
17490/**
17491 *
17492 * Update text content with 2 bound values surrounded by other text.
17493 *
17494 * Used when a text node has 2 interpolated values in it:
17495 *
17496 * ```html
17497 * <div>prefix{{v0}}-{{v1}}suffix</div>
17498 * ```
17499 *
17500 * Its compiled representation is:
17501 *
17502 * ```ts
17503 * ɵɵtextInterpolate2('prefix', v0, '-', v1, 'suffix');
17504 * ```
17505 * @returns itself, so that it may be chained.
17506 * @see textInterpolateV
17507 * @codeGenApi
17508 */
17509function ɵɵtextInterpolate2(prefix, v0, i0, v1, suffix) {
17510 const lView = getLView();
17511 const interpolated = interpolation2(lView, prefix, v0, i0, v1, suffix);
17512 if (interpolated !== NO_CHANGE) {
17513 textBindingInternal(lView, getSelectedIndex(), interpolated);
17514 }
17515 return ɵɵtextInterpolate2;
17516}
17517/**
17518 *
17519 * Update text content with 3 bound values surrounded by other text.
17520 *
17521 * Used when a text node has 3 interpolated values in it:
17522 *
17523 * ```html
17524 * <div>prefix{{v0}}-{{v1}}-{{v2}}suffix</div>
17525 * ```
17526 *
17527 * Its compiled representation is:
17528 *
17529 * ```ts
17530 * ɵɵtextInterpolate3(
17531 * 'prefix', v0, '-', v1, '-', v2, 'suffix');
17532 * ```
17533 * @returns itself, so that it may be chained.
17534 * @see textInterpolateV
17535 * @codeGenApi
17536 */
17537function ɵɵtextInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
17538 const lView = getLView();
17539 const interpolated = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
17540 if (interpolated !== NO_CHANGE) {
17541 textBindingInternal(lView, getSelectedIndex(), interpolated);
17542 }
17543 return ɵɵtextInterpolate3;
17544}
17545/**
17546 *
17547 * Update text content with 4 bound values surrounded by other text.
17548 *
17549 * Used when a text node has 4 interpolated values in it:
17550 *
17551 * ```html
17552 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix</div>
17553 * ```
17554 *
17555 * Its compiled representation is:
17556 *
17557 * ```ts
17558 * ɵɵtextInterpolate4(
17559 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
17560 * ```
17561 * @returns itself, so that it may be chained.
17562 * @see ɵɵtextInterpolateV
17563 * @codeGenApi
17564 */
17565function ɵɵtextInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
17566 const lView = getLView();
17567 const interpolated = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
17568 if (interpolated !== NO_CHANGE) {
17569 textBindingInternal(lView, getSelectedIndex(), interpolated);
17570 }
17571 return ɵɵtextInterpolate4;
17572}
17573/**
17574 *
17575 * Update text content with 5 bound values surrounded by other text.
17576 *
17577 * Used when a text node has 5 interpolated values in it:
17578 *
17579 * ```html
17580 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix</div>
17581 * ```
17582 *
17583 * Its compiled representation is:
17584 *
17585 * ```ts
17586 * ɵɵtextInterpolate5(
17587 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
17588 * ```
17589 * @returns itself, so that it may be chained.
17590 * @see textInterpolateV
17591 * @codeGenApi
17592 */
17593function ɵɵtextInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
17594 const lView = getLView();
17595 const interpolated = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
17596 if (interpolated !== NO_CHANGE) {
17597 textBindingInternal(lView, getSelectedIndex(), interpolated);
17598 }
17599 return ɵɵtextInterpolate5;
17600}
17601/**
17602 *
17603 * Update text content with 6 bound values surrounded by other text.
17604 *
17605 * Used when a text node has 6 interpolated values in it:
17606 *
17607 * ```html
17608 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix</div>
17609 * ```
17610 *
17611 * Its compiled representation is:
17612 *
17613 * ```ts
17614 * ɵɵtextInterpolate6(
17615 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
17616 * ```
17617 *
17618 * @param i4 Static value used for concatenation only.
17619 * @param v5 Value checked for change. @returns itself, so that it may be chained.
17620 * @see textInterpolateV
17621 * @codeGenApi
17622 */
17623function ɵɵtextInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
17624 const lView = getLView();
17625 const interpolated = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
17626 if (interpolated !== NO_CHANGE) {
17627 textBindingInternal(lView, getSelectedIndex(), interpolated);
17628 }
17629 return ɵɵtextInterpolate6;
17630}
17631/**
17632 *
17633 * Update text content with 7 bound values surrounded by other text.
17634 *
17635 * Used when a text node has 7 interpolated values in it:
17636 *
17637 * ```html
17638 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix</div>
17639 * ```
17640 *
17641 * Its compiled representation is:
17642 *
17643 * ```ts
17644 * ɵɵtextInterpolate7(
17645 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
17646 * ```
17647 * @returns itself, so that it may be chained.
17648 * @see textInterpolateV
17649 * @codeGenApi
17650 */
17651function ɵɵtextInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
17652 const lView = getLView();
17653 const interpolated = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
17654 if (interpolated !== NO_CHANGE) {
17655 textBindingInternal(lView, getSelectedIndex(), interpolated);
17656 }
17657 return ɵɵtextInterpolate7;
17658}
17659/**
17660 *
17661 * Update text content with 8 bound values surrounded by other text.
17662 *
17663 * Used when a text node has 8 interpolated values in it:
17664 *
17665 * ```html
17666 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix</div>
17667 * ```
17668 *
17669 * Its compiled representation is:
17670 *
17671 * ```ts
17672 * ɵɵtextInterpolate8(
17673 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
17674 * ```
17675 * @returns itself, so that it may be chained.
17676 * @see textInterpolateV
17677 * @codeGenApi
17678 */
17679function ɵɵtextInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
17680 const lView = getLView();
17681 const interpolated = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
17682 if (interpolated !== NO_CHANGE) {
17683 textBindingInternal(lView, getSelectedIndex(), interpolated);
17684 }
17685 return ɵɵtextInterpolate8;
17686}
17687/**
17688 * Update text content with 9 or more bound values other surrounded by text.
17689 *
17690 * Used when the number of interpolated values exceeds 8.
17691 *
17692 * ```html
17693 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix</div>
17694 * ```
17695 *
17696 * Its compiled representation is:
17697 *
17698 * ```ts
17699 * ɵɵtextInterpolateV(
17700 * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
17701 * 'suffix']);
17702 * ```
17703 *.
17704 * @param values The collection of values and the strings in between those values, beginning with
17705 * a string prefix and ending with a string suffix.
17706 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
17707 *
17708 * @returns itself, so that it may be chained.
17709 * @codeGenApi
17710 */
17711function ɵɵtextInterpolateV(values) {
17712 const lView = getLView();
17713 const interpolated = interpolationV(lView, values);
17714 if (interpolated !== NO_CHANGE) {
17715 textBindingInternal(lView, getSelectedIndex(), interpolated);
17716 }
17717 return ɵɵtextInterpolateV;
17718}
17719
17720/**
17721 * @license
17722 * Copyright Google LLC All Rights Reserved.
17723 *
17724 * Use of this source code is governed by an MIT-style license that can be
17725 * found in the LICENSE file at https://angular.io/license
17726 */
17727/**
17728 *
17729 * Update an interpolated class on an element with single bound value surrounded by text.
17730 *
17731 * Used when the value passed to a property has 1 interpolated value in it:
17732 *
17733 * ```html
17734 * <div class="prefix{{v0}}suffix"></div>
17735 * ```
17736 *
17737 * Its compiled representation is:
17738 *
17739 * ```ts
17740 * ɵɵclassMapInterpolate1('prefix', v0, 'suffix');
17741 * ```
17742 *
17743 * @param prefix Static value used for concatenation only.
17744 * @param v0 Value checked for change.
17745 * @param suffix Static value used for concatenation only.
17746 * @codeGenApi
17747 */
17748function ɵɵclassMapInterpolate1(prefix, v0, suffix) {
17749 const lView = getLView();
17750 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
17751 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17752}
17753/**
17754 *
17755 * Update an interpolated class on an element with 2 bound values surrounded by text.
17756 *
17757 * Used when the value passed to a property has 2 interpolated values in it:
17758 *
17759 * ```html
17760 * <div class="prefix{{v0}}-{{v1}}suffix"></div>
17761 * ```
17762 *
17763 * Its compiled representation is:
17764 *
17765 * ```ts
17766 * ɵɵclassMapInterpolate2('prefix', v0, '-', v1, 'suffix');
17767 * ```
17768 *
17769 * @param prefix Static value used for concatenation only.
17770 * @param v0 Value checked for change.
17771 * @param i0 Static value used for concatenation only.
17772 * @param v1 Value checked for change.
17773 * @param suffix Static value used for concatenation only.
17774 * @codeGenApi
17775 */
17776function ɵɵclassMapInterpolate2(prefix, v0, i0, v1, suffix) {
17777 const lView = getLView();
17778 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
17779 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17780}
17781/**
17782 *
17783 * Update an interpolated class on an element with 3 bound values surrounded by text.
17784 *
17785 * Used when the value passed to a property has 3 interpolated values in it:
17786 *
17787 * ```html
17788 * <div class="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
17789 * ```
17790 *
17791 * Its compiled representation is:
17792 *
17793 * ```ts
17794 * ɵɵclassMapInterpolate3(
17795 * 'prefix', v0, '-', v1, '-', v2, 'suffix');
17796 * ```
17797 *
17798 * @param prefix Static value used for concatenation only.
17799 * @param v0 Value checked for change.
17800 * @param i0 Static value used for concatenation only.
17801 * @param v1 Value checked for change.
17802 * @param i1 Static value used for concatenation only.
17803 * @param v2 Value checked for change.
17804 * @param suffix Static value used for concatenation only.
17805 * @codeGenApi
17806 */
17807function ɵɵclassMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
17808 const lView = getLView();
17809 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
17810 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17811}
17812/**
17813 *
17814 * Update an interpolated class on an element with 4 bound values surrounded by text.
17815 *
17816 * Used when the value passed to a property has 4 interpolated values in it:
17817 *
17818 * ```html
17819 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
17820 * ```
17821 *
17822 * Its compiled representation is:
17823 *
17824 * ```ts
17825 * ɵɵclassMapInterpolate4(
17826 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
17827 * ```
17828 *
17829 * @param prefix Static value used for concatenation only.
17830 * @param v0 Value checked for change.
17831 * @param i0 Static value used for concatenation only.
17832 * @param v1 Value checked for change.
17833 * @param i1 Static value used for concatenation only.
17834 * @param v2 Value checked for change.
17835 * @param i2 Static value used for concatenation only.
17836 * @param v3 Value checked for change.
17837 * @param suffix Static value used for concatenation only.
17838 * @codeGenApi
17839 */
17840function ɵɵclassMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
17841 const lView = getLView();
17842 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
17843 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17844}
17845/**
17846 *
17847 * Update an interpolated class on an element with 5 bound values surrounded by text.
17848 *
17849 * Used when the value passed to a property has 5 interpolated values in it:
17850 *
17851 * ```html
17852 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
17853 * ```
17854 *
17855 * Its compiled representation is:
17856 *
17857 * ```ts
17858 * ɵɵclassMapInterpolate5(
17859 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
17860 * ```
17861 *
17862 * @param prefix Static value used for concatenation only.
17863 * @param v0 Value checked for change.
17864 * @param i0 Static value used for concatenation only.
17865 * @param v1 Value checked for change.
17866 * @param i1 Static value used for concatenation only.
17867 * @param v2 Value checked for change.
17868 * @param i2 Static value used for concatenation only.
17869 * @param v3 Value checked for change.
17870 * @param i3 Static value used for concatenation only.
17871 * @param v4 Value checked for change.
17872 * @param suffix Static value used for concatenation only.
17873 * @codeGenApi
17874 */
17875function ɵɵclassMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
17876 const lView = getLView();
17877 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
17878 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17879}
17880/**
17881 *
17882 * Update an interpolated class on an element with 6 bound values surrounded by text.
17883 *
17884 * Used when the value passed to a property has 6 interpolated values in it:
17885 *
17886 * ```html
17887 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
17888 * ```
17889 *
17890 * Its compiled representation is:
17891 *
17892 * ```ts
17893 * ɵɵclassMapInterpolate6(
17894 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
17895 * ```
17896 *
17897 * @param prefix Static value used for concatenation only.
17898 * @param v0 Value checked for change.
17899 * @param i0 Static value used for concatenation only.
17900 * @param v1 Value checked for change.
17901 * @param i1 Static value used for concatenation only.
17902 * @param v2 Value checked for change.
17903 * @param i2 Static value used for concatenation only.
17904 * @param v3 Value checked for change.
17905 * @param i3 Static value used for concatenation only.
17906 * @param v4 Value checked for change.
17907 * @param i4 Static value used for concatenation only.
17908 * @param v5 Value checked for change.
17909 * @param suffix Static value used for concatenation only.
17910 * @codeGenApi
17911 */
17912function ɵɵclassMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
17913 const lView = getLView();
17914 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
17915 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17916}
17917/**
17918 *
17919 * Update an interpolated class on an element with 7 bound values surrounded by text.
17920 *
17921 * Used when the value passed to a property has 7 interpolated values in it:
17922 *
17923 * ```html
17924 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
17925 * ```
17926 *
17927 * Its compiled representation is:
17928 *
17929 * ```ts
17930 * ɵɵclassMapInterpolate7(
17931 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
17932 * ```
17933 *
17934 * @param prefix Static value used for concatenation only.
17935 * @param v0 Value checked for change.
17936 * @param i0 Static value used for concatenation only.
17937 * @param v1 Value checked for change.
17938 * @param i1 Static value used for concatenation only.
17939 * @param v2 Value checked for change.
17940 * @param i2 Static value used for concatenation only.
17941 * @param v3 Value checked for change.
17942 * @param i3 Static value used for concatenation only.
17943 * @param v4 Value checked for change.
17944 * @param i4 Static value used for concatenation only.
17945 * @param v5 Value checked for change.
17946 * @param i5 Static value used for concatenation only.
17947 * @param v6 Value checked for change.
17948 * @param suffix Static value used for concatenation only.
17949 * @codeGenApi
17950 */
17951function ɵɵclassMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
17952 const lView = getLView();
17953 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
17954 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17955}
17956/**
17957 *
17958 * Update an interpolated class on an element with 8 bound values surrounded by text.
17959 *
17960 * Used when the value passed to a property has 8 interpolated values in it:
17961 *
17962 * ```html
17963 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
17964 * ```
17965 *
17966 * Its compiled representation is:
17967 *
17968 * ```ts
17969 * ɵɵclassMapInterpolate8(
17970 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
17971 * ```
17972 *
17973 * @param prefix Static value used for concatenation only.
17974 * @param v0 Value checked for change.
17975 * @param i0 Static value used for concatenation only.
17976 * @param v1 Value checked for change.
17977 * @param i1 Static value used for concatenation only.
17978 * @param v2 Value checked for change.
17979 * @param i2 Static value used for concatenation only.
17980 * @param v3 Value checked for change.
17981 * @param i3 Static value used for concatenation only.
17982 * @param v4 Value checked for change.
17983 * @param i4 Static value used for concatenation only.
17984 * @param v5 Value checked for change.
17985 * @param i5 Static value used for concatenation only.
17986 * @param v6 Value checked for change.
17987 * @param i6 Static value used for concatenation only.
17988 * @param v7 Value checked for change.
17989 * @param suffix Static value used for concatenation only.
17990 * @codeGenApi
17991 */
17992function ɵɵclassMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
17993 const lView = getLView();
17994 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
17995 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17996}
17997/**
17998 * Update an interpolated class on an element with 9 or more bound values surrounded by text.
17999 *
18000 * Used when the number of interpolated values exceeds 8.
18001 *
18002 * ```html
18003 * <div
18004 * class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
18005 * ```
18006 *
18007 * Its compiled representation is:
18008 *
18009 * ```ts
18010 * ɵɵclassMapInterpolateV(
18011 * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
18012 * 'suffix']);
18013 * ```
18014 *.
18015 * @param values The collection of values and the strings in-between those values, beginning with
18016 * a string prefix and ending with a string suffix.
18017 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
18018 * @codeGenApi
18019 */
18020function ɵɵclassMapInterpolateV(values) {
18021 const lView = getLView();
18022 const interpolatedValue = interpolationV(lView, values);
18023 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
18024}
18025
18026/**
18027 * @license
18028 * Copyright Google LLC All Rights Reserved.
18029 *
18030 * Use of this source code is governed by an MIT-style license that can be
18031 * found in the LICENSE file at https://angular.io/license
18032 */
18033/**
18034 *
18035 * Update an interpolated style on an element with single bound value surrounded by text.
18036 *
18037 * Used when the value passed to a property has 1 interpolated value in it:
18038 *
18039 * ```html
18040 * <div style="key: {{v0}}suffix"></div>
18041 * ```
18042 *
18043 * Its compiled representation is:
18044 *
18045 * ```ts
18046 * ɵɵstyleMapInterpolate1('key: ', v0, 'suffix');
18047 * ```
18048 *
18049 * @param prefix Static value used for concatenation only.
18050 * @param v0 Value checked for change.
18051 * @param suffix Static value used for concatenation only.
18052 * @codeGenApi
18053 */
18054function ɵɵstyleMapInterpolate1(prefix, v0, suffix) {
18055 const lView = getLView();
18056 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
18057 ɵɵstyleMap(interpolatedValue);
18058}
18059/**
18060 *
18061 * Update an interpolated style on an element with 2 bound values surrounded by text.
18062 *
18063 * Used when the value passed to a property has 2 interpolated values in it:
18064 *
18065 * ```html
18066 * <div style="key: {{v0}}; key1: {{v1}}suffix"></div>
18067 * ```
18068 *
18069 * Its compiled representation is:
18070 *
18071 * ```ts
18072 * ɵɵstyleMapInterpolate2('key: ', v0, '; key1: ', v1, 'suffix');
18073 * ```
18074 *
18075 * @param prefix Static value used for concatenation only.
18076 * @param v0 Value checked for change.
18077 * @param i0 Static value used for concatenation only.
18078 * @param v1 Value checked for change.
18079 * @param suffix Static value used for concatenation only.
18080 * @codeGenApi
18081 */
18082function ɵɵstyleMapInterpolate2(prefix, v0, i0, v1, suffix) {
18083 const lView = getLView();
18084 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
18085 ɵɵstyleMap(interpolatedValue);
18086}
18087/**
18088 *
18089 * Update an interpolated style on an element with 3 bound values surrounded by text.
18090 *
18091 * Used when the value passed to a property has 3 interpolated values in it:
18092 *
18093 * ```html
18094 * <div style="key: {{v0}}; key2: {{v1}}; key2: {{v2}}suffix"></div>
18095 * ```
18096 *
18097 * Its compiled representation is:
18098 *
18099 * ```ts
18100 * ɵɵstyleMapInterpolate3(
18101 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, 'suffix');
18102 * ```
18103 *
18104 * @param prefix Static value used for concatenation only.
18105 * @param v0 Value checked for change.
18106 * @param i0 Static value used for concatenation only.
18107 * @param v1 Value checked for change.
18108 * @param i1 Static value used for concatenation only.
18109 * @param v2 Value checked for change.
18110 * @param suffix Static value used for concatenation only.
18111 * @codeGenApi
18112 */
18113function ɵɵstyleMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
18114 const lView = getLView();
18115 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
18116 ɵɵstyleMap(interpolatedValue);
18117}
18118/**
18119 *
18120 * Update an interpolated style on an element with 4 bound values surrounded by text.
18121 *
18122 * Used when the value passed to a property has 4 interpolated values in it:
18123 *
18124 * ```html
18125 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}suffix"></div>
18126 * ```
18127 *
18128 * Its compiled representation is:
18129 *
18130 * ```ts
18131 * ɵɵstyleMapInterpolate4(
18132 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, 'suffix');
18133 * ```
18134 *
18135 * @param prefix Static value used for concatenation only.
18136 * @param v0 Value checked for change.
18137 * @param i0 Static value used for concatenation only.
18138 * @param v1 Value checked for change.
18139 * @param i1 Static value used for concatenation only.
18140 * @param v2 Value checked for change.
18141 * @param i2 Static value used for concatenation only.
18142 * @param v3 Value checked for change.
18143 * @param suffix Static value used for concatenation only.
18144 * @codeGenApi
18145 */
18146function ɵɵstyleMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
18147 const lView = getLView();
18148 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
18149 ɵɵstyleMap(interpolatedValue);
18150}
18151/**
18152 *
18153 * Update an interpolated style on an element with 5 bound values surrounded by text.
18154 *
18155 * Used when the value passed to a property has 5 interpolated values in it:
18156 *
18157 * ```html
18158 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}suffix"></div>
18159 * ```
18160 *
18161 * Its compiled representation is:
18162 *
18163 * ```ts
18164 * ɵɵstyleMapInterpolate5(
18165 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, 'suffix');
18166 * ```
18167 *
18168 * @param prefix Static value used for concatenation only.
18169 * @param v0 Value checked for change.
18170 * @param i0 Static value used for concatenation only.
18171 * @param v1 Value checked for change.
18172 * @param i1 Static value used for concatenation only.
18173 * @param v2 Value checked for change.
18174 * @param i2 Static value used for concatenation only.
18175 * @param v3 Value checked for change.
18176 * @param i3 Static value used for concatenation only.
18177 * @param v4 Value checked for change.
18178 * @param suffix Static value used for concatenation only.
18179 * @codeGenApi
18180 */
18181function ɵɵstyleMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
18182 const lView = getLView();
18183 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
18184 ɵɵstyleMap(interpolatedValue);
18185}
18186/**
18187 *
18188 * Update an interpolated style on an element with 6 bound values surrounded by text.
18189 *
18190 * Used when the value passed to a property has 6 interpolated values in it:
18191 *
18192 * ```html
18193 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}};
18194 * key5: {{v5}}suffix"></div>
18195 * ```
18196 *
18197 * Its compiled representation is:
18198 *
18199 * ```ts
18200 * ɵɵstyleMapInterpolate6(
18201 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18202 * 'suffix');
18203 * ```
18204 *
18205 * @param prefix Static value used for concatenation only.
18206 * @param v0 Value checked for change.
18207 * @param i0 Static value used for concatenation only.
18208 * @param v1 Value checked for change.
18209 * @param i1 Static value used for concatenation only.
18210 * @param v2 Value checked for change.
18211 * @param i2 Static value used for concatenation only.
18212 * @param v3 Value checked for change.
18213 * @param i3 Static value used for concatenation only.
18214 * @param v4 Value checked for change.
18215 * @param i4 Static value used for concatenation only.
18216 * @param v5 Value checked for change.
18217 * @param suffix Static value used for concatenation only.
18218 * @codeGenApi
18219 */
18220function ɵɵstyleMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
18221 const lView = getLView();
18222 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
18223 ɵɵstyleMap(interpolatedValue);
18224}
18225/**
18226 *
18227 * Update an interpolated style on an element with 7 bound values surrounded by text.
18228 *
18229 * Used when the value passed to a property has 7 interpolated values in it:
18230 *
18231 * ```html
18232 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
18233 * key6: {{v6}}suffix"></div>
18234 * ```
18235 *
18236 * Its compiled representation is:
18237 *
18238 * ```ts
18239 * ɵɵstyleMapInterpolate7(
18240 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18241 * '; key6: ', v6, 'suffix');
18242 * ```
18243 *
18244 * @param prefix Static value used for concatenation only.
18245 * @param v0 Value checked for change.
18246 * @param i0 Static value used for concatenation only.
18247 * @param v1 Value checked for change.
18248 * @param i1 Static value used for concatenation only.
18249 * @param v2 Value checked for change.
18250 * @param i2 Static value used for concatenation only.
18251 * @param v3 Value checked for change.
18252 * @param i3 Static value used for concatenation only.
18253 * @param v4 Value checked for change.
18254 * @param i4 Static value used for concatenation only.
18255 * @param v5 Value checked for change.
18256 * @param i5 Static value used for concatenation only.
18257 * @param v6 Value checked for change.
18258 * @param suffix Static value used for concatenation only.
18259 * @codeGenApi
18260 */
18261function ɵɵstyleMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
18262 const lView = getLView();
18263 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
18264 ɵɵstyleMap(interpolatedValue);
18265}
18266/**
18267 *
18268 * Update an interpolated style on an element with 8 bound values surrounded by text.
18269 *
18270 * Used when the value passed to a property has 8 interpolated values in it:
18271 *
18272 * ```html
18273 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
18274 * key6: {{v6}}; key7: {{v7}}suffix"></div>
18275 * ```
18276 *
18277 * Its compiled representation is:
18278 *
18279 * ```ts
18280 * ɵɵstyleMapInterpolate8(
18281 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18282 * '; key6: ', v6, '; key7: ', v7, 'suffix');
18283 * ```
18284 *
18285 * @param prefix Static value used for concatenation only.
18286 * @param v0 Value checked for change.
18287 * @param i0 Static value used for concatenation only.
18288 * @param v1 Value checked for change.
18289 * @param i1 Static value used for concatenation only.
18290 * @param v2 Value checked for change.
18291 * @param i2 Static value used for concatenation only.
18292 * @param v3 Value checked for change.
18293 * @param i3 Static value used for concatenation only.
18294 * @param v4 Value checked for change.
18295 * @param i4 Static value used for concatenation only.
18296 * @param v5 Value checked for change.
18297 * @param i5 Static value used for concatenation only.
18298 * @param v6 Value checked for change.
18299 * @param i6 Static value used for concatenation only.
18300 * @param v7 Value checked for change.
18301 * @param suffix Static value used for concatenation only.
18302 * @codeGenApi
18303 */
18304function ɵɵstyleMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
18305 const lView = getLView();
18306 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
18307 ɵɵstyleMap(interpolatedValue);
18308}
18309/**
18310 * Update an interpolated style on an element with 9 or more bound values surrounded by text.
18311 *
18312 * Used when the number of interpolated values exceeds 8.
18313 *
18314 * ```html
18315 * <div
18316 * class="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
18317 * key6: {{v6}}; key7: {{v7}}; key8: {{v8}}; key9: {{v9}}suffix"></div>
18318 * ```
18319 *
18320 * Its compiled representation is:
18321 *
18322 * ```ts
18323 * ɵɵstyleMapInterpolateV(
18324 * ['key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18325 * '; key6: ', v6, '; key7: ', v7, '; key8: ', v8, '; key9: ', v9, 'suffix']);
18326 * ```
18327 *.
18328 * @param values The collection of values and the strings in-between those values, beginning with
18329 * a string prefix and ending with a string suffix.
18330 * (e.g. `['prefix', value0, '; key2: ', value1, '; key2: ', value2, ..., value99, 'suffix']`)
18331 * @codeGenApi
18332 */
18333function ɵɵstyleMapInterpolateV(values) {
18334 const lView = getLView();
18335 const interpolatedValue = interpolationV(lView, values);
18336 ɵɵstyleMap(interpolatedValue);
18337}
18338
18339/**
18340 * @license
18341 * Copyright Google LLC All Rights Reserved.
18342 *
18343 * Use of this source code is governed by an MIT-style license that can be
18344 * found in the LICENSE file at https://angular.io/license
18345 */
18346/**
18347 *
18348 * Update an interpolated style property on an element with single bound value surrounded by text.
18349 *
18350 * Used when the value passed to a property has 1 interpolated value in it:
18351 *
18352 * ```html
18353 * <div style.color="prefix{{v0}}suffix"></div>
18354 * ```
18355 *
18356 * Its compiled representation is:
18357 *
18358 * ```ts
18359 * ɵɵstylePropInterpolate1(0, 'prefix', v0, 'suffix');
18360 * ```
18361 *
18362 * @param styleIndex Index of style to update. This index value refers to the
18363 * index of the style in the style bindings array that was passed into
18364 * `styling`.
18365 * @param prefix Static value used for concatenation only.
18366 * @param v0 Value checked for change.
18367 * @param suffix Static value used for concatenation only.
18368 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18369 * @returns itself, so that it may be chained.
18370 * @codeGenApi
18371 */
18372function ɵɵstylePropInterpolate1(prop, prefix, v0, suffix, valueSuffix) {
18373 const lView = getLView();
18374 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
18375 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18376 return ɵɵstylePropInterpolate1;
18377}
18378/**
18379 *
18380 * Update an interpolated style property on an element with 2 bound values surrounded by text.
18381 *
18382 * Used when the value passed to a property has 2 interpolated values in it:
18383 *
18384 * ```html
18385 * <div style.color="prefix{{v0}}-{{v1}}suffix"></div>
18386 * ```
18387 *
18388 * Its compiled representation is:
18389 *
18390 * ```ts
18391 * ɵɵstylePropInterpolate2(0, 'prefix', v0, '-', v1, 'suffix');
18392 * ```
18393 *
18394 * @param styleIndex Index of style to update. This index value refers to the
18395 * index of the style in the style bindings array that was passed into
18396 * `styling`.
18397 * @param prefix Static value used for concatenation only.
18398 * @param v0 Value checked for change.
18399 * @param i0 Static value used for concatenation only.
18400 * @param v1 Value checked for change.
18401 * @param suffix Static value used for concatenation only.
18402 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18403 * @returns itself, so that it may be chained.
18404 * @codeGenApi
18405 */
18406function ɵɵstylePropInterpolate2(prop, prefix, v0, i0, v1, suffix, valueSuffix) {
18407 const lView = getLView();
18408 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
18409 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18410 return ɵɵstylePropInterpolate2;
18411}
18412/**
18413 *
18414 * Update an interpolated style property on an element with 3 bound values surrounded by text.
18415 *
18416 * Used when the value passed to a property has 3 interpolated values in it:
18417 *
18418 * ```html
18419 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
18420 * ```
18421 *
18422 * Its compiled representation is:
18423 *
18424 * ```ts
18425 * ɵɵstylePropInterpolate3(0, 'prefix', v0, '-', v1, '-', v2, 'suffix');
18426 * ```
18427 *
18428 * @param styleIndex Index of style to update. This index value refers to the
18429 * index of the style in the style bindings array that was passed into
18430 * `styling`.
18431 * @param prefix Static value used for concatenation only.
18432 * @param v0 Value checked for change.
18433 * @param i0 Static value used for concatenation only.
18434 * @param v1 Value checked for change.
18435 * @param i1 Static value used for concatenation only.
18436 * @param v2 Value checked for change.
18437 * @param suffix Static value used for concatenation only.
18438 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18439 * @returns itself, so that it may be chained.
18440 * @codeGenApi
18441 */
18442function ɵɵstylePropInterpolate3(prop, prefix, v0, i0, v1, i1, v2, suffix, valueSuffix) {
18443 const lView = getLView();
18444 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
18445 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18446 return ɵɵstylePropInterpolate3;
18447}
18448/**
18449 *
18450 * Update an interpolated style property on an element with 4 bound values surrounded by text.
18451 *
18452 * Used when the value passed to a property has 4 interpolated values in it:
18453 *
18454 * ```html
18455 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
18456 * ```
18457 *
18458 * Its compiled representation is:
18459 *
18460 * ```ts
18461 * ɵɵstylePropInterpolate4(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
18462 * ```
18463 *
18464 * @param styleIndex Index of style to update. This index value refers to the
18465 * index of the style in the style bindings array that was passed into
18466 * `styling`.
18467 * @param prefix Static value used for concatenation only.
18468 * @param v0 Value checked for change.
18469 * @param i0 Static value used for concatenation only.
18470 * @param v1 Value checked for change.
18471 * @param i1 Static value used for concatenation only.
18472 * @param v2 Value checked for change.
18473 * @param i2 Static value used for concatenation only.
18474 * @param v3 Value checked for change.
18475 * @param suffix Static value used for concatenation only.
18476 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18477 * @returns itself, so that it may be chained.
18478 * @codeGenApi
18479 */
18480function ɵɵstylePropInterpolate4(prop, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, valueSuffix) {
18481 const lView = getLView();
18482 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
18483 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18484 return ɵɵstylePropInterpolate4;
18485}
18486/**
18487 *
18488 * Update an interpolated style property on an element with 5 bound values surrounded by text.
18489 *
18490 * Used when the value passed to a property has 5 interpolated values in it:
18491 *
18492 * ```html
18493 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
18494 * ```
18495 *
18496 * Its compiled representation is:
18497 *
18498 * ```ts
18499 * ɵɵstylePropInterpolate5(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
18500 * ```
18501 *
18502 * @param styleIndex Index of style to update. This index value refers to the
18503 * index of the style in the style bindings array that was passed into
18504 * `styling`.
18505 * @param prefix Static value used for concatenation only.
18506 * @param v0 Value checked for change.
18507 * @param i0 Static value used for concatenation only.
18508 * @param v1 Value checked for change.
18509 * @param i1 Static value used for concatenation only.
18510 * @param v2 Value checked for change.
18511 * @param i2 Static value used for concatenation only.
18512 * @param v3 Value checked for change.
18513 * @param i3 Static value used for concatenation only.
18514 * @param v4 Value checked for change.
18515 * @param suffix Static value used for concatenation only.
18516 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18517 * @returns itself, so that it may be chained.
18518 * @codeGenApi
18519 */
18520function ɵɵstylePropInterpolate5(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, valueSuffix) {
18521 const lView = getLView();
18522 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
18523 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18524 return ɵɵstylePropInterpolate5;
18525}
18526/**
18527 *
18528 * Update an interpolated style property on an element with 6 bound values surrounded by text.
18529 *
18530 * Used when the value passed to a property has 6 interpolated values in it:
18531 *
18532 * ```html
18533 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
18534 * ```
18535 *
18536 * Its compiled representation is:
18537 *
18538 * ```ts
18539 * ɵɵstylePropInterpolate6(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
18540 * ```
18541 *
18542 * @param styleIndex Index of style to update. This index value refers to the
18543 * index of the style in the style bindings array that was passed into
18544 * `styling`.
18545 * @param prefix Static value used for concatenation only.
18546 * @param v0 Value checked for change.
18547 * @param i0 Static value used for concatenation only.
18548 * @param v1 Value checked for change.
18549 * @param i1 Static value used for concatenation only.
18550 * @param v2 Value checked for change.
18551 * @param i2 Static value used for concatenation only.
18552 * @param v3 Value checked for change.
18553 * @param i3 Static value used for concatenation only.
18554 * @param v4 Value checked for change.
18555 * @param i4 Static value used for concatenation only.
18556 * @param v5 Value checked for change.
18557 * @param suffix Static value used for concatenation only.
18558 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18559 * @returns itself, so that it may be chained.
18560 * @codeGenApi
18561 */
18562function ɵɵstylePropInterpolate6(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, valueSuffix) {
18563 const lView = getLView();
18564 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
18565 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18566 return ɵɵstylePropInterpolate6;
18567}
18568/**
18569 *
18570 * Update an interpolated style property on an element with 7 bound values surrounded by text.
18571 *
18572 * Used when the value passed to a property has 7 interpolated values in it:
18573 *
18574 * ```html
18575 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
18576 * ```
18577 *
18578 * Its compiled representation is:
18579 *
18580 * ```ts
18581 * ɵɵstylePropInterpolate7(
18582 * 0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
18583 * ```
18584 *
18585 * @param styleIndex Index of style to update. This index value refers to the
18586 * index of the style in the style bindings array that was passed into
18587 * `styling`.
18588 * @param prefix Static value used for concatenation only.
18589 * @param v0 Value checked for change.
18590 * @param i0 Static value used for concatenation only.
18591 * @param v1 Value checked for change.
18592 * @param i1 Static value used for concatenation only.
18593 * @param v2 Value checked for change.
18594 * @param i2 Static value used for concatenation only.
18595 * @param v3 Value checked for change.
18596 * @param i3 Static value used for concatenation only.
18597 * @param v4 Value checked for change.
18598 * @param i4 Static value used for concatenation only.
18599 * @param v5 Value checked for change.
18600 * @param i5 Static value used for concatenation only.
18601 * @param v6 Value checked for change.
18602 * @param suffix Static value used for concatenation only.
18603 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18604 * @returns itself, so that it may be chained.
18605 * @codeGenApi
18606 */
18607function ɵɵstylePropInterpolate7(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, valueSuffix) {
18608 const lView = getLView();
18609 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
18610 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18611 return ɵɵstylePropInterpolate7;
18612}
18613/**
18614 *
18615 * Update an interpolated style property on an element with 8 bound values surrounded by text.
18616 *
18617 * Used when the value passed to a property has 8 interpolated values in it:
18618 *
18619 * ```html
18620 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
18621 * ```
18622 *
18623 * Its compiled representation is:
18624 *
18625 * ```ts
18626 * ɵɵstylePropInterpolate8(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6,
18627 * '-', v7, 'suffix');
18628 * ```
18629 *
18630 * @param styleIndex Index of style to update. This index value refers to the
18631 * index of the style in the style bindings array that was passed into
18632 * `styling`.
18633 * @param prefix Static value used for concatenation only.
18634 * @param v0 Value checked for change.
18635 * @param i0 Static value used for concatenation only.
18636 * @param v1 Value checked for change.
18637 * @param i1 Static value used for concatenation only.
18638 * @param v2 Value checked for change.
18639 * @param i2 Static value used for concatenation only.
18640 * @param v3 Value checked for change.
18641 * @param i3 Static value used for concatenation only.
18642 * @param v4 Value checked for change.
18643 * @param i4 Static value used for concatenation only.
18644 * @param v5 Value checked for change.
18645 * @param i5 Static value used for concatenation only.
18646 * @param v6 Value checked for change.
18647 * @param i6 Static value used for concatenation only.
18648 * @param v7 Value checked for change.
18649 * @param suffix Static value used for concatenation only.
18650 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18651 * @returns itself, so that it may be chained.
18652 * @codeGenApi
18653 */
18654function ɵɵstylePropInterpolate8(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, valueSuffix) {
18655 const lView = getLView();
18656 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
18657 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18658 return ɵɵstylePropInterpolate8;
18659}
18660/**
18661 * Update an interpolated style property on an element with 9 or more bound values surrounded by
18662 * text.
18663 *
18664 * Used when the number of interpolated values exceeds 8.
18665 *
18666 * ```html
18667 * <div
18668 * style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix">
18669 * </div>
18670 * ```
18671 *
18672 * Its compiled representation is:
18673 *
18674 * ```ts
18675 * ɵɵstylePropInterpolateV(
18676 * 0, ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
18677 * 'suffix']);
18678 * ```
18679 *
18680 * @param styleIndex Index of style to update. This index value refers to the
18681 * index of the style in the style bindings array that was passed into
18682 * `styling`..
18683 * @param values The collection of values and the strings in-between those values, beginning with
18684 * a string prefix and ending with a string suffix.
18685 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
18686 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18687 * @returns itself, so that it may be chained.
18688 * @codeGenApi
18689 */
18690function ɵɵstylePropInterpolateV(prop, values, valueSuffix) {
18691 const lView = getLView();
18692 const interpolatedValue = interpolationV(lView, values);
18693 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18694 return ɵɵstylePropInterpolateV;
18695}
18696
18697/**
18698 * @license
18699 * Copyright Google LLC All Rights Reserved.
18700 *
18701 * Use of this source code is governed by an MIT-style license that can be
18702 * found in the LICENSE file at https://angular.io/license
18703 */
18704/**
18705 * Update a property on a host element. Only applies to native node properties, not inputs.
18706 *
18707 * Operates on the element selected by index via the {@link select} instruction.
18708 *
18709 * @param propName Name of property. Because it is going to DOM, this is not subject to
18710 * renaming as part of minification.
18711 * @param value New value to write.
18712 * @param sanitizer An optional function used to sanitize the value.
18713 * @returns This function returns itself so that it may be chained
18714 * (e.g. `property('name', ctx.name)('title', ctx.title)`)
18715 *
18716 * @codeGenApi
18717 */
18718function ɵɵhostProperty(propName, value, sanitizer) {
18719 const lView = getLView();
18720 const bindingIndex = nextBindingIndex();
18721 if (bindingUpdated(lView, bindingIndex, value)) {
18722 const tView = getTView();
18723 const tNode = getSelectedTNode();
18724 elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, true);
18725 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
18726 }
18727 return ɵɵhostProperty;
18728}
18729/**
18730 * Updates a synthetic host binding (e.g. `[@foo]`) on a component or directive.
18731 *
18732 * This instruction is for compatibility purposes and is designed to ensure that a
18733 * synthetic host binding (e.g. `@HostBinding('@foo')`) properly gets rendered in
18734 * the component's renderer. Normally all host bindings are evaluated with the parent
18735 * component's renderer, but, in the case of animation @triggers, they need to be
18736 * evaluated with the sub component's renderer (because that's where the animation
18737 * triggers are defined).
18738 *
18739 * Do not use this instruction as a replacement for `elementProperty`. This instruction
18740 * only exists to ensure compatibility with the ViewEngine's host binding behavior.
18741 *
18742 * @param index The index of the element to update in the data array
18743 * @param propName Name of property. Because it is going to DOM, this is not subject to
18744 * renaming as part of minification.
18745 * @param value New value to write.
18746 * @param sanitizer An optional function used to sanitize the value.
18747 *
18748 * @codeGenApi
18749 */
18750function ɵɵsyntheticHostProperty(propName, value, sanitizer) {
18751 const lView = getLView();
18752 const bindingIndex = nextBindingIndex();
18753 if (bindingUpdated(lView, bindingIndex, value)) {
18754 const tView = getTView();
18755 const tNode = getSelectedTNode();
18756 const currentDef = getCurrentDirectiveDef(tView.data);
18757 const renderer = loadComponentRenderer(currentDef, tNode, lView);
18758 elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true);
18759 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
18760 }
18761 return ɵɵsyntheticHostProperty;
18762}
18763
18764/**
18765 * @license
18766 * Copyright Google LLC All Rights Reserved.
18767 *
18768 * Use of this source code is governed by an MIT-style license that can be
18769 * found in the LICENSE file at https://angular.io/license
18770 */
18771/**
18772 * NOTE: changes to the `ngI18nClosureMode` name must be synced with `compiler-cli/src/tooling.ts`.
18773 */
18774if (typeof ngI18nClosureMode === 'undefined') {
18775 // These property accesses can be ignored because ngI18nClosureMode will be set to false
18776 // when optimizing code and the whole if statement will be dropped.
18777 // Make sure to refer to ngI18nClosureMode as ['ngI18nClosureMode'] for closure.
18778 // NOTE: we need to have it in IIFE so that the tree-shaker is happy.
18779 (function () {
18780 // tslint:disable-next-line:no-toplevel-property-access
18781 _global['ngI18nClosureMode'] =
18782 // TODO(FW-1250): validate that this actually, you know, works.
18783 // tslint:disable-next-line:no-toplevel-property-access
18784 typeof goog !== 'undefined' && typeof goog.getMsg === 'function';
18785 })();
18786}
18787
18788/**
18789 * @license
18790 * Copyright Google LLC All Rights Reserved.
18791 *
18792 * Use of this source code is governed by an MIT-style license that can be
18793 * found in the LICENSE file at https://angular.io/license
18794 */
18795// THIS CODE IS GENERATED - DO NOT MODIFY.
18796const u = undefined;
18797function plural(val) {
18798 const n = val, i = Math.floor(Math.abs(val)), v = val.toString().replace(/^[^.]*\.?/, '').length;
18799 if (i === 1 && v === 0)
18800 return 1;
18801 return 5;
18802}
18803var localeEn = ["en", [["a", "p"], ["AM", "PM"], u], [["AM", "PM"], u, u], [["S", "M", "T", "W", "T", "F", "S"], ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]], u, [["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"], ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]], u, [["B", "A"], ["BC", "AD"], ["Before Christ", "Anno Domini"]], 0, [6, 0], ["M/d/yy", "MMM d, y", "MMMM d, y", "EEEE, MMMM d, y"], ["h:mm a", "h:mm:ss a", "h:mm:ss a z", "h:mm:ss a zzzz"], ["{1}, {0}", u, "{1} 'at' {0}", u], [".", ",", ";", "%", "+", "-", "E", "×", "‰", "∞", "NaN", ":"], ["#,##0.###", "#,##0%", "¤#,##0.00", "#E0"], "USD", "$", "US Dollar", {}, "ltr", plural];
18804
18805/**
18806 * @license
18807 * Copyright Google LLC All Rights Reserved.
18808 *
18809 * Use of this source code is governed by an MIT-style license that can be
18810 * found in the LICENSE file at https://angular.io/license
18811 */
18812/**
18813 * This const is used to store the locale data registered with `registerLocaleData`
18814 */
18815let LOCALE_DATA = {};
18816/**
18817 * Register locale data to be used internally by Angular. See the
18818 * ["I18n guide"](guide/i18n-common-format-data-locale) to know how to import additional locale
18819 * data.
18820 *
18821 * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1
18822 */
18823function registerLocaleData(data, localeId, extraData) {
18824 if (typeof localeId !== 'string') {
18825 extraData = localeId;
18826 localeId = data[LocaleDataIndex.LocaleId];
18827 }
18828 localeId = localeId.toLowerCase().replace(/_/g, '-');
18829 LOCALE_DATA[localeId] = data;
18830 if (extraData) {
18831 LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData;
18832 }
18833}
18834/**
18835 * Finds the locale data for a given locale.
18836 *
18837 * @param locale The locale code.
18838 * @returns The locale data.
18839 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
18840 */
18841function findLocaleData(locale) {
18842 const normalizedLocale = normalizeLocale(locale);
18843 let match = getLocaleData(normalizedLocale);
18844 if (match) {
18845 return match;
18846 }
18847 // let's try to find a parent locale
18848 const parentLocale = normalizedLocale.split('-')[0];
18849 match = getLocaleData(parentLocale);
18850 if (match) {
18851 return match;
18852 }
18853 if (parentLocale === 'en') {
18854 return localeEn;
18855 }
18856 throw new Error(`Missing locale data for the locale "${locale}".`);
18857}
18858/**
18859 * Retrieves the default currency code for the given locale.
18860 *
18861 * The default is defined as the first currency which is still in use.
18862 *
18863 * @param locale The code of the locale whose currency code we want.
18864 * @returns The code of the default currency for the given locale.
18865 *
18866 */
18867function getLocaleCurrencyCode(locale) {
18868 const data = findLocaleData(locale);
18869 return data[LocaleDataIndex.CurrencyCode] || null;
18870}
18871/**
18872 * Retrieves the plural function used by ICU expressions to determine the plural case to use
18873 * for a given locale.
18874 * @param locale A locale code for the locale format rules to use.
18875 * @returns The plural function for the locale.
18876 * @see `NgPlural`
18877 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
18878 */
18879function getLocalePluralCase(locale) {
18880 const data = findLocaleData(locale);
18881 return data[LocaleDataIndex.PluralCase];
18882}
18883/**
18884 * Helper function to get the given `normalizedLocale` from `LOCALE_DATA`
18885 * or from the global `ng.common.locale`.
18886 */
18887function getLocaleData(normalizedLocale) {
18888 if (!(normalizedLocale in LOCALE_DATA)) {
18889 LOCALE_DATA[normalizedLocale] = _global.ng && _global.ng.common && _global.ng.common.locales &&
18890 _global.ng.common.locales[normalizedLocale];
18891 }
18892 return LOCALE_DATA[normalizedLocale];
18893}
18894/**
18895 * Helper function to remove all the locale data from `LOCALE_DATA`.
18896 */
18897function unregisterAllLocaleData() {
18898 LOCALE_DATA = {};
18899}
18900/**
18901 * Index of each type of locale data from the locale data array
18902 */
18903var LocaleDataIndex;
18904(function (LocaleDataIndex) {
18905 LocaleDataIndex[LocaleDataIndex["LocaleId"] = 0] = "LocaleId";
18906 LocaleDataIndex[LocaleDataIndex["DayPeriodsFormat"] = 1] = "DayPeriodsFormat";
18907 LocaleDataIndex[LocaleDataIndex["DayPeriodsStandalone"] = 2] = "DayPeriodsStandalone";
18908 LocaleDataIndex[LocaleDataIndex["DaysFormat"] = 3] = "DaysFormat";
18909 LocaleDataIndex[LocaleDataIndex["DaysStandalone"] = 4] = "DaysStandalone";
18910 LocaleDataIndex[LocaleDataIndex["MonthsFormat"] = 5] = "MonthsFormat";
18911 LocaleDataIndex[LocaleDataIndex["MonthsStandalone"] = 6] = "MonthsStandalone";
18912 LocaleDataIndex[LocaleDataIndex["Eras"] = 7] = "Eras";
18913 LocaleDataIndex[LocaleDataIndex["FirstDayOfWeek"] = 8] = "FirstDayOfWeek";
18914 LocaleDataIndex[LocaleDataIndex["WeekendRange"] = 9] = "WeekendRange";
18915 LocaleDataIndex[LocaleDataIndex["DateFormat"] = 10] = "DateFormat";
18916 LocaleDataIndex[LocaleDataIndex["TimeFormat"] = 11] = "TimeFormat";
18917 LocaleDataIndex[LocaleDataIndex["DateTimeFormat"] = 12] = "DateTimeFormat";
18918 LocaleDataIndex[LocaleDataIndex["NumberSymbols"] = 13] = "NumberSymbols";
18919 LocaleDataIndex[LocaleDataIndex["NumberFormats"] = 14] = "NumberFormats";
18920 LocaleDataIndex[LocaleDataIndex["CurrencyCode"] = 15] = "CurrencyCode";
18921 LocaleDataIndex[LocaleDataIndex["CurrencySymbol"] = 16] = "CurrencySymbol";
18922 LocaleDataIndex[LocaleDataIndex["CurrencyName"] = 17] = "CurrencyName";
18923 LocaleDataIndex[LocaleDataIndex["Currencies"] = 18] = "Currencies";
18924 LocaleDataIndex[LocaleDataIndex["Directionality"] = 19] = "Directionality";
18925 LocaleDataIndex[LocaleDataIndex["PluralCase"] = 20] = "PluralCase";
18926 LocaleDataIndex[LocaleDataIndex["ExtraData"] = 21] = "ExtraData";
18927})(LocaleDataIndex || (LocaleDataIndex = {}));
18928/**
18929 * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.
18930 */
18931function normalizeLocale(locale) {
18932 return locale.toLowerCase().replace(/_/g, '-');
18933}
18934
18935/**
18936 * @license
18937 * Copyright Google LLC All Rights Reserved.
18938 *
18939 * Use of this source code is governed by an MIT-style license that can be
18940 * found in the LICENSE file at https://angular.io/license
18941 */
18942const pluralMapping = ['zero', 'one', 'two', 'few', 'many'];
18943/**
18944 * Returns the plural case based on the locale
18945 */
18946function getPluralCase(value, locale) {
18947 const plural = getLocalePluralCase(locale)(parseInt(value, 10));
18948 const result = pluralMapping[plural];
18949 return (result !== undefined) ? result : 'other';
18950}
18951/**
18952 * The locale id that the application is using by default (for translations and ICU expressions).
18953 */
18954const DEFAULT_LOCALE_ID = 'en-US';
18955/**
18956 * USD currency code that the application uses by default for CurrencyPipe when no
18957 * DEFAULT_CURRENCY_CODE is provided.
18958 */
18959const USD_CURRENCY_CODE = 'USD';
18960
18961/**
18962 * @license
18963 * Copyright Google LLC All Rights Reserved.
18964 *
18965 * Use of this source code is governed by an MIT-style license that can be
18966 * found in the LICENSE file at https://angular.io/license
18967 */
18968/**
18969 * Marks that the next string is an element name.
18970 *
18971 * See `I18nMutateOpCodes` documentation.
18972 */
18973const ELEMENT_MARKER = {
18974 marker: 'element'
18975};
18976/**
18977 * Marks that the next string is comment text need for ICU.
18978 *
18979 * See `I18nMutateOpCodes` documentation.
18980 */
18981const ICU_MARKER = {
18982 marker: 'ICU'
18983};
18984/**
18985 * See `I18nCreateOpCodes`
18986 */
18987var I18nCreateOpCode;
18988(function (I18nCreateOpCode) {
18989 /**
18990 * Number of bits to shift index so that it can be combined with the `APPEND_EAGERLY` and
18991 * `COMMENT`.
18992 */
18993 I18nCreateOpCode[I18nCreateOpCode["SHIFT"] = 2] = "SHIFT";
18994 /**
18995 * Should the node be appended to parent imedditatly after creation.
18996 */
18997 I18nCreateOpCode[I18nCreateOpCode["APPEND_EAGERLY"] = 1] = "APPEND_EAGERLY";
18998 /**
18999 * If set the node should be comment (rather than a text) node.
19000 */
19001 I18nCreateOpCode[I18nCreateOpCode["COMMENT"] = 2] = "COMMENT";
19002})(I18nCreateOpCode || (I18nCreateOpCode = {}));
19003// Note: This hack is necessary so we don't erroneously get a circular dependency
19004// failure based on types.
19005const unusedValueExportToPlacateAjd$2 = 1;
19006
19007/**
19008 * @license
19009 * Copyright Google LLC All Rights Reserved.
19010 *
19011 * Use of this source code is governed by an MIT-style license that can be
19012 * found in the LICENSE file at https://angular.io/license
19013 */
19014/**
19015 * The locale id that the application is currently using (for translations and ICU expressions).
19016 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
19017 * but is now defined as a global value.
19018 */
19019let LOCALE_ID$1 = DEFAULT_LOCALE_ID;
19020/**
19021 * Sets the locale id that will be used for translations and ICU expressions.
19022 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
19023 * but is now defined as a global value.
19024 *
19025 * @param localeId
19026 */
19027function setLocaleId(localeId) {
19028 assertDefined(localeId, `Expected localeId to be defined`);
19029 if (typeof localeId === 'string') {
19030 LOCALE_ID$1 = localeId.toLowerCase().replace(/_/g, '-');
19031 }
19032}
19033/**
19034 * Gets the locale id that will be used for translations and ICU expressions.
19035 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
19036 * but is now defined as a global value.
19037 */
19038function getLocaleId() {
19039 return LOCALE_ID$1;
19040}
19041
19042/**
19043 * @license
19044 * Copyright Google LLC All Rights Reserved.
19045 *
19046 * Use of this source code is governed by an MIT-style license that can be
19047 * found in the LICENSE file at https://angular.io/license
19048 */
19049/**
19050 * Find a node in front of which `currentTNode` should be inserted (takes i18n into account).
19051 *
19052 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
19053 * takes `TNode.insertBeforeIndex` into account.
19054 *
19055 * @param parentTNode parent `TNode`
19056 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
19057 * @param lView current `LView`
19058 */
19059function getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView) {
19060 const tNodeInsertBeforeIndex = currentTNode.insertBeforeIndex;
19061 const insertBeforeIndex = Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tNodeInsertBeforeIndex;
19062 if (insertBeforeIndex === null) {
19063 return getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView);
19064 }
19065 else {
19066 ngDevMode && assertIndexInRange(lView, insertBeforeIndex);
19067 return unwrapRNode(lView[insertBeforeIndex]);
19068 }
19069}
19070/**
19071 * Process `TNode.insertBeforeIndex` by adding i18n text nodes.
19072 *
19073 * See `TNode.insertBeforeIndex`
19074 */
19075function processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRElement) {
19076 const tNodeInsertBeforeIndex = childTNode.insertBeforeIndex;
19077 if (Array.isArray(tNodeInsertBeforeIndex)) {
19078 // An array indicates that there are i18n nodes that need to be added as children of this
19079 // `childRNode`. These i18n nodes were created before this `childRNode` was available and so
19080 // only now can be added. The first element of the array is the normal index where we should
19081 // insert the `childRNode`. Additional elements are the extra nodes to be added as children of
19082 // `childRNode`.
19083 ngDevMode && assertDomNode(childRNode);
19084 let i18nParent = childRNode;
19085 let anchorRNode = null;
19086 if (!(childTNode.type & 3 /* AnyRNode */)) {
19087 anchorRNode = i18nParent;
19088 i18nParent = parentRElement;
19089 }
19090 if (i18nParent !== null && (childTNode.flags & 2 /* isComponentHost */) === 0) {
19091 for (let i = 1; i < tNodeInsertBeforeIndex.length; i++) {
19092 // No need to `unwrapRNode` because all of the indexes point to i18n text nodes.
19093 // see `assertDomNode` below.
19094 const i18nChild = lView[tNodeInsertBeforeIndex[i]];
19095 nativeInsertBefore(renderer, i18nParent, i18nChild, anchorRNode, false);
19096 }
19097 }
19098 }
19099}
19100
19101/**
19102 * @license
19103 * Copyright Google LLC All Rights Reserved.
19104 *
19105 * Use of this source code is governed by an MIT-style license that can be
19106 * found in the LICENSE file at https://angular.io/license
19107 */
19108/**
19109 * Add `tNode` to `previousTNodes` list and update relevant `TNode`s in `previousTNodes` list
19110 * `tNode.insertBeforeIndex`.
19111 *
19112 * Things to keep in mind:
19113 * 1. All i18n text nodes are encoded as `TNodeType.Element` and are created eagerly by the
19114 * `ɵɵi18nStart` instruction.
19115 * 2. All `TNodeType.Placeholder` `TNodes` are elements which will be created later by
19116 * `ɵɵelementStart` instruction.
19117 * 3. `ɵɵelementStart` instruction will create `TNode`s in the ascending `TNode.index` order. (So a
19118 * smaller index `TNode` is guaranteed to be created before a larger one)
19119 *
19120 * We use the above three invariants to determine `TNode.insertBeforeIndex`.
19121 *
19122 * In an ideal world `TNode.insertBeforeIndex` would always be `TNode.next.index`. However,
19123 * this will not work because `TNode.next.index` may be larger than `TNode.index` which means that
19124 * the next node is not yet created and therefore we can't insert in front of it.
19125 *
19126 * Rule1: `TNode.insertBeforeIndex = null` if `TNode.next === null` (Initial condition, as we don't
19127 * know if there will be further `TNode`s inserted after.)
19128 * Rule2: If `previousTNode` is created after the `tNode` being inserted, then
19129 * `previousTNode.insertBeforeNode = tNode.index` (So when a new `tNode` is added we check
19130 * previous to see if we can update its `insertBeforeTNode`)
19131 *
19132 * See `TNode.insertBeforeIndex` for more context.
19133 *
19134 * @param previousTNodes A list of previous TNodes so that we can easily traverse `TNode`s in
19135 * reverse order. (If `TNode` would have `previous` this would not be necessary.)
19136 * @param newTNode A TNode to add to the `previousTNodes` list.
19137 */
19138function addTNodeAndUpdateInsertBeforeIndex(previousTNodes, newTNode) {
19139 // Start with Rule1
19140 ngDevMode &&
19141 assertEqual(newTNode.insertBeforeIndex, null, 'We expect that insertBeforeIndex is not set');
19142 previousTNodes.push(newTNode);
19143 if (previousTNodes.length > 1) {
19144 for (let i = previousTNodes.length - 2; i >= 0; i--) {
19145 const existingTNode = previousTNodes[i];
19146 // Text nodes are created eagerly and so they don't need their `indexBeforeIndex` updated.
19147 // It is safe to ignore them.
19148 if (!isI18nText(existingTNode)) {
19149 if (isNewTNodeCreatedBefore(existingTNode, newTNode) &&
19150 getInsertBeforeIndex(existingTNode) === null) {
19151 // If it was created before us in time, (and it does not yet have `insertBeforeIndex`)
19152 // then add the `insertBeforeIndex`.
19153 setInsertBeforeIndex(existingTNode, newTNode.index);
19154 }
19155 }
19156 }
19157 }
19158}
19159function isI18nText(tNode) {
19160 return !(tNode.type & 64 /* Placeholder */);
19161}
19162function isNewTNodeCreatedBefore(existingTNode, newTNode) {
19163 return isI18nText(newTNode) || existingTNode.index > newTNode.index;
19164}
19165function getInsertBeforeIndex(tNode) {
19166 const index = tNode.insertBeforeIndex;
19167 return Array.isArray(index) ? index[0] : index;
19168}
19169function setInsertBeforeIndex(tNode, value) {
19170 const index = tNode.insertBeforeIndex;
19171 if (Array.isArray(index)) {
19172 // Array is stored if we have to insert child nodes. See `TNode.insertBeforeIndex`
19173 index[0] = value;
19174 }
19175 else {
19176 setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);
19177 tNode.insertBeforeIndex = value;
19178 }
19179}
19180
19181/**
19182 * @license
19183 * Copyright Google LLC All Rights Reserved.
19184 *
19185 * Use of this source code is governed by an MIT-style license that can be
19186 * found in the LICENSE file at https://angular.io/license
19187 */
19188/**
19189 * Retrieve `TIcu` at a given `index`.
19190 *
19191 * The `TIcu` can be stored either directly (if it is nested ICU) OR
19192 * it is stored inside tho `TIcuContainer` if it is top level ICU.
19193 *
19194 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
19195 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is
19196 * expressed (parent ICU may have selected a case which does not contain it.)
19197 *
19198 * @param tView Current `TView`.
19199 * @param index Index where the value should be read from.
19200 */
19201function getTIcu(tView, index) {
19202 const value = tView.data[index];
19203 if (value === null || typeof value === 'string')
19204 return null;
19205 if (ngDevMode &&
19206 !(value.hasOwnProperty('tViews') || value.hasOwnProperty('currentCaseLViewIndex'))) {
19207 throwError('We expect to get \'null\'|\'TIcu\'|\'TIcuContainer\', but got: ' + value);
19208 }
19209 // Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be
19210 // either TIcu or TIcuContainerNode. This is not ideal, but we still think it is OK because it
19211 // will be just two cases which fits into the browser inline cache (inline cache can take up to
19212 // 4)
19213 const tIcu = value.hasOwnProperty('currentCaseLViewIndex') ? value :
19214 value.value;
19215 ngDevMode && assertTIcu(tIcu);
19216 return tIcu;
19217}
19218/**
19219 * Store `TIcu` at a give `index`.
19220 *
19221 * The `TIcu` can be stored either directly (if it is nested ICU) OR
19222 * it is stored inside tho `TIcuContainer` if it is top level ICU.
19223 *
19224 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
19225 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is
19226 * expressed (parent ICU may have selected a case which does not contain it.)
19227 *
19228 * @param tView Current `TView`.
19229 * @param index Index where the value should be stored at in `Tview.data`
19230 * @param tIcu The TIcu to store.
19231 */
19232function setTIcu(tView, index, tIcu) {
19233 const tNode = tView.data[index];
19234 ngDevMode &&
19235 assertEqual(tNode === null || tNode.hasOwnProperty('tViews'), true, 'We expect to get \'null\'|\'TIcuContainer\'');
19236 if (tNode === null) {
19237 tView.data[index] = tIcu;
19238 }
19239 else {
19240 ngDevMode && assertTNodeType(tNode, 32 /* Icu */);
19241 tNode.value = tIcu;
19242 }
19243}
19244/**
19245 * Set `TNode.insertBeforeIndex` taking the `Array` into account.
19246 *
19247 * See `TNode.insertBeforeIndex`
19248 */
19249function setTNodeInsertBeforeIndex(tNode, index) {
19250 ngDevMode && assertTNode(tNode);
19251 let insertBeforeIndex = tNode.insertBeforeIndex;
19252 if (insertBeforeIndex === null) {
19253 setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);
19254 insertBeforeIndex = tNode.insertBeforeIndex =
19255 [null /* may be updated to number later */, index];
19256 }
19257 else {
19258 assertEqual(Array.isArray(insertBeforeIndex), true, 'Expecting array here');
19259 insertBeforeIndex.push(index);
19260 }
19261}
19262/**
19263 * Create `TNode.type=TNodeType.Placeholder` node.
19264 *
19265 * See `TNodeType.Placeholder` for more information.
19266 */
19267function createTNodePlaceholder(tView, previousTNodes, index) {
19268 const tNode = createTNodeAtIndex(tView, index, 64 /* Placeholder */, null, null);
19269 addTNodeAndUpdateInsertBeforeIndex(previousTNodes, tNode);
19270 return tNode;
19271}
19272/**
19273 * Returns current ICU case.
19274 *
19275 * ICU cases are stored as index into the `TIcu.cases`.
19276 * At times it is necessary to communicate that the ICU case just switched and that next ICU update
19277 * should update all bindings regardless of the mask. In such a case the we store negative numbers
19278 * for cases which have just been switched. This function removes the negative flag.
19279 */
19280function getCurrentICUCaseIndex(tIcu, lView) {
19281 const currentCase = lView[tIcu.currentCaseLViewIndex];
19282 return currentCase === null ? currentCase : (currentCase < 0 ? ~currentCase : currentCase);
19283}
19284function getParentFromIcuCreateOpCode(mergedCode) {
19285 return mergedCode >>> 17 /* SHIFT_PARENT */;
19286}
19287function getRefFromIcuCreateOpCode(mergedCode) {
19288 return (mergedCode & 131070 /* MASK_REF */) >>> 1 /* SHIFT_REF */;
19289}
19290function getInstructionFromIcuCreateOpCode(mergedCode) {
19291 return mergedCode & 1 /* MASK_INSTRUCTION */;
19292}
19293function icuCreateOpCode(opCode, parentIdx, refIdx) {
19294 ngDevMode && assertGreaterThanOrEqual(parentIdx, 0, 'Missing parent index');
19295 ngDevMode && assertGreaterThan(refIdx, 0, 'Missing ref index');
19296 return opCode | parentIdx << 17 /* SHIFT_PARENT */ | refIdx << 1 /* SHIFT_REF */;
19297}
19298
19299/**
19300 * @license
19301 * Copyright Google LLC All Rights Reserved.
19302 *
19303 * Use of this source code is governed by an MIT-style license that can be
19304 * found in the LICENSE file at https://angular.io/license
19305 */
19306/**
19307 * Keep track of which input bindings in `ɵɵi18nExp` have changed.
19308 *
19309 * This is used to efficiently update expressions in i18n only when the corresponding input has
19310 * changed.
19311 *
19312 * 1) Each bit represents which of the `ɵɵi18nExp` has changed.
19313 * 2) There are 32 bits allowed in JS.
19314 * 3) Bit 32 is special as it is shared for all changes past 32. (In other words if you have more
19315 * than 32 `ɵɵi18nExp` then all changes past 32nd `ɵɵi18nExp` will be mapped to same bit. This means
19316 * that we may end up changing more than we need to. But i18n expressions with 32 bindings is rare
19317 * so in practice it should not be an issue.)
19318 */
19319let changeMask = 0b0;
19320/**
19321 * Keeps track of which bit needs to be updated in `changeMask`
19322 *
19323 * This value gets incremented on every call to `ɵɵi18nExp`
19324 */
19325let changeMaskCounter = 0;
19326/**
19327 * Keep track of which input bindings in `ɵɵi18nExp` have changed.
19328 *
19329 * `setMaskBit` gets invoked by each call to `ɵɵi18nExp`.
19330 *
19331 * @param hasChange did `ɵɵi18nExp` detect a change.
19332 */
19333function setMaskBit(hasChange) {
19334 if (hasChange) {
19335 changeMask = changeMask | (1 << Math.min(changeMaskCounter, 31));
19336 }
19337 changeMaskCounter++;
19338}
19339function applyI18n(tView, lView, index) {
19340 if (changeMaskCounter > 0) {
19341 ngDevMode && assertDefined(tView, `tView should be defined`);
19342 const tI18n = tView.data[index];
19343 // When `index` points to an `ɵɵi18nAttributes` then we have an array otherwise `TI18n`
19344 const updateOpCodes = Array.isArray(tI18n) ? tI18n : tI18n.update;
19345 const bindingsStartIndex = getBindingIndex() - changeMaskCounter - 1;
19346 applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask);
19347 }
19348 // Reset changeMask & maskBit to default for the next update cycle
19349 changeMask = 0b0;
19350 changeMaskCounter = 0;
19351}
19352/**
19353 * Apply `I18nCreateOpCodes` op-codes as stored in `TI18n.create`.
19354 *
19355 * Creates text (and comment) nodes which are internationalized.
19356 *
19357 * @param lView Current lView
19358 * @param createOpCodes Set of op-codes to apply
19359 * @param parentRNode Parent node (so that direct children can be added eagerly) or `null` if it is
19360 * a root node.
19361 * @param insertInFrontOf DOM node that should be used as an anchor.
19362 */
19363function applyCreateOpCodes(lView, createOpCodes, parentRNode, insertInFrontOf) {
19364 const renderer = lView[RENDERER];
19365 for (let i = 0; i < createOpCodes.length; i++) {
19366 const opCode = createOpCodes[i++];
19367 const text = createOpCodes[i];
19368 const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;
19369 const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;
19370 const index = opCode >>> I18nCreateOpCode.SHIFT;
19371 let rNode = lView[index];
19372 if (rNode === null) {
19373 // We only create new DOM nodes if they don't already exist: If ICU switches case back to a
19374 // case which was already instantiated, no need to create new DOM nodes.
19375 rNode = lView[index] =
19376 isComment ? renderer.createComment(text) : createTextNode(renderer, text);
19377 }
19378 if (appendNow && parentRNode !== null) {
19379 nativeInsertBefore(renderer, parentRNode, rNode, insertInFrontOf, false);
19380 }
19381 }
19382}
19383/**
19384 * Apply `I18nMutateOpCodes` OpCodes.
19385 *
19386 * @param tView Current `TView`
19387 * @param mutableOpCodes Mutable OpCodes to process
19388 * @param lView Current `LView`
19389 * @param anchorRNode place where the i18n node should be inserted.
19390 */
19391function applyMutableOpCodes(tView, mutableOpCodes, lView, anchorRNode) {
19392 ngDevMode && assertDomNode(anchorRNode);
19393 const renderer = lView[RENDERER];
19394 // `rootIdx` represents the node into which all inserts happen.
19395 let rootIdx = null;
19396 // `rootRNode` represents the real node into which we insert. This can be different from
19397 // `lView[rootIdx]` if we have projection.
19398 // - null we don't have a parent (as can be the case in when we are inserting into a root of
19399 // LView which has no parent.)
19400 // - `RElement` The element representing the root after taking projection into account.
19401 let rootRNode;
19402 for (let i = 0; i < mutableOpCodes.length; i++) {
19403 const opCode = mutableOpCodes[i];
19404 if (typeof opCode == 'string') {
19405 const textNodeIndex = mutableOpCodes[++i];
19406 if (lView[textNodeIndex] === null) {
19407 ngDevMode && ngDevMode.rendererCreateTextNode++;
19408 ngDevMode && assertIndexInRange(lView, textNodeIndex);
19409 lView[textNodeIndex] = createTextNode(renderer, opCode);
19410 }
19411 }
19412 else if (typeof opCode == 'number') {
19413 switch (opCode & 1 /* MASK_INSTRUCTION */) {
19414 case 0 /* AppendChild */:
19415 const parentIdx = getParentFromIcuCreateOpCode(opCode);
19416 if (rootIdx === null) {
19417 // The first operation should save the `rootIdx` because the first operation
19418 // must insert into the root. (Only subsequent operations can insert into a dynamic
19419 // parent)
19420 rootIdx = parentIdx;
19421 rootRNode = nativeParentNode(renderer, anchorRNode);
19422 }
19423 let insertInFrontOf;
19424 let parentRNode;
19425 if (parentIdx === rootIdx) {
19426 insertInFrontOf = anchorRNode;
19427 parentRNode = rootRNode;
19428 }
19429 else {
19430 insertInFrontOf = null;
19431 parentRNode = unwrapRNode(lView[parentIdx]);
19432 }
19433 // FIXME(misko): Refactor with `processI18nText`
19434 if (parentRNode !== null) {
19435 // This can happen if the `LView` we are adding to is not attached to a parent `LView`.
19436 // In such a case there is no "root" we can attach to. This is fine, as we still need to
19437 // create the elements. When the `LView` gets later added to a parent these "root" nodes
19438 // get picked up and added.
19439 ngDevMode && assertDomNode(parentRNode);
19440 const refIdx = getRefFromIcuCreateOpCode(opCode);
19441 ngDevMode && assertGreaterThan(refIdx, HEADER_OFFSET, 'Missing ref');
19442 // `unwrapRNode` is not needed here as all of these point to RNodes as part of the i18n
19443 // which can't have components.
19444 const child = lView[refIdx];
19445 ngDevMode && assertDomNode(child);
19446 nativeInsertBefore(renderer, parentRNode, child, insertInFrontOf, false);
19447 const tIcu = getTIcu(tView, refIdx);
19448 if (tIcu !== null && typeof tIcu === 'object') {
19449 // If we just added a comment node which has ICU then that ICU may have already been
19450 // rendered and therefore we need to re-add it here.
19451 ngDevMode && assertTIcu(tIcu);
19452 const caseIndex = getCurrentICUCaseIndex(tIcu, lView);
19453 if (caseIndex !== null) {
19454 applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, lView[tIcu.anchorIdx]);
19455 }
19456 }
19457 }
19458 break;
19459 case 1 /* Attr */:
19460 const elementNodeIndex = opCode >>> 1 /* SHIFT_REF */;
19461 const attrName = mutableOpCodes[++i];
19462 const attrValue = mutableOpCodes[++i];
19463 // This code is used for ICU expressions only, since we don't support
19464 // directives/components in ICUs, we don't need to worry about inputs here
19465 setElementAttribute$1(renderer, getNativeByIndex(elementNodeIndex, lView), null, null, attrName, attrValue, null);
19466 break;
19467 default:
19468 throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
19469 }
19470 }
19471 else {
19472 switch (opCode) {
19473 case ICU_MARKER:
19474 const commentValue = mutableOpCodes[++i];
19475 const commentNodeIndex = mutableOpCodes[++i];
19476 if (lView[commentNodeIndex] === null) {
19477 ngDevMode &&
19478 assertEqual(typeof commentValue, 'string', `Expected "${commentValue}" to be a comment node value`);
19479 ngDevMode && ngDevMode.rendererCreateComment++;
19480 ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex);
19481 const commentRNode = lView[commentNodeIndex] =
19482 createCommentNode(renderer, commentValue);
19483 // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)
19484 attachPatchData(commentRNode, lView);
19485 }
19486 break;
19487 case ELEMENT_MARKER:
19488 const tagName = mutableOpCodes[++i];
19489 const elementNodeIndex = mutableOpCodes[++i];
19490 if (lView[elementNodeIndex] === null) {
19491 ngDevMode &&
19492 assertEqual(typeof tagName, 'string', `Expected "${tagName}" to be an element node tag name`);
19493 ngDevMode && ngDevMode.rendererCreateElement++;
19494 ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex);
19495 const elementRNode = lView[elementNodeIndex] =
19496 createElementNode(renderer, tagName, null);
19497 // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)
19498 attachPatchData(elementRNode, lView);
19499 }
19500 break;
19501 default:
19502 ngDevMode &&
19503 throwError(`Unable to determine the type of mutate operation for "${opCode}"`);
19504 }
19505 }
19506 }
19507}
19508/**
19509 * Apply `I18nUpdateOpCodes` OpCodes
19510 *
19511 * @param tView Current `TView`
19512 * @param lView Current `LView`
19513 * @param updateOpCodes OpCodes to process
19514 * @param bindingsStartIndex Location of the first `ɵɵi18nApply`
19515 * @param changeMask Each bit corresponds to a `ɵɵi18nExp` (Counting backwards from
19516 * `bindingsStartIndex`)
19517 */
19518function applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask) {
19519 for (let i = 0; i < updateOpCodes.length; i++) {
19520 // bit code to check if we should apply the next update
19521 const checkBit = updateOpCodes[i];
19522 // Number of opCodes to skip until next set of update codes
19523 const skipCodes = updateOpCodes[++i];
19524 if (checkBit & changeMask) {
19525 // The value has been updated since last checked
19526 let value = '';
19527 for (let j = i + 1; j <= (i + skipCodes); j++) {
19528 const opCode = updateOpCodes[j];
19529 if (typeof opCode == 'string') {
19530 value += opCode;
19531 }
19532 else if (typeof opCode == 'number') {
19533 if (opCode < 0) {
19534 // Negative opCode represent `i18nExp` values offset.
19535 value += renderStringify(lView[bindingsStartIndex - opCode]);
19536 }
19537 else {
19538 const nodeIndex = (opCode >>> 2 /* SHIFT_REF */);
19539 switch (opCode & 3 /* MASK_OPCODE */) {
19540 case 1 /* Attr */:
19541 const propName = updateOpCodes[++j];
19542 const sanitizeFn = updateOpCodes[++j];
19543 const tNodeOrTagName = tView.data[nodeIndex];
19544 ngDevMode && assertDefined(tNodeOrTagName, 'Experting TNode or string');
19545 if (typeof tNodeOrTagName === 'string') {
19546 // IF we don't have a `TNode`, then we are an element in ICU (as ICU content does
19547 // not have TNode), in which case we know that there are no directives, and hence
19548 // we use attribute setting.
19549 setElementAttribute$1(lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value, sanitizeFn);
19550 }
19551 else {
19552 elementPropertyInternal(tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn, false);
19553 }
19554 break;
19555 case 0 /* Text */:
19556 const rText = lView[nodeIndex];
19557 rText !== null && updateTextNode(lView[RENDERER], rText, value);
19558 break;
19559 case 2 /* IcuSwitch */:
19560 applyIcuSwitchCase(tView, getTIcu(tView, nodeIndex), lView, value);
19561 break;
19562 case 3 /* IcuUpdate */:
19563 applyIcuUpdateCase(tView, getTIcu(tView, nodeIndex), bindingsStartIndex, lView);
19564 break;
19565 }
19566 }
19567 }
19568 }
19569 }
19570 else {
19571 const opCode = updateOpCodes[i + 1];
19572 if (opCode > 0 && (opCode & 3 /* MASK_OPCODE */) === 3 /* IcuUpdate */) {
19573 // Special case for the `icuUpdateCase`. It could be that the mask did not match, but
19574 // we still need to execute `icuUpdateCase` because the case has changed recently due to
19575 // previous `icuSwitchCase` instruction. (`icuSwitchCase` and `icuUpdateCase` always come in
19576 // pairs.)
19577 const nodeIndex = (opCode >>> 2 /* SHIFT_REF */);
19578 const tIcu = getTIcu(tView, nodeIndex);
19579 const currentIndex = lView[tIcu.currentCaseLViewIndex];
19580 if (currentIndex < 0) {
19581 applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView);
19582 }
19583 }
19584 }
19585 i += skipCodes;
19586 }
19587}
19588/**
19589 * Apply OpCodes associated with updating an existing ICU.
19590 *
19591 * @param tView Current `TView`
19592 * @param tIcu Current `TIcu`
19593 * @param bindingsStartIndex Location of the first `ɵɵi18nApply`
19594 * @param lView Current `LView`
19595 */
19596function applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView) {
19597 ngDevMode && assertIndexInRange(lView, tIcu.currentCaseLViewIndex);
19598 let activeCaseIndex = lView[tIcu.currentCaseLViewIndex];
19599 if (activeCaseIndex !== null) {
19600 let mask = changeMask;
19601 if (activeCaseIndex < 0) {
19602 // Clear the flag.
19603 // Negative number means that the ICU was freshly created and we need to force the update.
19604 activeCaseIndex = lView[tIcu.currentCaseLViewIndex] = ~activeCaseIndex;
19605 // -1 is same as all bits on, which simulates creation since it marks all bits dirty
19606 mask = -1;
19607 }
19608 applyUpdateOpCodes(tView, lView, tIcu.update[activeCaseIndex], bindingsStartIndex, mask);
19609 }
19610}
19611/**
19612 * Apply OpCodes associated with switching a case on ICU.
19613 *
19614 * This involves tearing down existing case and than building up a new case.
19615 *
19616 * @param tView Current `TView`
19617 * @param tIcu Current `TIcu`
19618 * @param lView Current `LView`
19619 * @param value Value of the case to update to.
19620 */
19621function applyIcuSwitchCase(tView, tIcu, lView, value) {
19622 // Rebuild a new case for this ICU
19623 const caseIndex = getCaseIndex(tIcu, value);
19624 let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);
19625 if (activeCaseIndex !== caseIndex) {
19626 applyIcuSwitchCaseRemove(tView, tIcu, lView);
19627 lView[tIcu.currentCaseLViewIndex] = caseIndex === null ? null : ~caseIndex;
19628 if (caseIndex !== null) {
19629 // Add the nodes for the new case
19630 const anchorRNode = lView[tIcu.anchorIdx];
19631 if (anchorRNode) {
19632 ngDevMode && assertDomNode(anchorRNode);
19633 applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, anchorRNode);
19634 }
19635 }
19636 }
19637}
19638/**
19639 * Apply OpCodes associated with tearing ICU case.
19640 *
19641 * This involves tearing down existing case and than building up a new case.
19642 *
19643 * @param tView Current `TView`
19644 * @param tIcu Current `TIcu`
19645 * @param lView Current `LView`
19646 */
19647function applyIcuSwitchCaseRemove(tView, tIcu, lView) {
19648 let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);
19649 if (activeCaseIndex !== null) {
19650 const removeCodes = tIcu.remove[activeCaseIndex];
19651 for (let i = 0; i < removeCodes.length; i++) {
19652 const nodeOrIcuIndex = removeCodes[i];
19653 if (nodeOrIcuIndex > 0) {
19654 // Positive numbers are `RNode`s.
19655 const rNode = getNativeByIndex(nodeOrIcuIndex, lView);
19656 rNode !== null && nativeRemoveNode(lView[RENDERER], rNode);
19657 }
19658 else {
19659 // Negative numbers are ICUs
19660 applyIcuSwitchCaseRemove(tView, getTIcu(tView, ~nodeOrIcuIndex), lView);
19661 }
19662 }
19663 }
19664}
19665/**
19666 * Returns the index of the current case of an ICU expression depending on the main binding value
19667 *
19668 * @param icuExpression
19669 * @param bindingValue The value of the main binding used by this ICU expression
19670 */
19671function getCaseIndex(icuExpression, bindingValue) {
19672 let index = icuExpression.cases.indexOf(bindingValue);
19673 if (index === -1) {
19674 switch (icuExpression.type) {
19675 case 1 /* plural */: {
19676 const resolvedCase = getPluralCase(bindingValue, getLocaleId());
19677 index = icuExpression.cases.indexOf(resolvedCase);
19678 if (index === -1 && resolvedCase !== 'other') {
19679 index = icuExpression.cases.indexOf('other');
19680 }
19681 break;
19682 }
19683 case 0 /* select */: {
19684 index = icuExpression.cases.indexOf('other');
19685 break;
19686 }
19687 }
19688 }
19689 return index === -1 ? null : index;
19690}
19691
19692/**
19693 * @license
19694 * Copyright Google LLC All Rights Reserved.
19695 *
19696 * Use of this source code is governed by an MIT-style license that can be
19697 * found in the LICENSE file at https://angular.io/license
19698 */
19699function loadIcuContainerVisitor() {
19700 const _stack = [];
19701 let _index = -1;
19702 let _lView;
19703 let _removes;
19704 /**
19705 * Retrieves a set of root nodes from `TIcu.remove`. Used by `TNodeType.ICUContainer`
19706 * to determine which root belong to the ICU.
19707 *
19708 * Example of usage.
19709 * ```
19710 * const nextRNode = icuContainerIteratorStart(tIcuContainerNode, lView);
19711 * let rNode: RNode|null;
19712 * while(rNode = nextRNode()) {
19713 * console.log(rNode);
19714 * }
19715 * ```
19716 *
19717 * @param tIcuContainerNode Current `TIcuContainerNode`
19718 * @param lView `LView` where the `RNode`s should be looked up.
19719 */
19720 function icuContainerIteratorStart(tIcuContainerNode, lView) {
19721 _lView = lView;
19722 while (_stack.length)
19723 _stack.pop();
19724 ngDevMode && assertTNodeForLView(tIcuContainerNode, lView);
19725 enterIcu(tIcuContainerNode.value, lView);
19726 return icuContainerIteratorNext;
19727 }
19728 function enterIcu(tIcu, lView) {
19729 _index = 0;
19730 const currentCase = getCurrentICUCaseIndex(tIcu, lView);
19731 if (currentCase !== null) {
19732 ngDevMode && assertNumberInRange(currentCase, 0, tIcu.cases.length - 1);
19733 _removes = tIcu.remove[currentCase];
19734 }
19735 else {
19736 _removes = EMPTY_ARRAY;
19737 }
19738 }
19739 function icuContainerIteratorNext() {
19740 if (_index < _removes.length) {
19741 const removeOpCode = _removes[_index++];
19742 ngDevMode && assertNumber(removeOpCode, 'Expecting OpCode number');
19743 if (removeOpCode > 0) {
19744 const rNode = _lView[removeOpCode];
19745 ngDevMode && assertDomNode(rNode);
19746 return rNode;
19747 }
19748 else {
19749 _stack.push(_index, _removes);
19750 // ICUs are represented by negative indices
19751 const tIcuIndex = ~removeOpCode;
19752 const tIcu = _lView[TVIEW].data[tIcuIndex];
19753 ngDevMode && assertTIcu(tIcu);
19754 enterIcu(tIcu, _lView);
19755 return icuContainerIteratorNext();
19756 }
19757 }
19758 else {
19759 if (_stack.length === 0) {
19760 return null;
19761 }
19762 else {
19763 _removes = _stack.pop();
19764 _index = _stack.pop();
19765 return icuContainerIteratorNext();
19766 }
19767 }
19768 }
19769 return icuContainerIteratorStart;
19770}
19771
19772/**
19773 * @license
19774 * Copyright Google LLC All Rights Reserved.
19775 *
19776 * Use of this source code is governed by an MIT-style license that can be
19777 * found in the LICENSE file at https://angular.io/license
19778 */
19779/**
19780 * Converts `I18nCreateOpCodes` array into a human readable format.
19781 *
19782 * This function is attached to the `I18nCreateOpCodes.debug` property if `ngDevMode` is enabled.
19783 * This function provides a human readable view of the opcodes. This is useful when debugging the
19784 * application as well as writing more readable tests.
19785 *
19786 * @param this `I18nCreateOpCodes` if attached as a method.
19787 * @param opcodes `I18nCreateOpCodes` if invoked as a function.
19788 */
19789function i18nCreateOpCodesToString(opcodes) {
19790 const createOpCodes = opcodes || (Array.isArray(this) ? this : []);
19791 let lines = [];
19792 for (let i = 0; i < createOpCodes.length; i++) {
19793 const opCode = createOpCodes[i++];
19794 const text = createOpCodes[i];
19795 const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;
19796 const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;
19797 const index = opCode >>> I18nCreateOpCode.SHIFT;
19798 lines.push(`lView[${index}] = document.${isComment ? 'createComment' : 'createText'}(${JSON.stringify(text)});`);
19799 if (appendNow) {
19800 lines.push(`parent.appendChild(lView[${index}]);`);
19801 }
19802 }
19803 return lines;
19804}
19805/**
19806 * Converts `I18nUpdateOpCodes` array into a human readable format.
19807 *
19808 * This function is attached to the `I18nUpdateOpCodes.debug` property if `ngDevMode` is enabled.
19809 * This function provides a human readable view of the opcodes. This is useful when debugging the
19810 * application as well as writing more readable tests.
19811 *
19812 * @param this `I18nUpdateOpCodes` if attached as a method.
19813 * @param opcodes `I18nUpdateOpCodes` if invoked as a function.
19814 */
19815function i18nUpdateOpCodesToString(opcodes) {
19816 const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : []));
19817 let lines = [];
19818 function consumeOpCode(value) {
19819 const ref = value >>> 2 /* SHIFT_REF */;
19820 const opCode = value & 3 /* MASK_OPCODE */;
19821 switch (opCode) {
19822 case 0 /* Text */:
19823 return `(lView[${ref}] as Text).textContent = $$$`;
19824 case 1 /* Attr */:
19825 const attrName = parser.consumeString();
19826 const sanitizationFn = parser.consumeFunction();
19827 const value = sanitizationFn ? `(${sanitizationFn})($$$)` : '$$$';
19828 return `(lView[${ref}] as Element).setAttribute('${attrName}', ${value})`;
19829 case 2 /* IcuSwitch */:
19830 return `icuSwitchCase(${ref}, $$$)`;
19831 case 3 /* IcuUpdate */:
19832 return `icuUpdateCase(${ref})`;
19833 }
19834 throw new Error('unexpected OpCode');
19835 }
19836 while (parser.hasMore()) {
19837 let mask = parser.consumeNumber();
19838 let size = parser.consumeNumber();
19839 const end = parser.i + size;
19840 const statements = [];
19841 let statement = '';
19842 while (parser.i < end) {
19843 let value = parser.consumeNumberOrString();
19844 if (typeof value === 'string') {
19845 statement += value;
19846 }
19847 else if (value < 0) {
19848 // Negative numbers are ref indexes
19849 // Here `i` refers to current binding index. It is to signify that the value is relative,
19850 // rather than absolute.
19851 statement += '${lView[i' + value + ']}';
19852 }
19853 else {
19854 // Positive numbers are operations.
19855 const opCodeText = consumeOpCode(value);
19856 statements.push(opCodeText.replace('$$$', '`' + statement + '`') + ';');
19857 statement = '';
19858 }
19859 }
19860 lines.push(`if (mask & 0b${mask.toString(2)}) { ${statements.join(' ')} }`);
19861 }
19862 return lines;
19863}
19864/**
19865 * Converts `I18nCreateOpCodes` array into a human readable format.
19866 *
19867 * This function is attached to the `I18nCreateOpCodes.debug` if `ngDevMode` is enabled. This
19868 * function provides a human readable view of the opcodes. This is useful when debugging the
19869 * application as well as writing more readable tests.
19870 *
19871 * @param this `I18nCreateOpCodes` if attached as a method.
19872 * @param opcodes `I18nCreateOpCodes` if invoked as a function.
19873 */
19874function icuCreateOpCodesToString(opcodes) {
19875 const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : []));
19876 let lines = [];
19877 function consumeOpCode(opCode) {
19878 const parent = getParentFromIcuCreateOpCode(opCode);
19879 const ref = getRefFromIcuCreateOpCode(opCode);
19880 switch (getInstructionFromIcuCreateOpCode(opCode)) {
19881 case 0 /* AppendChild */:
19882 return `(lView[${parent}] as Element).appendChild(lView[${lastRef}])`;
19883 case 1 /* Attr */:
19884 return `(lView[${ref}] as Element).setAttribute("${parser.consumeString()}", "${parser.consumeString()}")`;
19885 }
19886 throw new Error('Unexpected OpCode: ' + getInstructionFromIcuCreateOpCode(opCode));
19887 }
19888 let lastRef = -1;
19889 while (parser.hasMore()) {
19890 let value = parser.consumeNumberStringOrMarker();
19891 if (value === ICU_MARKER) {
19892 const text = parser.consumeString();
19893 lastRef = parser.consumeNumber();
19894 lines.push(`lView[${lastRef}] = document.createComment("${text}")`);
19895 }
19896 else if (value === ELEMENT_MARKER) {
19897 const text = parser.consumeString();
19898 lastRef = parser.consumeNumber();
19899 lines.push(`lView[${lastRef}] = document.createElement("${text}")`);
19900 }
19901 else if (typeof value === 'string') {
19902 lastRef = parser.consumeNumber();
19903 lines.push(`lView[${lastRef}] = document.createTextNode("${value}")`);
19904 }
19905 else if (typeof value === 'number') {
19906 const line = consumeOpCode(value);
19907 line && lines.push(line);
19908 }
19909 else {
19910 throw new Error('Unexpected value');
19911 }
19912 }
19913 return lines;
19914}
19915/**
19916 * Converts `I18nRemoveOpCodes` array into a human readable format.
19917 *
19918 * This function is attached to the `I18nRemoveOpCodes.debug` if `ngDevMode` is enabled. This
19919 * function provides a human readable view of the opcodes. This is useful when debugging the
19920 * application as well as writing more readable tests.
19921 *
19922 * @param this `I18nRemoveOpCodes` if attached as a method.
19923 * @param opcodes `I18nRemoveOpCodes` if invoked as a function.
19924 */
19925function i18nRemoveOpCodesToString(opcodes) {
19926 const removeCodes = opcodes || (Array.isArray(this) ? this : []);
19927 let lines = [];
19928 for (let i = 0; i < removeCodes.length; i++) {
19929 const nodeOrIcuIndex = removeCodes[i];
19930 if (nodeOrIcuIndex > 0) {
19931 // Positive numbers are `RNode`s.
19932 lines.push(`remove(lView[${nodeOrIcuIndex}])`);
19933 }
19934 else {
19935 // Negative numbers are ICUs
19936 lines.push(`removeNestedICU(${~nodeOrIcuIndex})`);
19937 }
19938 }
19939 return lines;
19940}
19941class OpCodeParser {
19942 constructor(codes) {
19943 this.i = 0;
19944 this.codes = codes;
19945 }
19946 hasMore() {
19947 return this.i < this.codes.length;
19948 }
19949 consumeNumber() {
19950 let value = this.codes[this.i++];
19951 assertNumber(value, 'expecting number in OpCode');
19952 return value;
19953 }
19954 consumeString() {
19955 let value = this.codes[this.i++];
19956 assertString(value, 'expecting string in OpCode');
19957 return value;
19958 }
19959 consumeFunction() {
19960 let value = this.codes[this.i++];
19961 if (value === null || typeof value === 'function') {
19962 return value;
19963 }
19964 throw new Error('expecting function in OpCode');
19965 }
19966 consumeNumberOrString() {
19967 let value = this.codes[this.i++];
19968 if (typeof value === 'string') {
19969 return value;
19970 }
19971 assertNumber(value, 'expecting number or string in OpCode');
19972 return value;
19973 }
19974 consumeNumberStringOrMarker() {
19975 let value = this.codes[this.i++];
19976 if (typeof value === 'string' || typeof value === 'number' || value == ICU_MARKER ||
19977 value == ELEMENT_MARKER) {
19978 return value;
19979 }
19980 assertNumber(value, 'expecting number, string, ICU_MARKER or ELEMENT_MARKER in OpCode');
19981 return value;
19982 }
19983}
19984
19985/**
19986 * @license
19987 * Copyright Google LLC All Rights Reserved.
19988 *
19989 * Use of this source code is governed by an MIT-style license that can be
19990 * found in the LICENSE file at https://angular.io/license
19991 */
19992const BINDING_REGEXP = /�(\d+):?\d*�/gi;
19993const ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi;
19994const NESTED_ICU = /�(\d+)�/;
19995const ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/;
19996const MARKER = `�`;
19997const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi;
19998const PH_REGEXP = /�(\/?[#*]\d+):?\d*�/gi;
19999/**
20000 * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
20001 * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
20002 * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
20003 * and later on replaced by a space. We are re-implementing the same idea here, since translations
20004 * might contain this special character.
20005 */
20006const NGSP_UNICODE_REGEXP = /\uE500/g;
20007function replaceNgsp(value) {
20008 return value.replace(NGSP_UNICODE_REGEXP, ' ');
20009}
20010/**
20011 * Create dynamic nodes from i18n translation block.
20012 *
20013 * - Text nodes are created synchronously
20014 * - TNodes are linked into tree lazily
20015 *
20016 * @param tView Current `TView`
20017 * @parentTNodeIndex index to the parent TNode of this i18n block
20018 * @param lView Current `LView`
20019 * @param index Index of `ɵɵi18nStart` instruction.
20020 * @param message Message to translate.
20021 * @param subTemplateIndex Index into the sub template of message translation. (ie in case of
20022 * `ngIf`) (-1 otherwise)
20023 */
20024function i18nStartFirstCreatePass(tView, parentTNodeIndex, lView, index, message, subTemplateIndex) {
20025 const rootTNode = getCurrentParentTNode();
20026 const createOpCodes = [];
20027 const updateOpCodes = [];
20028 const existingTNodeStack = [[]];
20029 if (ngDevMode) {
20030 attachDebugGetter(createOpCodes, i18nCreateOpCodesToString);
20031 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
20032 }
20033 message = getTranslationForTemplate(message, subTemplateIndex);
20034 const msgParts = replaceNgsp(message).split(PH_REGEXP);
20035 for (let i = 0; i < msgParts.length; i++) {
20036 let value = msgParts[i];
20037 if ((i & 1) === 0) {
20038 // Even indexes are text (including bindings & ICU expressions)
20039 const parts = i18nParseTextIntoPartsAndICU(value);
20040 for (let j = 0; j < parts.length; j++) {
20041 let part = parts[j];
20042 if ((j & 1) === 0) {
20043 // `j` is odd therefore `part` is string
20044 const text = part;
20045 ngDevMode && assertString(text, 'Parsed ICU part should be string');
20046 if (text !== '') {
20047 i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodeStack[0], createOpCodes, updateOpCodes, lView, text);
20048 }
20049 }
20050 else {
20051 // `j` is Even therefor `part` is an `ICUExpression`
20052 const icuExpression = part;
20053 // Verify that ICU expression has the right shape. Translations might contain invalid
20054 // constructions (while original messages were correct), so ICU parsing at runtime may
20055 // not succeed (thus `icuExpression` remains a string).
20056 // Note: we intentionally retain the error here by not using `ngDevMode`, because
20057 // the value can change based on the locale and users aren't guaranteed to hit
20058 // an invalid string while they're developing.
20059 if (typeof icuExpression !== 'object') {
20060 throw new Error(`Unable to parse ICU expression in "${message}" message.`);
20061 }
20062 const icuContainerTNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodeStack[0], lView, createOpCodes, ngDevMode ? `ICU ${index}:${icuExpression.mainBinding}` : '', true);
20063 const icuNodeIndex = icuContainerTNode.index;
20064 ngDevMode &&
20065 assertGreaterThanOrEqual(icuNodeIndex, HEADER_OFFSET, 'Index must be in absolute LView offset');
20066 icuStart(tView, lView, updateOpCodes, parentTNodeIndex, icuExpression, icuNodeIndex);
20067 }
20068 }
20069 }
20070 else {
20071 // Odd indexes are placeholders (elements and sub-templates)
20072 // At this point value is something like: '/#1:2' (originally coming from '�/#1:2�')
20073 const isClosing = value.charCodeAt(0) === 47 /* SLASH */;
20074 const type = value.charCodeAt(isClosing ? 1 : 0);
20075 ngDevMode && assertOneOf(type, 42 /* STAR */, 35 /* HASH */);
20076 const index = HEADER_OFFSET + Number.parseInt(value.substring((isClosing ? 2 : 1)));
20077 if (isClosing) {
20078 existingTNodeStack.shift();
20079 setCurrentTNode(getCurrentParentTNode(), false);
20080 }
20081 else {
20082 const tNode = createTNodePlaceholder(tView, existingTNodeStack[0], index);
20083 existingTNodeStack.unshift([]);
20084 setCurrentTNode(tNode, true);
20085 }
20086 }
20087 }
20088 tView.data[index] = {
20089 create: createOpCodes,
20090 update: updateOpCodes,
20091 };
20092}
20093/**
20094 * Allocate space in i18n Range add create OpCode instruction to crete a text or comment node.
20095 *
20096 * @param tView Current `TView` needed to allocate space in i18n range.
20097 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will be
20098 * added as part of the `i18nStart` instruction or as part of the `TNode.insertBeforeIndex`.
20099 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.
20100 * @param lView Current `LView` needed to allocate space in i18n range.
20101 * @param createOpCodes Array storing `I18nCreateOpCodes` where new opCodes will be added.
20102 * @param text Text to be added when the `Text` or `Comment` node will be created.
20103 * @param isICU true if a `Comment` node for ICU (instead of `Text`) node should be created.
20104 */
20105function createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, text, isICU) {
20106 const i18nNodeIdx = allocExpando(tView, lView, 1, null);
20107 let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;
20108 let parentTNode = getCurrentParentTNode();
20109 if (rootTNode === parentTNode) {
20110 // FIXME(misko): A null `parentTNode` should represent when we fall of the `LView` boundary.
20111 // (there is no parent), but in some circumstances (because we are inconsistent about how we set
20112 // `previousOrParentTNode`) it could point to `rootTNode` So this is a work around.
20113 parentTNode = null;
20114 }
20115 if (parentTNode === null) {
20116 // If we don't have a parent that means that we can eagerly add nodes.
20117 // If we have a parent than these nodes can't be added now (as the parent has not been created
20118 // yet) and instead the `parentTNode` is responsible for adding it. See
20119 // `TNode.insertBeforeIndex`
20120 opCode |= I18nCreateOpCode.APPEND_EAGERLY;
20121 }
20122 if (isICU) {
20123 opCode |= I18nCreateOpCode.COMMENT;
20124 ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);
20125 }
20126 createOpCodes.push(opCode, text === null ? '' : text);
20127 // We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the
20128 // bindings are.
20129 const tNode = createTNodeAtIndex(tView, i18nNodeIdx, isICU ? 32 /* Icu */ : 1 /* Text */, text === null ? (ngDevMode ? '{{?}}' : '') : text, null);
20130 addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);
20131 const tNodeIdx = tNode.index;
20132 setCurrentTNode(tNode, false /* Text nodes are self closing */);
20133 if (parentTNode !== null && rootTNode !== parentTNode) {
20134 // We are a child of deeper node (rather than a direct child of `i18nStart` instruction.)
20135 // We have to make sure to add ourselves to the parent.
20136 setTNodeInsertBeforeIndex(parentTNode, tNodeIdx);
20137 }
20138 return tNode;
20139}
20140/**
20141 * Processes text node in i18n block.
20142 *
20143 * Text nodes can have:
20144 * - Create instruction in `createOpCodes` for creating the text node.
20145 * - Allocate spec for text node in i18n range of `LView`
20146 * - If contains binding:
20147 * - bindings => allocate space in i18n range of `LView` to store the binding value.
20148 * - populate `updateOpCodes` with update instructions.
20149 *
20150 * @param tView Current `TView`
20151 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will
20152 * be added as part of the `i18nStart` instruction or as part of the
20153 * `TNode.insertBeforeIndex`.
20154 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.
20155 * @param createOpCodes Location where the creation OpCodes will be stored.
20156 * @param lView Current `LView`
20157 * @param text The translated text (which may contain binding)
20158 */
20159function i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodes, createOpCodes, updateOpCodes, lView, text) {
20160 const hasBinding = text.match(BINDING_REGEXP);
20161 const tNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false);
20162 if (hasBinding) {
20163 generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index, null, 0, null);
20164 }
20165}
20166/**
20167 * See `i18nAttributes` above.
20168 */
20169function i18nAttributesFirstPass(tView, index, values) {
20170 const previousElement = getCurrentTNode();
20171 const previousElementIndex = previousElement.index;
20172 const updateOpCodes = [];
20173 if (ngDevMode) {
20174 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
20175 }
20176 if (tView.firstCreatePass && tView.data[index] === null) {
20177 for (let i = 0; i < values.length; i += 2) {
20178 const attrName = values[i];
20179 const message = values[i + 1];
20180 if (message !== '') {
20181 // Check if attribute value contains an ICU and throw an error if that's the case.
20182 // ICUs in element attributes are not supported.
20183 // Note: we intentionally retain the error here by not using `ngDevMode`, because
20184 // the `value` can change based on the locale and users aren't guaranteed to hit
20185 // an invalid string while they're developing.
20186 if (ICU_REGEXP.test(message)) {
20187 throw new Error(`ICU expressions are not supported in attributes. Message: "${message}".`);
20188 }
20189 // i18n attributes that hit this code path are guaranteed to have bindings, because
20190 // the compiler treats static i18n attributes as regular attribute bindings.
20191 // Since this may not be the first i18n attribute on this element we need to pass in how
20192 // many previous bindings there have already been.
20193 generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), null);
20194 }
20195 }
20196 tView.data[index] = updateOpCodes;
20197 }
20198}
20199/**
20200 * Generate the OpCodes to update the bindings of a string.
20201 *
20202 * @param updateOpCodes Place where the update opcodes will be stored.
20203 * @param str The string containing the bindings.
20204 * @param destinationNode Index of the destination node which will receive the binding.
20205 * @param attrName Name of the attribute, if the string belongs to an attribute.
20206 * @param sanitizeFn Sanitization function used to sanitize the string after update, if necessary.
20207 * @param bindingStart The lView index of the next expression that can be bound via an opCode.
20208 * @returns The mask value for these bindings
20209 */
20210function generateBindingUpdateOpCodes(updateOpCodes, str, destinationNode, attrName, bindingStart, sanitizeFn) {
20211 ngDevMode &&
20212 assertGreaterThanOrEqual(destinationNode, HEADER_OFFSET, 'Index must be in absolute LView offset');
20213 const maskIndex = updateOpCodes.length; // Location of mask
20214 const sizeIndex = maskIndex + 1; // location of size for skipping
20215 updateOpCodes.push(null, null); // Alloc space for mask and size
20216 const startIndex = maskIndex + 2; // location of first allocation.
20217 if (ngDevMode) {
20218 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
20219 }
20220 const textParts = str.split(BINDING_REGEXP);
20221 let mask = 0;
20222 for (let j = 0; j < textParts.length; j++) {
20223 const textValue = textParts[j];
20224 if (j & 1) {
20225 // Odd indexes are bindings
20226 const bindingIndex = bindingStart + parseInt(textValue, 10);
20227 updateOpCodes.push(-1 - bindingIndex);
20228 mask = mask | toMaskBit(bindingIndex);
20229 }
20230 else if (textValue !== '') {
20231 // Even indexes are text
20232 updateOpCodes.push(textValue);
20233 }
20234 }
20235 updateOpCodes.push(destinationNode << 2 /* SHIFT_REF */ |
20236 (attrName ? 1 /* Attr */ : 0 /* Text */));
20237 if (attrName) {
20238 updateOpCodes.push(attrName, sanitizeFn);
20239 }
20240 updateOpCodes[maskIndex] = mask;
20241 updateOpCodes[sizeIndex] = updateOpCodes.length - startIndex;
20242 return mask;
20243}
20244/**
20245 * Count the number of bindings in the given `opCodes`.
20246 *
20247 * It could be possible to speed this up, by passing the number of bindings found back from
20248 * `generateBindingUpdateOpCodes()` to `i18nAttributesFirstPass()` but this would then require more
20249 * complexity in the code and/or transient objects to be created.
20250 *
20251 * Since this function is only called once when the template is instantiated, is trivial in the
20252 * first instance (since `opCodes` will be an empty array), and it is not common for elements to
20253 * contain multiple i18n bound attributes, it seems like this is a reasonable compromise.
20254 */
20255function countBindings(opCodes) {
20256 let count = 0;
20257 for (let i = 0; i < opCodes.length; i++) {
20258 const opCode = opCodes[i];
20259 // Bindings are negative numbers.
20260 if (typeof opCode === 'number' && opCode < 0) {
20261 count++;
20262 }
20263 }
20264 return count;
20265}
20266/**
20267 * Convert binding index to mask bit.
20268 *
20269 * Each index represents a single bit on the bit-mask. Because bit-mask only has 32 bits, we make
20270 * the 32nd bit share all masks for all bindings higher than 32. Since it is extremely rare to
20271 * have more than 32 bindings this will be hit very rarely. The downside of hitting this corner
20272 * case is that we will execute binding code more often than necessary. (penalty of performance)
20273 */
20274function toMaskBit(bindingIndex) {
20275 return 1 << Math.min(bindingIndex, 31);
20276}
20277function isRootTemplateMessage(subTemplateIndex) {
20278 return subTemplateIndex === -1;
20279}
20280/**
20281 * Removes everything inside the sub-templates of a message.
20282 */
20283function removeInnerTemplateTranslation(message) {
20284 let match;
20285 let res = '';
20286 let index = 0;
20287 let inTemplate = false;
20288 let tagMatched;
20289 while ((match = SUBTEMPLATE_REGEXP.exec(message)) !== null) {
20290 if (!inTemplate) {
20291 res += message.substring(index, match.index + match[0].length);
20292 tagMatched = match[1];
20293 inTemplate = true;
20294 }
20295 else {
20296 if (match[0] === `${MARKER}/*${tagMatched}${MARKER}`) {
20297 index = match.index;
20298 inTemplate = false;
20299 }
20300 }
20301 }
20302 ngDevMode &&
20303 assertEqual(inTemplate, false, `Tag mismatch: unable to find the end of the sub-template in the translation "${message}"`);
20304 res += message.substr(index);
20305 return res;
20306}
20307/**
20308 * Extracts a part of a message and removes the rest.
20309 *
20310 * This method is used for extracting a part of the message associated with a template. A
20311 * translated message can span multiple templates.
20312 *
20313 * Example:
20314 * ```
20315 * <div i18n>Translate <span *ngIf>me</span>!</div>
20316 * ```
20317 *
20318 * @param message The message to crop
20319 * @param subTemplateIndex Index of the sub-template to extract. If undefined it returns the
20320 * external template and removes all sub-templates.
20321 */
20322function getTranslationForTemplate(message, subTemplateIndex) {
20323 if (isRootTemplateMessage(subTemplateIndex)) {
20324 // We want the root template message, ignore all sub-templates
20325 return removeInnerTemplateTranslation(message);
20326 }
20327 else {
20328 // We want a specific sub-template
20329 const start = message.indexOf(`:${subTemplateIndex}${MARKER}`) + 2 + subTemplateIndex.toString().length;
20330 const end = message.search(new RegExp(`${MARKER}\\/\\*\\d+:${subTemplateIndex}${MARKER}`));
20331 return removeInnerTemplateTranslation(message.substring(start, end));
20332 }
20333}
20334/**
20335 * Generate the OpCodes for ICU expressions.
20336 *
20337 * @param icuExpression
20338 * @param index Index where the anchor is stored and an optional `TIcuContainerNode`
20339 * - `lView[anchorIdx]` points to a `Comment` node representing the anchor for the ICU.
20340 * - `tView.data[anchorIdx]` points to the `TIcuContainerNode` if ICU is root (`null` otherwise)
20341 */
20342function icuStart(tView, lView, updateOpCodes, parentIdx, icuExpression, anchorIdx) {
20343 ngDevMode && assertDefined(icuExpression, 'ICU expression must be defined');
20344 let bindingMask = 0;
20345 const tIcu = {
20346 type: icuExpression.type,
20347 currentCaseLViewIndex: allocExpando(tView, lView, 1, null),
20348 anchorIdx,
20349 cases: [],
20350 create: [],
20351 remove: [],
20352 update: []
20353 };
20354 addUpdateIcuSwitch(updateOpCodes, icuExpression, anchorIdx);
20355 setTIcu(tView, anchorIdx, tIcu);
20356 const values = icuExpression.values;
20357 for (let i = 0; i < values.length; i++) {
20358 // Each value is an array of strings & other ICU expressions
20359 const valueArr = values[i];
20360 const nestedIcus = [];
20361 for (let j = 0; j < valueArr.length; j++) {
20362 const value = valueArr[j];
20363 if (typeof value !== 'string') {
20364 // It is an nested ICU expression
20365 const icuIndex = nestedIcus.push(value) - 1;
20366 // Replace nested ICU expression by a comment node
20367 valueArr[j] = `<!--�${icuIndex}�-->`;
20368 }
20369 }
20370 bindingMask = parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, icuExpression.cases[i], valueArr.join(''), nestedIcus) |
20371 bindingMask;
20372 }
20373 if (bindingMask) {
20374 addUpdateIcuUpdate(updateOpCodes, bindingMask, anchorIdx);
20375 }
20376}
20377/**
20378 * Parses text containing an ICU expression and produces a JSON object for it.
20379 * Original code from closure library, modified for Angular.
20380 *
20381 * @param pattern Text containing an ICU expression that needs to be parsed.
20382 *
20383 */
20384function parseICUBlock(pattern) {
20385 const cases = [];
20386 const values = [];
20387 let icuType = 1 /* plural */;
20388 let mainBinding = 0;
20389 pattern = pattern.replace(ICU_BLOCK_REGEXP, function (str, binding, type) {
20390 if (type === 'select') {
20391 icuType = 0 /* select */;
20392 }
20393 else {
20394 icuType = 1 /* plural */;
20395 }
20396 mainBinding = parseInt(binding.substr(1), 10);
20397 return '';
20398 });
20399 const parts = i18nParseTextIntoPartsAndICU(pattern);
20400 // Looking for (key block)+ sequence. One of the keys has to be "other".
20401 for (let pos = 0; pos < parts.length;) {
20402 let key = parts[pos++].trim();
20403 if (icuType === 1 /* plural */) {
20404 // Key can be "=x", we just want "x"
20405 key = key.replace(/\s*(?:=)?(\w+)\s*/, '$1');
20406 }
20407 if (key.length) {
20408 cases.push(key);
20409 }
20410 const blocks = i18nParseTextIntoPartsAndICU(parts[pos++]);
20411 if (cases.length > values.length) {
20412 values.push(blocks);
20413 }
20414 }
20415 // TODO(ocombe): support ICU expressions in attributes, see #21615
20416 return { type: icuType, mainBinding: mainBinding, cases, values };
20417}
20418/**
20419 * Breaks pattern into strings and top level {...} blocks.
20420 * Can be used to break a message into text and ICU expressions, or to break an ICU expression
20421 * into keys and cases. Original code from closure library, modified for Angular.
20422 *
20423 * @param pattern (sub)Pattern to be broken.
20424 * @returns An `Array<string|IcuExpression>` where:
20425 * - odd positions: `string` => text between ICU expressions
20426 * - even positions: `ICUExpression` => ICU expression parsed into `ICUExpression` record.
20427 */
20428function i18nParseTextIntoPartsAndICU(pattern) {
20429 if (!pattern) {
20430 return [];
20431 }
20432 let prevPos = 0;
20433 const braceStack = [];
20434 const results = [];
20435 const braces = /[{}]/g;
20436 // lastIndex doesn't get set to 0 so we have to.
20437 braces.lastIndex = 0;
20438 let match;
20439 while (match = braces.exec(pattern)) {
20440 const pos = match.index;
20441 if (match[0] == '}') {
20442 braceStack.pop();
20443 if (braceStack.length == 0) {
20444 // End of the block.
20445 const block = pattern.substring(prevPos, pos);
20446 if (ICU_BLOCK_REGEXP.test(block)) {
20447 results.push(parseICUBlock(block));
20448 }
20449 else {
20450 results.push(block);
20451 }
20452 prevPos = pos + 1;
20453 }
20454 }
20455 else {
20456 if (braceStack.length == 0) {
20457 const substring = pattern.substring(prevPos, pos);
20458 results.push(substring);
20459 prevPos = pos + 1;
20460 }
20461 braceStack.push('{');
20462 }
20463 }
20464 const substring = pattern.substring(prevPos);
20465 results.push(substring);
20466 return results;
20467}
20468/**
20469 * Parses a node, its children and its siblings, and generates the mutate & update OpCodes.
20470 *
20471 */
20472function parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, caseName, unsafeCaseHtml, nestedIcus) {
20473 const create = [];
20474 const remove = [];
20475 const update = [];
20476 if (ngDevMode) {
20477 attachDebugGetter(create, icuCreateOpCodesToString);
20478 attachDebugGetter(remove, i18nRemoveOpCodesToString);
20479 attachDebugGetter(update, i18nUpdateOpCodesToString);
20480 }
20481 tIcu.cases.push(caseName);
20482 tIcu.create.push(create);
20483 tIcu.remove.push(remove);
20484 tIcu.update.push(update);
20485 const inertBodyHelper = getInertBodyHelper(getDocument());
20486 const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeCaseHtml);
20487 ngDevMode && assertDefined(inertBodyElement, 'Unable to generate inert body element');
20488 const inertRootNode = getTemplateContent(inertBodyElement) || inertBodyElement;
20489 if (inertRootNode) {
20490 return walkIcuTree(tView, tIcu, lView, updateOpCodes, create, remove, update, inertRootNode, parentIdx, nestedIcus, 0);
20491 }
20492 else {
20493 return 0;
20494 }
20495}
20496function walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, parentNode, parentIdx, nestedIcus, depth) {
20497 let bindingMask = 0;
20498 let currentNode = parentNode.firstChild;
20499 while (currentNode) {
20500 const newIndex = allocExpando(tView, lView, 1, null);
20501 switch (currentNode.nodeType) {
20502 case Node.ELEMENT_NODE:
20503 const element = currentNode;
20504 const tagName = element.tagName.toLowerCase();
20505 if (VALID_ELEMENTS.hasOwnProperty(tagName)) {
20506 addCreateNodeAndAppend(create, ELEMENT_MARKER, tagName, parentIdx, newIndex);
20507 tView.data[newIndex] = tagName;
20508 const elAttrs = element.attributes;
20509 for (let i = 0; i < elAttrs.length; i++) {
20510 const attr = elAttrs.item(i);
20511 const lowerAttrName = attr.name.toLowerCase();
20512 const hasBinding = !!attr.value.match(BINDING_REGEXP);
20513 // we assume the input string is safe, unless it's using a binding
20514 if (hasBinding) {
20515 if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
20516 if (URI_ATTRS[lowerAttrName]) {
20517 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, _sanitizeUrl);
20518 }
20519 else if (SRCSET_ATTRS[lowerAttrName]) {
20520 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, sanitizeSrcset);
20521 }
20522 else {
20523 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, null);
20524 }
20525 }
20526 else {
20527 ngDevMode &&
20528 console.warn(`WARNING: ignoring unsafe attribute value ` +
20529 `${lowerAttrName} on element ${tagName} ` +
20530 `(see https://g.co/ng/security#xss)`);
20531 }
20532 }
20533 else {
20534 addCreateAttribute(create, newIndex, attr);
20535 }
20536 }
20537 // Parse the children of this node (if any)
20538 bindingMask = walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, currentNode, newIndex, nestedIcus, depth + 1) |
20539 bindingMask;
20540 addRemoveNode(remove, newIndex, depth);
20541 }
20542 break;
20543 case Node.TEXT_NODE:
20544 const value = currentNode.textContent || '';
20545 const hasBinding = value.match(BINDING_REGEXP);
20546 addCreateNodeAndAppend(create, null, hasBinding ? '' : value, parentIdx, newIndex);
20547 addRemoveNode(remove, newIndex, depth);
20548 if (hasBinding) {
20549 bindingMask =
20550 generateBindingUpdateOpCodes(update, value, newIndex, null, 0, null) | bindingMask;
20551 }
20552 break;
20553 case Node.COMMENT_NODE:
20554 // Check if the comment node is a placeholder for a nested ICU
20555 const isNestedIcu = NESTED_ICU.exec(currentNode.textContent || '');
20556 if (isNestedIcu) {
20557 const nestedIcuIndex = parseInt(isNestedIcu[1], 10);
20558 const icuExpression = nestedIcus[nestedIcuIndex];
20559 // Create the comment node that will anchor the ICU expression
20560 addCreateNodeAndAppend(create, ICU_MARKER, ngDevMode ? `nested ICU ${nestedIcuIndex}` : '', parentIdx, newIndex);
20561 icuStart(tView, lView, sharedUpdateOpCodes, parentIdx, icuExpression, newIndex);
20562 addRemoveNestedIcu(remove, newIndex, depth);
20563 }
20564 break;
20565 }
20566 currentNode = currentNode.nextSibling;
20567 }
20568 return bindingMask;
20569}
20570function addRemoveNode(remove, index, depth) {
20571 if (depth === 0) {
20572 remove.push(index);
20573 }
20574}
20575function addRemoveNestedIcu(remove, index, depth) {
20576 if (depth === 0) {
20577 remove.push(~index); // remove ICU at `index`
20578 remove.push(index); // remove ICU comment at `index`
20579 }
20580}
20581function addUpdateIcuSwitch(update, icuExpression, index) {
20582 update.push(toMaskBit(icuExpression.mainBinding), 2, -1 - icuExpression.mainBinding, index << 2 /* SHIFT_REF */ | 2 /* IcuSwitch */);
20583}
20584function addUpdateIcuUpdate(update, bindingMask, index) {
20585 update.push(bindingMask, 1, index << 2 /* SHIFT_REF */ | 3 /* IcuUpdate */);
20586}
20587function addCreateNodeAndAppend(create, marker, text, appendToParentIdx, createAtIdx) {
20588 if (marker !== null) {
20589 create.push(marker);
20590 }
20591 create.push(text, createAtIdx, icuCreateOpCode(0 /* AppendChild */, appendToParentIdx, createAtIdx));
20592}
20593function addCreateAttribute(create, newIndex, attr) {
20594 create.push(newIndex << 1 /* SHIFT_REF */ | 1 /* Attr */, attr.name, attr.value);
20595}
20596
20597/**
20598 * @license
20599 * Copyright Google LLC All Rights Reserved.
20600 *
20601 * Use of this source code is governed by an MIT-style license that can be
20602 * found in the LICENSE file at https://angular.io/license
20603 */
20604// i18nPostprocess consts
20605const ROOT_TEMPLATE_ID = 0;
20606const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]/;
20607const PP_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]|(�\/?\*\d+:\d+�)/g;
20608const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g;
20609const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g;
20610const PP_ICUS_REGEXP = /�I18N_EXP_(ICU(_\d+)?)�/g;
20611const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/;
20612const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
20613/**
20614 * Handles message string post-processing for internationalization.
20615 *
20616 * Handles message string post-processing by transforming it from intermediate
20617 * format (that might contain some markers that we need to replace) to the final
20618 * form, consumable by i18nStart instruction. Post processing steps include:
20619 *
20620 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
20621 * 2. Replace all ICU vars (like "VAR_PLURAL")
20622 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
20623 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
20624 * in case multiple ICUs have the same placeholder name
20625 *
20626 * @param message Raw translation string for post processing
20627 * @param replacements Set of replacements that should be applied
20628 *
20629 * @returns Transformed string that can be consumed by i18nStart instruction
20630 *
20631 * @codeGenApi
20632 */
20633function i18nPostprocess(message, replacements = {}) {
20634 /**
20635 * Step 1: resolve all multi-value placeholders like [�#5�|�*1:1��#2:1�|�#4:1�]
20636 *
20637 * Note: due to the way we process nested templates (BFS), multi-value placeholders are typically
20638 * grouped by templates, for example: [�#5�|�#6�|�#1:1�|�#3:2�] where �#5� and �#6� belong to root
20639 * template, �#1:1� belong to nested template with index 1 and �#1:2� - nested template with index
20640 * 3. However in real templates the order might be different: i.e. �#1:1� and/or �#3:2� may go in
20641 * front of �#6�. The post processing step restores the right order by keeping track of the
20642 * template id stack and looks for placeholders that belong to the currently active template.
20643 */
20644 let result = message;
20645 if (PP_MULTI_VALUE_PLACEHOLDERS_REGEXP.test(message)) {
20646 const matches = {};
20647 const templateIdsStack = [ROOT_TEMPLATE_ID];
20648 result = result.replace(PP_PLACEHOLDERS_REGEXP, (m, phs, tmpl) => {
20649 const content = phs || tmpl;
20650 const placeholders = matches[content] || [];
20651 if (!placeholders.length) {
20652 content.split('|').forEach((placeholder) => {
20653 const match = placeholder.match(PP_TEMPLATE_ID_REGEXP);
20654 const templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID;
20655 const isCloseTemplateTag = PP_CLOSE_TEMPLATE_REGEXP.test(placeholder);
20656 placeholders.push([templateId, isCloseTemplateTag, placeholder]);
20657 });
20658 matches[content] = placeholders;
20659 }
20660 if (!placeholders.length) {
20661 throw new Error(`i18n postprocess: unmatched placeholder - ${content}`);
20662 }
20663 const currentTemplateId = templateIdsStack[templateIdsStack.length - 1];
20664 let idx = 0;
20665 // find placeholder index that matches current template id
20666 for (let i = 0; i < placeholders.length; i++) {
20667 if (placeholders[i][0] === currentTemplateId) {
20668 idx = i;
20669 break;
20670 }
20671 }
20672 // update template id stack based on the current tag extracted
20673 const [templateId, isCloseTemplateTag, placeholder] = placeholders[idx];
20674 if (isCloseTemplateTag) {
20675 templateIdsStack.pop();
20676 }
20677 else if (currentTemplateId !== templateId) {
20678 templateIdsStack.push(templateId);
20679 }
20680 // remove processed tag from the list
20681 placeholders.splice(idx, 1);
20682 return placeholder;
20683 });
20684 }
20685 // return current result if no replacements specified
20686 if (!Object.keys(replacements).length) {
20687 return result;
20688 }
20689 /**
20690 * Step 2: replace all ICU vars (like "VAR_PLURAL")
20691 */
20692 result = result.replace(PP_ICU_VARS_REGEXP, (match, start, key, _type, _idx, end) => {
20693 return replacements.hasOwnProperty(key) ? `${start}${replacements[key]}${end}` : match;
20694 });
20695 /**
20696 * Step 3: replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
20697 */
20698 result = result.replace(PP_ICU_PLACEHOLDERS_REGEXP, (match, key) => {
20699 return replacements.hasOwnProperty(key) ? replacements[key] : match;
20700 });
20701 /**
20702 * Step 4: replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) in case
20703 * multiple ICUs have the same placeholder name
20704 */
20705 result = result.replace(PP_ICUS_REGEXP, (match, key) => {
20706 if (replacements.hasOwnProperty(key)) {
20707 const list = replacements[key];
20708 if (!list.length) {
20709 throw new Error(`i18n postprocess: unmatched ICU - ${match} with key: ${key}`);
20710 }
20711 return list.shift();
20712 }
20713 return match;
20714 });
20715 return result;
20716}
20717
20718/**
20719 * @license
20720 * Copyright Google LLC All Rights Reserved.
20721 *
20722 * Use of this source code is governed by an MIT-style license that can be
20723 * found in the LICENSE file at https://angular.io/license
20724 */
20725/**
20726 * Marks a block of text as translatable.
20727 *
20728 * The instructions `i18nStart` and `i18nEnd` mark the translation block in the template.
20729 * The translation `message` is the value which is locale specific. The translation string may
20730 * contain placeholders which associate inner elements and sub-templates within the translation.
20731 *
20732 * The translation `message` placeholders are:
20733 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
20734 * interpolated into. The placeholder `index` points to the expression binding index. An optional
20735 * `block` that matches the sub-template in which it was declared.
20736 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning
20737 * and end of DOM element that were embedded in the original translation block. The placeholder
20738 * `index` points to the element index in the template instructions set. An optional `block` that
20739 * matches the sub-template in which it was declared.
20740 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
20741 * split up and translated separately in each angular template function. The `index` points to the
20742 * `template` instruction index. A `block` that matches the sub-template in which it was declared.
20743 *
20744 * @param index A unique index of the translation in the static block.
20745 * @param messageIndex An index of the translation message from the `def.consts` array.
20746 * @param subTemplateIndex Optional sub-template index in the `message`.
20747 *
20748 * @codeGenApi
20749 */
20750function ɵɵi18nStart(index, messageIndex, subTemplateIndex = -1) {
20751 const tView = getTView();
20752 const lView = getLView();
20753 const adjustedIndex = HEADER_OFFSET + index;
20754 ngDevMode && assertDefined(tView, `tView should be defined`);
20755 const message = getConstant(tView.consts, messageIndex);
20756 const parentTNode = getCurrentParentTNode();
20757 if (tView.firstCreatePass) {
20758 i18nStartFirstCreatePass(tView, parentTNode === null ? 0 : parentTNode.index, lView, adjustedIndex, message, subTemplateIndex);
20759 }
20760 const tI18n = tView.data[adjustedIndex];
20761 const sameViewParentTNode = parentTNode === lView[T_HOST] ? null : parentTNode;
20762 const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView);
20763 // If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.
20764 // When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.
20765 const insertInFrontOf = parentTNode && (parentTNode.type & 8 /* ElementContainer */) ?
20766 lView[parentTNode.index] :
20767 null;
20768 applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);
20769 setInI18nBlock(true);
20770}
20771/**
20772 * Translates a translation block marked by `i18nStart` and `i18nEnd`. It inserts the text/ICU nodes
20773 * into the render tree, moves the placeholder nodes and removes the deleted nodes.
20774 *
20775 * @codeGenApi
20776 */
20777function ɵɵi18nEnd() {
20778 setInI18nBlock(false);
20779}
20780/**
20781 *
20782 * Use this instruction to create a translation block that doesn't contain any placeholder.
20783 * It calls both {@link i18nStart} and {@link i18nEnd} in one instruction.
20784 *
20785 * The translation `message` is the value which is locale specific. The translation string may
20786 * contain placeholders which associate inner elements and sub-templates within the translation.
20787 *
20788 * The translation `message` placeholders are:
20789 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
20790 * interpolated into. The placeholder `index` points to the expression binding index. An optional
20791 * `block` that matches the sub-template in which it was declared.
20792 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning
20793 * and end of DOM element that were embedded in the original translation block. The placeholder
20794 * `index` points to the element index in the template instructions set. An optional `block` that
20795 * matches the sub-template in which it was declared.
20796 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
20797 * split up and translated separately in each angular template function. The `index` points to the
20798 * `template` instruction index. A `block` that matches the sub-template in which it was declared.
20799 *
20800 * @param index A unique index of the translation in the static block.
20801 * @param messageIndex An index of the translation message from the `def.consts` array.
20802 * @param subTemplateIndex Optional sub-template index in the `message`.
20803 *
20804 * @codeGenApi
20805 */
20806function ɵɵi18n(index, messageIndex, subTemplateIndex) {
20807 ɵɵi18nStart(index, messageIndex, subTemplateIndex);
20808 ɵɵi18nEnd();
20809}
20810/**
20811 * Marks a list of attributes as translatable.
20812 *
20813 * @param index A unique index in the static block
20814 * @param values
20815 *
20816 * @codeGenApi
20817 */
20818function ɵɵi18nAttributes(index, attrsIndex) {
20819 const tView = getTView();
20820 ngDevMode && assertDefined(tView, `tView should be defined`);
20821 const attrs = getConstant(tView.consts, attrsIndex);
20822 i18nAttributesFirstPass(tView, index + HEADER_OFFSET, attrs);
20823}
20824/**
20825 * Stores the values of the bindings during each update cycle in order to determine if we need to
20826 * update the translated nodes.
20827 *
20828 * @param value The binding's value
20829 * @returns This function returns itself so that it may be chained
20830 * (e.g. `i18nExp(ctx.name)(ctx.title)`)
20831 *
20832 * @codeGenApi
20833 */
20834function ɵɵi18nExp(value) {
20835 const lView = getLView();
20836 setMaskBit(bindingUpdated(lView, nextBindingIndex(), value));
20837 return ɵɵi18nExp;
20838}
20839/**
20840 * Updates a translation block or an i18n attribute when the bindings have changed.
20841 *
20842 * @param index Index of either {@link i18nStart} (translation block) or {@link i18nAttributes}
20843 * (i18n attribute) on which it should update the content.
20844 *
20845 * @codeGenApi
20846 */
20847function ɵɵi18nApply(index) {
20848 applyI18n(getTView(), getLView(), index + HEADER_OFFSET);
20849}
20850/**
20851 * Handles message string post-processing for internationalization.
20852 *
20853 * Handles message string post-processing by transforming it from intermediate
20854 * format (that might contain some markers that we need to replace) to the final
20855 * form, consumable by i18nStart instruction. Post processing steps include:
20856 *
20857 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
20858 * 2. Replace all ICU vars (like "VAR_PLURAL")
20859 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
20860 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
20861 * in case multiple ICUs have the same placeholder name
20862 *
20863 * @param message Raw translation string for post processing
20864 * @param replacements Set of replacements that should be applied
20865 *
20866 * @returns Transformed string that can be consumed by i18nStart instruction
20867 *
20868 * @codeGenApi
20869 */
20870function ɵɵi18nPostprocess(message, replacements = {}) {
20871 return i18nPostprocess(message, replacements);
20872}
20873
20874/**
20875 * @license
20876 * Copyright Google LLC All Rights Reserved.
20877 *
20878 * Use of this source code is governed by an MIT-style license that can be
20879 * found in the LICENSE file at https://angular.io/license
20880 */
20881
20882/**
20883 * @license
20884 * Copyright Google LLC All Rights Reserved.
20885 *
20886 * Use of this source code is governed by an MIT-style license that can be
20887 * found in the LICENSE file at https://angular.io/license
20888 */
20889/**
20890 * Resolves the providers which are defined in the DirectiveDef.
20891 *
20892 * When inserting the tokens and the factories in their respective arrays, we can assume that
20893 * this method is called first for the component (if any), and then for other directives on the same
20894 * node.
20895 * As a consequence,the providers are always processed in that order:
20896 * 1) The view providers of the component
20897 * 2) The providers of the component
20898 * 3) The providers of the other directives
20899 * This matches the structure of the injectables arrays of a view (for each node).
20900 * So the tokens and the factories can be pushed at the end of the arrays, except
20901 * in one case for multi providers.
20902 *
20903 * @param def the directive definition
20904 * @param providers: Array of `providers`.
20905 * @param viewProviders: Array of `viewProviders`.
20906 */
20907function providersResolver(def, providers, viewProviders) {
20908 const tView = getTView();
20909 if (tView.firstCreatePass) {
20910 const isComponent = isComponentDef(def);
20911 // The list of view providers is processed first, and the flags are updated
20912 resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true);
20913 // Then, the list of providers is processed, and the flags are updated
20914 resolveProvider(providers, tView.data, tView.blueprint, isComponent, false);
20915 }
20916}
20917/**
20918 * Resolves a provider and publishes it to the DI system.
20919 */
20920function resolveProvider(provider, tInjectables, lInjectablesBlueprint, isComponent, isViewProvider) {
20921 provider = resolveForwardRef(provider);
20922 if (Array.isArray(provider)) {
20923 // Recursively call `resolveProvider`
20924 // Recursion is OK in this case because this code will not be in hot-path once we implement
20925 // cloning of the initial state.
20926 for (let i = 0; i < provider.length; i++) {
20927 resolveProvider(provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
20928 }
20929 }
20930 else {
20931 const tView = getTView();
20932 const lView = getLView();
20933 let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
20934 let providerFactory = providerToFactory(provider);
20935 const tNode = getCurrentTNode();
20936 const beginIndex = tNode.providerIndexes & 1048575 /* ProvidersStartIndexMask */;
20937 const endIndex = tNode.directiveStart;
20938 const cptViewProvidersCount = tNode.providerIndexes >> 20 /* CptViewProvidersCountShift */;
20939 if (isTypeProvider(provider) || !provider.multi) {
20940 // Single provider case: the factory is created and pushed immediately
20941 const factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject);
20942 const existingFactoryIndex = indexOf(token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount, endIndex);
20943 if (existingFactoryIndex === -1) {
20944 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
20945 registerDestroyHooksIfSupported(tView, provider, tInjectables.length);
20946 tInjectables.push(token);
20947 tNode.directiveStart++;
20948 tNode.directiveEnd++;
20949 if (isViewProvider) {
20950 tNode.providerIndexes += 1048576 /* CptViewProvidersCountShifter */;
20951 }
20952 lInjectablesBlueprint.push(factory);
20953 lView.push(factory);
20954 }
20955 else {
20956 lInjectablesBlueprint[existingFactoryIndex] = factory;
20957 lView[existingFactoryIndex] = factory;
20958 }
20959 }
20960 else {
20961 // Multi provider case:
20962 // We create a multi factory which is going to aggregate all the values.
20963 // Since the output of such a factory depends on content or view injection,
20964 // we create two of them, which are linked together.
20965 //
20966 // The first one (for view providers) is always in the first block of the injectables array,
20967 // and the second one (for providers) is always in the second block.
20968 // This is important because view providers have higher priority. When a multi token
20969 // is being looked up, the view providers should be found first.
20970 // Note that it is not possible to have a multi factory in the third block (directive block).
20971 //
20972 // The algorithm to process multi providers is as follows:
20973 // 1) If the multi provider comes from the `viewProviders` of the component:
20974 // a) If the special view providers factory doesn't exist, it is created and pushed.
20975 // b) Else, the multi provider is added to the existing multi factory.
20976 // 2) If the multi provider comes from the `providers` of the component or of another
20977 // directive:
20978 // a) If the multi factory doesn't exist, it is created and provider pushed into it.
20979 // It is also linked to the multi factory for view providers, if it exists.
20980 // b) Else, the multi provider is added to the existing multi factory.
20981 const existingProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);
20982 const existingViewProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);
20983 const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 &&
20984 lInjectablesBlueprint[existingProvidersFactoryIndex];
20985 const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 &&
20986 lInjectablesBlueprint[existingViewProvidersFactoryIndex];
20987 if (isViewProvider && !doesViewProvidersFactoryExist ||
20988 !isViewProvider && !doesProvidersFactoryExist) {
20989 // Cases 1.a and 2.a
20990 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
20991 const factory = multiFactory(isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver, lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory);
20992 if (!isViewProvider && doesViewProvidersFactoryExist) {
20993 lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory;
20994 }
20995 registerDestroyHooksIfSupported(tView, provider, tInjectables.length, 0);
20996 tInjectables.push(token);
20997 tNode.directiveStart++;
20998 tNode.directiveEnd++;
20999 if (isViewProvider) {
21000 tNode.providerIndexes += 1048576 /* CptViewProvidersCountShifter */;
21001 }
21002 lInjectablesBlueprint.push(factory);
21003 lView.push(factory);
21004 }
21005 else {
21006 // Cases 1.b and 2.b
21007 const indexInFactory = multiFactoryAdd(lInjectablesBlueprint[isViewProvider ? existingViewProvidersFactoryIndex :
21008 existingProvidersFactoryIndex], providerFactory, !isViewProvider && isComponent);
21009 registerDestroyHooksIfSupported(tView, provider, existingProvidersFactoryIndex > -1 ? existingProvidersFactoryIndex :
21010 existingViewProvidersFactoryIndex, indexInFactory);
21011 }
21012 if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) {
21013 lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders++;
21014 }
21015 }
21016 }
21017}
21018/**
21019 * Registers the `ngOnDestroy` hook of a provider, if the provider supports destroy hooks.
21020 * @param tView `TView` in which to register the hook.
21021 * @param provider Provider whose hook should be registered.
21022 * @param contextIndex Index under which to find the context for the hook when it's being invoked.
21023 * @param indexInFactory Only required for `multi` providers. Index of the provider in the multi
21024 * provider factory.
21025 */
21026function registerDestroyHooksIfSupported(tView, provider, contextIndex, indexInFactory) {
21027 const providerIsTypeProvider = isTypeProvider(provider);
21028 if (providerIsTypeProvider || isClassProvider(provider)) {
21029 const prototype = (provider.useClass || provider).prototype;
21030 const ngOnDestroy = prototype.ngOnDestroy;
21031 if (ngOnDestroy) {
21032 const hooks = tView.destroyHooks || (tView.destroyHooks = []);
21033 if (!providerIsTypeProvider && provider.multi) {
21034 ngDevMode &&
21035 assertDefined(indexInFactory, 'indexInFactory when registering multi factory destroy hook');
21036 const existingCallbacksIndex = hooks.indexOf(contextIndex);
21037 if (existingCallbacksIndex === -1) {
21038 hooks.push(contextIndex, [indexInFactory, ngOnDestroy]);
21039 }
21040 else {
21041 hooks[existingCallbacksIndex + 1].push(indexInFactory, ngOnDestroy);
21042 }
21043 }
21044 else {
21045 hooks.push(contextIndex, ngOnDestroy);
21046 }
21047 }
21048 }
21049}
21050/**
21051 * Add a factory in a multi factory.
21052 * @returns Index at which the factory was inserted.
21053 */
21054function multiFactoryAdd(multiFactory, factory, isComponentProvider) {
21055 if (isComponentProvider) {
21056 multiFactory.componentProviders++;
21057 }
21058 return multiFactory.multi.push(factory) - 1;
21059}
21060/**
21061 * Returns the index of item in the array, but only in the begin to end range.
21062 */
21063function indexOf(item, arr, begin, end) {
21064 for (let i = begin; i < end; i++) {
21065 if (arr[i] === item)
21066 return i;
21067 }
21068 return -1;
21069}
21070/**
21071 * Use this with `multi` `providers`.
21072 */
21073function multiProvidersFactoryResolver(_, tData, lData, tNode) {
21074 return multiResolve(this.multi, []);
21075}
21076/**
21077 * Use this with `multi` `viewProviders`.
21078 *
21079 * This factory knows how to concatenate itself with the existing `multi` `providers`.
21080 */
21081function multiViewProvidersFactoryResolver(_, tData, lView, tNode) {
21082 const factories = this.multi;
21083 let result;
21084 if (this.providerFactory) {
21085 const componentCount = this.providerFactory.componentProviders;
21086 const multiProviders = getNodeInjectable(lView, lView[TVIEW], this.providerFactory.index, tNode);
21087 // Copy the section of the array which contains `multi` `providers` from the component
21088 result = multiProviders.slice(0, componentCount);
21089 // Insert the `viewProvider` instances.
21090 multiResolve(factories, result);
21091 // Copy the section of the array which contains `multi` `providers` from other directives
21092 for (let i = componentCount; i < multiProviders.length; i++) {
21093 result.push(multiProviders[i]);
21094 }
21095 }
21096 else {
21097 result = [];
21098 // Insert the `viewProvider` instances.
21099 multiResolve(factories, result);
21100 }
21101 return result;
21102}
21103/**
21104 * Maps an array of factories into an array of values.
21105 */
21106function multiResolve(factories, result) {
21107 for (let i = 0; i < factories.length; i++) {
21108 const factory = factories[i];
21109 result.push(factory());
21110 }
21111 return result;
21112}
21113/**
21114 * Creates a multi factory.
21115 */
21116function multiFactory(factoryFn, index, isViewProvider, isComponent, f) {
21117 const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject);
21118 factory.multi = [];
21119 factory.index = index;
21120 factory.componentProviders = 0;
21121 multiFactoryAdd(factory, f, isComponent && !isViewProvider);
21122 return factory;
21123}
21124
21125/**
21126 * This feature resolves the providers of a directive (or component),
21127 * and publish them into the DI system, making it visible to others for injection.
21128 *
21129 * For example:
21130 * ```ts
21131 * class ComponentWithProviders {
21132 * constructor(private greeter: GreeterDE) {}
21133 *
21134 * static ɵcmp = defineComponent({
21135 * type: ComponentWithProviders,
21136 * selectors: [['component-with-providers']],
21137 * factory: () => new ComponentWithProviders(directiveInject(GreeterDE as any)),
21138 * decls: 1,
21139 * vars: 1,
21140 * template: function(fs: RenderFlags, ctx: ComponentWithProviders) {
21141 * if (fs & RenderFlags.Create) {
21142 * ɵɵtext(0);
21143 * }
21144 * if (fs & RenderFlags.Update) {
21145 * ɵɵtextInterpolate(ctx.greeter.greet());
21146 * }
21147 * },
21148 * features: [ɵɵProvidersFeature([GreeterDE])]
21149 * });
21150 * }
21151 * ```
21152 *
21153 * @param definition
21154 *
21155 * @codeGenApi
21156 */
21157function ɵɵProvidersFeature(providers, viewProviders = []) {
21158 return (definition) => {
21159 definition.providersResolver =
21160 (def, processProvidersFn) => {
21161 return providersResolver(def, //
21162 processProvidersFn ? processProvidersFn(providers) : providers, //
21163 viewProviders);
21164 };
21165 };
21166}
21167
21168/**
21169 * @license
21170 * Copyright Google LLC All Rights Reserved.
21171 *
21172 * Use of this source code is governed by an MIT-style license that can be
21173 * found in the LICENSE file at https://angular.io/license
21174 */
21175/**
21176 * Represents a component created by a `ComponentFactory`.
21177 * Provides access to the component instance and related objects,
21178 * and provides the means of destroying the instance.
21179 *
21180 * @publicApi
21181 */
21182class ComponentRef$1 {
21183}
21184/**
21185 * Base class for a factory that can create a component dynamically.
21186 * Instantiate a factory for a given type of component with `resolveComponentFactory()`.
21187 * Use the resulting `ComponentFactory.create()` method to create a component of that type.
21188 *
21189 * @see [Dynamic Components](guide/dynamic-component-loader)
21190 *
21191 * @publicApi
21192 */
21193class ComponentFactory$1 {
21194}
21195
21196/**
21197 * @license
21198 * Copyright Google LLC All Rights Reserved.
21199 *
21200 * Use of this source code is governed by an MIT-style license that can be
21201 * found in the LICENSE file at https://angular.io/license
21202 */
21203function noComponentFactoryError(component) {
21204 const error = Error(`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
21205 error[ERROR_COMPONENT] = component;
21206 return error;
21207}
21208const ERROR_COMPONENT = 'ngComponent';
21209function getComponent(error) {
21210 return error[ERROR_COMPONENT];
21211}
21212class _NullComponentFactoryResolver {
21213 resolveComponentFactory(component) {
21214 throw noComponentFactoryError(component);
21215 }
21216}
21217/**
21218 * A simple registry that maps `Components` to generated `ComponentFactory` classes
21219 * that can be used to create instances of components.
21220 * Use to obtain the factory for a given component type,
21221 * then use the factory's `create()` method to create a component of that type.
21222 *
21223 * Note: since v13, dynamic component creation via
21224 * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)
21225 * does **not** require resolving component factory: component class can be used directly.
21226 *
21227 * @publicApi
21228 */
21229class ComponentFactoryResolver$1 {
21230}
21231ComponentFactoryResolver$1.NULL = ( /* @__PURE__ */new _NullComponentFactoryResolver());
21232class CodegenComponentFactoryResolver {
21233 constructor(factories, _parent, _ngModule) {
21234 this._parent = _parent;
21235 this._ngModule = _ngModule;
21236 this._factories = new Map();
21237 for (let i = 0; i < factories.length; i++) {
21238 const factory = factories[i];
21239 this._factories.set(factory.componentType, factory);
21240 }
21241 }
21242 resolveComponentFactory(component) {
21243 let factory = this._factories.get(component);
21244 if (!factory && this._parent) {
21245 factory = this._parent.resolveComponentFactory(component);
21246 }
21247 if (!factory) {
21248 throw noComponentFactoryError(component);
21249 }
21250 return new ComponentFactoryBoundToModule(factory, this._ngModule);
21251 }
21252}
21253class ComponentFactoryBoundToModule extends ComponentFactory$1 {
21254 constructor(factory, ngModule) {
21255 super();
21256 this.factory = factory;
21257 this.ngModule = ngModule;
21258 this.selector = factory.selector;
21259 this.componentType = factory.componentType;
21260 this.ngContentSelectors = factory.ngContentSelectors;
21261 this.inputs = factory.inputs;
21262 this.outputs = factory.outputs;
21263 }
21264 create(injector, projectableNodes, rootSelectorOrNode, ngModule) {
21265 return this.factory.create(injector, projectableNodes, rootSelectorOrNode, ngModule || this.ngModule);
21266 }
21267}
21268
21269/**
21270 * @license
21271 * Copyright Google LLC All Rights Reserved.
21272 *
21273 * Use of this source code is governed by an MIT-style license that can be
21274 * found in the LICENSE file at https://angular.io/license
21275 */
21276function noop(...args) {
21277 // Do nothing.
21278}
21279
21280/**
21281 * Creates an ElementRef from the most recent node.
21282 *
21283 * @returns The ElementRef instance to use
21284 */
21285function injectElementRef() {
21286 return createElementRef(getCurrentTNode(), getLView());
21287}
21288/**
21289 * Creates an ElementRef given a node.
21290 *
21291 * @param tNode The node for which you'd like an ElementRef
21292 * @param lView The view to which the node belongs
21293 * @returns The ElementRef instance to use
21294 */
21295function createElementRef(tNode, lView) {
21296 return new ElementRef(getNativeByTNode(tNode, lView));
21297}
21298const SWITCH_ELEMENT_REF_FACTORY__POST_R3__ = injectElementRef;
21299const SWITCH_ELEMENT_REF_FACTORY__PRE_R3__ = noop;
21300const SWITCH_ELEMENT_REF_FACTORY = SWITCH_ELEMENT_REF_FACTORY__POST_R3__;
21301/**
21302 * A wrapper around a native element inside of a View.
21303 *
21304 * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
21305 * element.
21306 *
21307 * @security Permitting direct access to the DOM can make your application more vulnerable to
21308 * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
21309 * [Security Guide](https://g.co/ng/security).
21310 *
21311 * @publicApi
21312 */
21313// Note: We don't expose things like `Injector`, `ViewContainer`, ... here,
21314// i.e. users have to ask for what they need. With that, we can build better analysis tools
21315// and could do better codegen in the future.
21316class ElementRef {
21317 constructor(nativeElement) {
21318 this.nativeElement = nativeElement;
21319 }
21320}
21321/**
21322 * @internal
21323 * @nocollapse
21324 */
21325ElementRef.__NG_ELEMENT_ID__ = SWITCH_ELEMENT_REF_FACTORY;
21326/**
21327 * Unwraps `ElementRef` and return the `nativeElement`.
21328 *
21329 * @param value value to unwrap
21330 * @returns `nativeElement` if `ElementRef` otherwise returns value as is.
21331 */
21332function unwrapElementRef(value) {
21333 return value instanceof ElementRef ? value.nativeElement : value;
21334}
21335
21336/**
21337 * @license
21338 * Copyright Google LLC All Rights Reserved.
21339 *
21340 * Use of this source code is governed by an MIT-style license that can be
21341 * found in the LICENSE file at https://angular.io/license
21342 */
21343const Renderer2Interceptor = new InjectionToken('Renderer2Interceptor');
21344/**
21345 * Creates and initializes a custom renderer that implements the `Renderer2` base class.
21346 *
21347 * @publicApi
21348 */
21349class RendererFactory2 {
21350}
21351/**
21352 * Extend this base class to implement custom rendering. By default, Angular
21353 * renders a template into DOM. You can use custom rendering to intercept
21354 * rendering calls, or to render to something other than DOM.
21355 *
21356 * Create your custom renderer using `RendererFactory2`.
21357 *
21358 * Use a custom renderer to bypass Angular's templating and
21359 * make custom UI changes that can't be expressed declaratively.
21360 * For example if you need to set a property or an attribute whose name is
21361 * not statically known, use the `setProperty()` or
21362 * `setAttribute()` method.
21363 *
21364 * @publicApi
21365 */
21366class Renderer2 {
21367}
21368/**
21369 * @internal
21370 * @nocollapse
21371 */
21372Renderer2.__NG_ELEMENT_ID__ = () => SWITCH_RENDERER2_FACTORY();
21373const SWITCH_RENDERER2_FACTORY__POST_R3__ = injectRenderer2;
21374const SWITCH_RENDERER2_FACTORY__PRE_R3__ = noop;
21375const SWITCH_RENDERER2_FACTORY = SWITCH_RENDERER2_FACTORY__POST_R3__;
21376/** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
21377function getOrCreateRenderer2(lView) {
21378 const renderer = lView[RENDERER];
21379 if (ngDevMode && !isProceduralRenderer(renderer)) {
21380 throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
21381 }
21382 return renderer;
21383}
21384/** Injects a Renderer2 for the current component. */
21385function injectRenderer2() {
21386 // We need the Renderer to be based on the component that it's being injected into, however since
21387 // DI happens before we've entered its view, `getLView` will return the parent view instead.
21388 const lView = getLView();
21389 const tNode = getCurrentTNode();
21390 const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
21391 return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView);
21392}
21393
21394/**
21395 * @license
21396 * Copyright Google LLC All Rights Reserved.
21397 *
21398 * Use of this source code is governed by an MIT-style license that can be
21399 * found in the LICENSE file at https://angular.io/license
21400 */
21401/**
21402 * Sanitizer is used by the views to sanitize potentially dangerous values.
21403 *
21404 * @publicApi
21405 */
21406class Sanitizer {
21407}
21408/** @nocollapse */
21409Sanitizer.ɵprov = ɵɵdefineInjectable({
21410 token: Sanitizer,
21411 providedIn: 'root',
21412 factory: () => null,
21413});
21414
21415/**
21416 * @license
21417 * Copyright Google LLC All Rights Reserved.
21418 *
21419 * Use of this source code is governed by an MIT-style license that can be
21420 * found in the LICENSE file at https://angular.io/license
21421 */
21422/**
21423 * @description Represents the version of Angular
21424 *
21425 * @publicApi
21426 */
21427class Version {
21428 constructor(full) {
21429 this.full = full;
21430 this.major = full.split('.')[0];
21431 this.minor = full.split('.')[1];
21432 this.patch = full.split('.').slice(2).join('.');
21433 }
21434}
21435/**
21436 * @publicApi
21437 */
21438const VERSION = new Version('13.0.2');
21439
21440/**
21441 * @license
21442 * Copyright Google LLC All Rights Reserved.
21443 *
21444 * Use of this source code is governed by an MIT-style license that can be
21445 * found in the LICENSE file at https://angular.io/license
21446 */
21447// This default value is when checking the hierarchy for a token.
21448//
21449// It means both:
21450// - the token is not provided by the current injector,
21451// - only the element injectors should be checked (ie do not check module injectors
21452//
21453// mod1
21454// /
21455// el1 mod2
21456// \ /
21457// el2
21458//
21459// When requesting el2.injector.get(token), we should check in the following order and return the
21460// first found value:
21461// - el2.injector.get(token, default)
21462// - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module
21463// - mod2.injector.get(token, default)
21464const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
21465
21466/**
21467 * @license
21468 * Copyright Google LLC All Rights Reserved.
21469 *
21470 * Use of this source code is governed by an MIT-style license that can be
21471 * found in the LICENSE file at https://angular.io/license
21472 */
21473function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
21474 while (tNode !== null) {
21475 ngDevMode &&
21476 assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */ | 16 /* Projection */ | 32 /* Icu */);
21477 const lNode = lView[tNode.index];
21478 if (lNode !== null) {
21479 result.push(unwrapRNode(lNode));
21480 }
21481 // A given lNode can represent either a native node or a LContainer (when it is a host of a
21482 // ViewContainerRef). When we find a LContainer we need to descend into it to collect root nodes
21483 // from the views in this container.
21484 if (isLContainer(lNode)) {
21485 for (let i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) {
21486 const lViewInAContainer = lNode[i];
21487 const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;
21488 if (lViewFirstChildTNode !== null) {
21489 collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
21490 }
21491 }
21492 }
21493 const tNodeType = tNode.type;
21494 if (tNodeType & 8 /* ElementContainer */) {
21495 collectNativeNodes(tView, lView, tNode.child, result);
21496 }
21497 else if (tNodeType & 32 /* Icu */) {
21498 const nextRNode = icuContainerIterate(tNode, lView);
21499 let rNode;
21500 while (rNode = nextRNode()) {
21501 result.push(rNode);
21502 }
21503 }
21504 else if (tNodeType & 16 /* Projection */) {
21505 const nodesInSlot = getProjectionNodes(lView, tNode);
21506 if (Array.isArray(nodesInSlot)) {
21507 result.push(...nodesInSlot);
21508 }
21509 else {
21510 const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
21511 ngDevMode && assertParentView(parentView);
21512 collectNativeNodes(parentView[TVIEW], parentView, nodesInSlot, result, true);
21513 }
21514 }
21515 tNode = isProjection ? tNode.projectionNext : tNode.next;
21516 }
21517 return result;
21518}
21519
21520/**
21521 * @license
21522 * Copyright Google LLC All Rights Reserved.
21523 *
21524 * Use of this source code is governed by an MIT-style license that can be
21525 * found in the LICENSE file at https://angular.io/license
21526 */
21527class ViewRef$1 {
21528 constructor(
21529 /**
21530 * This represents `LView` associated with the component when ViewRef is a ChangeDetectorRef.
21531 *
21532 * When ViewRef is created for a dynamic component, this also represents the `LView` for the
21533 * component.
21534 *
21535 * For a "regular" ViewRef created for an embedded view, this is the `LView` for the embedded
21536 * view.
21537 *
21538 * @internal
21539 */
21540 _lView,
21541 /**
21542 * This represents the `LView` associated with the point where `ChangeDetectorRef` was
21543 * requested.
21544 *
21545 * This may be different from `_lView` if the `_cdRefInjectingView` is an embedded view.
21546 */
21547 _cdRefInjectingView) {
21548 this._lView = _lView;
21549 this._cdRefInjectingView = _cdRefInjectingView;
21550 this._appRef = null;
21551 this._attachedToViewContainer = false;
21552 }
21553 get rootNodes() {
21554 const lView = this._lView;
21555 const tView = lView[TVIEW];
21556 return collectNativeNodes(tView, lView, tView.firstChild, []);
21557 }
21558 get context() {
21559 return this._lView[CONTEXT];
21560 }
21561 set context(value) {
21562 this._lView[CONTEXT] = value;
21563 }
21564 get destroyed() {
21565 return (this._lView[FLAGS] & 256 /* Destroyed */) === 256 /* Destroyed */;
21566 }
21567 destroy() {
21568 if (this._appRef) {
21569 this._appRef.detachView(this);
21570 }
21571 else if (this._attachedToViewContainer) {
21572 const parent = this._lView[PARENT];
21573 if (isLContainer(parent)) {
21574 const viewRefs = parent[VIEW_REFS];
21575 const index = viewRefs ? viewRefs.indexOf(this) : -1;
21576 if (index > -1) {
21577 ngDevMode &&
21578 assertEqual(index, parent.indexOf(this._lView) - CONTAINER_HEADER_OFFSET, 'An attached view should be in the same position within its container as its ViewRef in the VIEW_REFS array.');
21579 detachView(parent, index);
21580 removeFromArray(viewRefs, index);
21581 }
21582 }
21583 this._attachedToViewContainer = false;
21584 }
21585 destroyLView(this._lView[TVIEW], this._lView);
21586 }
21587 onDestroy(callback) {
21588 storeCleanupWithContext(this._lView[TVIEW], this._lView, null, callback);
21589 }
21590 /**
21591 * Marks a view and all of its ancestors dirty.
21592 *
21593 * This can be used to ensure an {@link ChangeDetectionStrategy#OnPush OnPush} component is
21594 * checked when it needs to be re-rendered but the two normal triggers haven't marked it
21595 * dirty (i.e. inputs haven't changed and events haven't fired in the view).
21596 *
21597 * <!-- TODO: Add a link to a chapter on OnPush components -->
21598 *
21599 * @usageNotes
21600 * ### Example
21601 *
21602 * ```typescript
21603 * @Component({
21604 * selector: 'app-root',
21605 * template: `Number of ticks: {{numberOfTicks}}`
21606 * changeDetection: ChangeDetectionStrategy.OnPush,
21607 * })
21608 * class AppComponent {
21609 * numberOfTicks = 0;
21610 *
21611 * constructor(private ref: ChangeDetectorRef) {
21612 * setInterval(() => {
21613 * this.numberOfTicks++;
21614 * // the following is required, otherwise the view will not be updated
21615 * this.ref.markForCheck();
21616 * }, 1000);
21617 * }
21618 * }
21619 * ```
21620 */
21621 markForCheck() {
21622 markViewDirty(this._cdRefInjectingView || this._lView);
21623 }
21624 /**
21625 * Detaches the view from the change detection tree.
21626 *
21627 * Detached views will not be checked during change detection runs until they are
21628 * re-attached, even if they are dirty. `detach` can be used in combination with
21629 * {@link ChangeDetectorRef#detectChanges detectChanges} to implement local change
21630 * detection checks.
21631 *
21632 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
21633 * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->
21634 *
21635 * @usageNotes
21636 * ### Example
21637 *
21638 * The following example defines a component with a large list of readonly data.
21639 * Imagine the data changes constantly, many times per second. For performance reasons,
21640 * we want to check and update the list every five seconds. We can do that by detaching
21641 * the component's change detector and doing a local check every five seconds.
21642 *
21643 * ```typescript
21644 * class DataProvider {
21645 * // in a real application the returned data will be different every time
21646 * get data() {
21647 * return [1,2,3,4,5];
21648 * }
21649 * }
21650 *
21651 * @Component({
21652 * selector: 'giant-list',
21653 * template: `
21654 * <li *ngFor="let d of dataProvider.data">Data {{d}}</li>
21655 * `,
21656 * })
21657 * class GiantList {
21658 * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {
21659 * ref.detach();
21660 * setInterval(() => {
21661 * this.ref.detectChanges();
21662 * }, 5000);
21663 * }
21664 * }
21665 *
21666 * @Component({
21667 * selector: 'app',
21668 * providers: [DataProvider],
21669 * template: `
21670 * <giant-list><giant-list>
21671 * `,
21672 * })
21673 * class App {
21674 * }
21675 * ```
21676 */
21677 detach() {
21678 this._lView[FLAGS] &= ~128 /* Attached */;
21679 }
21680 /**
21681 * Re-attaches a view to the change detection tree.
21682 *
21683 * This can be used to re-attach views that were previously detached from the tree
21684 * using {@link ChangeDetectorRef#detach detach}. Views are attached to the tree by default.
21685 *
21686 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
21687 *
21688 * @usageNotes
21689 * ### Example
21690 *
21691 * The following example creates a component displaying `live` data. The component will detach
21692 * its change detector from the main change detector tree when the component's live property
21693 * is set to false.
21694 *
21695 * ```typescript
21696 * class DataProvider {
21697 * data = 1;
21698 *
21699 * constructor() {
21700 * setInterval(() => {
21701 * this.data = this.data * 2;
21702 * }, 500);
21703 * }
21704 * }
21705 *
21706 * @Component({
21707 * selector: 'live-data',
21708 * inputs: ['live'],
21709 * template: 'Data: {{dataProvider.data}}'
21710 * })
21711 * class LiveData {
21712 * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {}
21713 *
21714 * set live(value) {
21715 * if (value) {
21716 * this.ref.reattach();
21717 * } else {
21718 * this.ref.detach();
21719 * }
21720 * }
21721 * }
21722 *
21723 * @Component({
21724 * selector: 'app-root',
21725 * providers: [DataProvider],
21726 * template: `
21727 * Live Update: <input type="checkbox" [(ngModel)]="live">
21728 * <live-data [live]="live"><live-data>
21729 * `,
21730 * })
21731 * class AppComponent {
21732 * live = true;
21733 * }
21734 * ```
21735 */
21736 reattach() {
21737 this._lView[FLAGS] |= 128 /* Attached */;
21738 }
21739 /**
21740 * Checks the view and its children.
21741 *
21742 * This can also be used in combination with {@link ChangeDetectorRef#detach detach} to implement
21743 * local change detection checks.
21744 *
21745 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
21746 * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->
21747 *
21748 * @usageNotes
21749 * ### Example
21750 *
21751 * The following example defines a component with a large list of readonly data.
21752 * Imagine, the data changes constantly, many times per second. For performance reasons,
21753 * we want to check and update the list every five seconds.
21754 *
21755 * We can do that by detaching the component's change detector and doing a local change detection
21756 * check every five seconds.
21757 *
21758 * See {@link ChangeDetectorRef#detach detach} for more information.
21759 */
21760 detectChanges() {
21761 detectChangesInternal(this._lView[TVIEW], this._lView, this.context);
21762 }
21763 /**
21764 * Checks the change detector and its children, and throws if any changes are detected.
21765 *
21766 * This is used in development mode to verify that running change detection doesn't
21767 * introduce other changes.
21768 */
21769 checkNoChanges() {
21770 checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
21771 }
21772 attachToViewContainerRef() {
21773 if (this._appRef) {
21774 throw new Error('This view is already attached directly to the ApplicationRef!');
21775 }
21776 this._attachedToViewContainer = true;
21777 }
21778 detachFromAppRef() {
21779 this._appRef = null;
21780 renderDetachView$1(this._lView[TVIEW], this._lView);
21781 }
21782 attachToAppRef(appRef) {
21783 if (this._attachedToViewContainer) {
21784 throw new Error('This view is already attached to a ViewContainer!');
21785 }
21786 this._appRef = appRef;
21787 }
21788}
21789/** @internal */
21790class RootViewRef extends ViewRef$1 {
21791 constructor(_view) {
21792 super(_view);
21793 this._view = _view;
21794 }
21795 detectChanges() {
21796 detectChangesInRootView(this._view);
21797 }
21798 checkNoChanges() {
21799 checkNoChangesInRootView(this._view);
21800 }
21801 get context() {
21802 return null;
21803 }
21804}
21805
21806/**
21807 * @license
21808 * Copyright Google LLC All Rights Reserved.
21809 *
21810 * Use of this source code is governed by an MIT-style license that can be
21811 * found in the LICENSE file at https://angular.io/license
21812 */
21813class ComponentFactoryResolver extends ComponentFactoryResolver$1 {
21814 /**
21815 * @param ngModule The NgModuleRef to which all resolved factories are bound.
21816 */
21817 constructor(ngModule) {
21818 super();
21819 this.ngModule = ngModule;
21820 }
21821 resolveComponentFactory(component) {
21822 ngDevMode && assertComponentType(component);
21823 const componentDef = getComponentDef(component);
21824 return new ComponentFactory(componentDef, this.ngModule);
21825 }
21826}
21827function toRefArray(map) {
21828 const array = [];
21829 for (let nonMinified in map) {
21830 if (map.hasOwnProperty(nonMinified)) {
21831 const minified = map[nonMinified];
21832 array.push({ propName: minified, templateName: nonMinified });
21833 }
21834 }
21835 return array;
21836}
21837function getNamespace(elementName) {
21838 const name = elementName.toLowerCase();
21839 return name === 'svg' ? SVG_NAMESPACE : (name === 'math' ? MATH_ML_NAMESPACE : null);
21840}
21841/**
21842 * A change detection scheduler token for {@link RootContext}. This token is the default value used
21843 * for the default `RootContext` found in the {@link ROOT_CONTEXT} token.
21844 */
21845const SCHEDULER = new InjectionToken('SCHEDULER_TOKEN', {
21846 providedIn: 'root',
21847 factory: () => defaultScheduler,
21848});
21849function createChainedInjector(rootViewInjector, moduleInjector) {
21850 return {
21851 get: (token, notFoundValue, flags) => {
21852 const value = rootViewInjector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags);
21853 if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
21854 notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
21855 // Return the value from the root element injector when
21856 // - it provides it
21857 // (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
21858 // - the module injector should not be checked
21859 // (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
21860 return value;
21861 }
21862 return moduleInjector.get(token, notFoundValue, flags);
21863 }
21864 };
21865}
21866/**
21867 * Render3 implementation of {@link viewEngine_ComponentFactory}.
21868 */
21869class ComponentFactory extends ComponentFactory$1 {
21870 /**
21871 * @param componentDef The component definition.
21872 * @param ngModule The NgModuleRef to which the factory is bound.
21873 */
21874 constructor(componentDef, ngModule) {
21875 super();
21876 this.componentDef = componentDef;
21877 this.ngModule = ngModule;
21878 this.componentType = componentDef.type;
21879 this.selector = stringifyCSSSelectorList(componentDef.selectors);
21880 this.ngContentSelectors =
21881 componentDef.ngContentSelectors ? componentDef.ngContentSelectors : [];
21882 this.isBoundToModule = !!ngModule;
21883 }
21884 get inputs() {
21885 return toRefArray(this.componentDef.inputs);
21886 }
21887 get outputs() {
21888 return toRefArray(this.componentDef.outputs);
21889 }
21890 create(injector, projectableNodes, rootSelectorOrNode, ngModule) {
21891 ngModule = ngModule || this.ngModule;
21892 const rootViewInjector = ngModule ? createChainedInjector(injector, ngModule.injector) : injector;
21893 const rendererFactory = rootViewInjector.get(RendererFactory2, domRendererFactory3);
21894 const sanitizer = rootViewInjector.get(Sanitizer, null);
21895 const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);
21896 // Determine a tag name used for creating host elements when this component is created
21897 // dynamically. Default to 'div' if this component did not specify any tag name in its selector.
21898 const elementName = this.componentDef.selectors[0][0] || 'div';
21899 const hostRNode = rootSelectorOrNode ?
21900 locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :
21901 createElementNode(rendererFactory.createRenderer(null, this.componentDef), elementName, getNamespace(elementName));
21902 const rootFlags = this.componentDef.onPush ? 64 /* Dirty */ | 512 /* IsRoot */ :
21903 16 /* CheckAlways */ | 512 /* IsRoot */;
21904 const rootContext = createRootContext();
21905 // Create the root view. Uses empty TView and ContentTemplate.
21906 const rootTView = createTView(0 /* Root */, null, null, 1, 0, null, null, null, null, null);
21907 const rootLView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector);
21908 // rootView is the parent when bootstrapping
21909 // TODO(misko): it looks like we are entering view here but we don't really need to as
21910 // `renderView` does that. However as the code is written it is needed because
21911 // `createRootComponentView` and `createRootComponent` both read global state. Fixing those
21912 // issues would allow us to drop this.
21913 enterView(rootLView);
21914 let component;
21915 let tElementNode;
21916 try {
21917 const componentView = createRootComponentView(hostRNode, this.componentDef, rootLView, rendererFactory, hostRenderer);
21918 if (hostRNode) {
21919 if (rootSelectorOrNode) {
21920 setUpAttributes(hostRenderer, hostRNode, ['ng-version', VERSION.full]);
21921 }
21922 else {
21923 // If host element is created as a part of this function call (i.e. `rootSelectorOrNode`
21924 // is not defined), also apply attributes and classes extracted from component selector.
21925 // Extract attributes and classes from the first selector only to match VE behavior.
21926 const { attrs, classes } = extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]);
21927 if (attrs) {
21928 setUpAttributes(hostRenderer, hostRNode, attrs);
21929 }
21930 if (classes && classes.length > 0) {
21931 writeDirectClass(hostRenderer, hostRNode, classes.join(' '));
21932 }
21933 }
21934 }
21935 tElementNode = getTNode(rootTView, HEADER_OFFSET);
21936 if (projectableNodes !== undefined) {
21937 const projection = tElementNode.projection = [];
21938 for (let i = 0; i < this.ngContentSelectors.length; i++) {
21939 const nodesforSlot = projectableNodes[i];
21940 // Projectable nodes can be passed as array of arrays or an array of iterables (ngUpgrade
21941 // case). Here we do normalize passed data structure to be an array of arrays to avoid
21942 // complex checks down the line.
21943 // We also normalize the length of the passed in projectable nodes (to match the number of
21944 // <ng-container> slots defined by a component).
21945 projection.push(nodesforSlot != null ? Array.from(nodesforSlot) : null);
21946 }
21947 }
21948 // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
21949 // executed here?
21950 // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
21951 component = createRootComponent(componentView, this.componentDef, rootLView, rootContext, [LifecycleHooksFeature]);
21952 renderView(rootTView, rootLView, null);
21953 }
21954 finally {
21955 leaveView();
21956 }
21957 return new ComponentRef(this.componentType, component, createElementRef(tElementNode, rootLView), rootLView, tElementNode);
21958 }
21959}
21960const componentFactoryResolver = new ComponentFactoryResolver();
21961/**
21962 * Creates a ComponentFactoryResolver and stores it on the injector. Or, if the
21963 * ComponentFactoryResolver
21964 * already exists, retrieves the existing ComponentFactoryResolver.
21965 *
21966 * @returns The ComponentFactoryResolver instance to use
21967 */
21968function injectComponentFactoryResolver() {
21969 return componentFactoryResolver;
21970}
21971/**
21972 * Represents an instance of a Component created via a {@link ComponentFactory}.
21973 *
21974 * `ComponentRef` provides access to the Component Instance as well other objects related to this
21975 * Component Instance and allows you to destroy the Component Instance via the {@link #destroy}
21976 * method.
21977 *
21978 */
21979class ComponentRef extends ComponentRef$1 {
21980 constructor(componentType, instance, location, _rootLView, _tNode) {
21981 super();
21982 this.location = location;
21983 this._rootLView = _rootLView;
21984 this._tNode = _tNode;
21985 this.instance = instance;
21986 this.hostView = this.changeDetectorRef = new RootViewRef(_rootLView);
21987 this.componentType = componentType;
21988 }
21989 get injector() {
21990 return new NodeInjector(this._tNode, this._rootLView);
21991 }
21992 destroy() {
21993 this.hostView.destroy();
21994 }
21995 onDestroy(callback) {
21996 this.hostView.onDestroy(callback);
21997 }
21998}
21999
22000/**
22001 * @license
22002 * Copyright Google LLC All Rights Reserved.
22003 *
22004 * Use of this source code is governed by an MIT-style license that can be
22005 * found in the LICENSE file at https://angular.io/license
22006 */
22007/**
22008 * Adds decorator, constructor, and property metadata to a given type via static metadata fields
22009 * on the type.
22010 *
22011 * These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
22012 *
22013 * Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments
22014 * being tree-shaken away during production builds.
22015 */
22016function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
22017 return noSideEffects(() => {
22018 const clazz = type;
22019 if (decorators !== null) {
22020 if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
22021 clazz.decorators.push(...decorators);
22022 }
22023 else {
22024 clazz.decorators = decorators;
22025 }
22026 }
22027 if (ctorParameters !== null) {
22028 // Rather than merging, clobber the existing parameters. If other projects exist which
22029 // use tsickle-style annotations and reflect over them in the same way, this could
22030 // cause issues, but that is vanishingly unlikely.
22031 clazz.ctorParameters = ctorParameters;
22032 }
22033 if (propDecorators !== null) {
22034 // The property decorator objects are merged as it is possible different fields have
22035 // different decorator types. Decorators on individual fields are not merged, as it's
22036 // also incredibly unlikely that a field will be decorated both with an Angular
22037 // decorator and a non-Angular decorator that's also been downleveled.
22038 if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
22039 clazz.propDecorators = { ...clazz.propDecorators, ...propDecorators };
22040 }
22041 else {
22042 clazz.propDecorators = propDecorators;
22043 }
22044 }
22045 });
22046}
22047
22048/**
22049 * @license
22050 * Copyright Google LLC All Rights Reserved.
22051 *
22052 * Use of this source code is governed by an MIT-style license that can be
22053 * found in the LICENSE file at https://angular.io/license
22054 */
22055/**
22056 * Represents an instance of an `NgModule` created by an `NgModuleFactory`.
22057 * Provides access to the `NgModule` instance and related objects.
22058 *
22059 * @publicApi
22060 */
22061class NgModuleRef$1 {
22062}
22063/**
22064 * @publicApi
22065 *
22066 * @deprecated
22067 * This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy
22068 * JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes)
22069 * for additional context. Angular provides APIs that accept NgModule classes directly (such as
22070 * [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and
22071 * [createNgModuleRef](api/core/createNgModuleRef)), consider switching to those APIs instead of
22072 * using factory-based ones.
22073 */
22074class NgModuleFactory$1 {
22075}
22076
22077/**
22078 * @license
22079 * Copyright Google LLC All Rights Reserved.
22080 *
22081 * Use of this source code is governed by an MIT-style license that can be
22082 * found in the LICENSE file at https://angular.io/license
22083 */
22084/**
22085 * Map of module-id to the corresponding NgModule.
22086 * - In pre Ivy we track NgModuleFactory,
22087 * - In post Ivy we track the NgModuleType
22088 */
22089const modules = new Map();
22090/**
22091 * Registers a loaded module. Should only be called from generated NgModuleFactory code.
22092 * @publicApi
22093 */
22094function registerModuleFactory(id, factory) {
22095 const existing = modules.get(id);
22096 assertSameOrNotExisting(id, existing && existing.moduleType, factory.moduleType);
22097 modules.set(id, factory);
22098}
22099function assertSameOrNotExisting(id, type, incoming) {
22100 if (type && type !== incoming) {
22101 throw new Error(`Duplicate module registered for ${id} - ${stringify(type)} vs ${stringify(type.name)}`);
22102 }
22103}
22104function registerNgModuleType(ngModuleType) {
22105 const visited = new Set();
22106 recurse(ngModuleType);
22107 function recurse(ngModuleType) {
22108 // The imports array of an NgModule must refer to other NgModules,
22109 // so an error is thrown if no module definition is available.
22110 const def = getNgModuleDef(ngModuleType, /* throwNotFound */ true);
22111 const id = def.id;
22112 if (id !== null) {
22113 const existing = modules.get(id);
22114 assertSameOrNotExisting(id, existing, ngModuleType);
22115 modules.set(id, ngModuleType);
22116 }
22117 const imports = maybeUnwrapFn(def.imports);
22118 for (const i of imports) {
22119 if (!visited.has(i)) {
22120 visited.add(i);
22121 recurse(i);
22122 }
22123 }
22124 }
22125}
22126function clearModulesForTest() {
22127 modules.clear();
22128}
22129function getRegisteredNgModuleType(id) {
22130 return (modules.get(id) || autoRegisterModuleById[id]);
22131}
22132
22133/**
22134 * @license
22135 * Copyright Google LLC All Rights Reserved.
22136 *
22137 * Use of this source code is governed by an MIT-style license that can be
22138 * found in the LICENSE file at https://angular.io/license
22139 */
22140function createNgModuleRef__PRE_R3__(ngModule, parentInjector) {
22141 throw new Error(`This API is Ivy-only and is not supported in ViewEngine`);
22142}
22143function createNgModuleRef__POST_R3__(ngModule, parentInjector) {
22144 return new NgModuleRef(ngModule, parentInjector ?? null);
22145}
22146/**
22147 * Returns a new NgModuleRef instance based on the NgModule class and parent injector provided.
22148 * @param ngModule NgModule class.
22149 * @param parentInjector Optional injector instance to use as a parent for the module injector. If
22150 * not provided, `NullInjector` will be used instead.
22151 * @publicApi
22152 */
22153const createNgModuleRef$1 = createNgModuleRef__POST_R3__;
22154class NgModuleRef extends NgModuleRef$1 {
22155 constructor(ngModuleType, _parent) {
22156 super();
22157 this._parent = _parent;
22158 // tslint:disable-next-line:require-internal-with-underscore
22159 this._bootstrapComponents = [];
22160 this.injector = this;
22161 this.destroyCbs = [];
22162 // When bootstrapping a module we have a dependency graph that looks like this:
22163 // ApplicationRef -> ComponentFactoryResolver -> NgModuleRef. The problem is that if the
22164 // module being resolved tries to inject the ComponentFactoryResolver, it'll create a
22165 // circular dependency which will result in a runtime error, because the injector doesn't
22166 // exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves
22167 // and providing it, rather than letting the injector resolve it.
22168 this.componentFactoryResolver = new ComponentFactoryResolver(this);
22169 const ngModuleDef = getNgModuleDef(ngModuleType);
22170 ngDevMode &&
22171 assertDefined(ngModuleDef, `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`);
22172 this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap);
22173 this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [
22174 { provide: NgModuleRef$1, useValue: this }, {
22175 provide: ComponentFactoryResolver$1,
22176 useValue: this.componentFactoryResolver
22177 }
22178 ], stringify(ngModuleType));
22179 // We need to resolve the injector types separately from the injector creation, because
22180 // the module might be trying to use this ref in its contructor for DI which will cause a
22181 // circular error that will eventually error out, because the injector isn't created yet.
22182 this._r3Injector._resolveInjectorDefTypes();
22183 this.instance = this.get(ngModuleType);
22184 }
22185 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, injectFlags = InjectFlags.Default) {
22186 if (token === Injector || token === NgModuleRef$1 || token === INJECTOR) {
22187 return this;
22188 }
22189 return this._r3Injector.get(token, notFoundValue, injectFlags);
22190 }
22191 destroy() {
22192 ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
22193 const injector = this._r3Injector;
22194 !injector.destroyed && injector.destroy();
22195 this.destroyCbs.forEach(fn => fn());
22196 this.destroyCbs = null;
22197 }
22198 onDestroy(callback) {
22199 ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
22200 this.destroyCbs.push(callback);
22201 }
22202}
22203class NgModuleFactory extends NgModuleFactory$1 {
22204 constructor(moduleType) {
22205 super();
22206 this.moduleType = moduleType;
22207 const ngModuleDef = getNgModuleDef(moduleType);
22208 if (ngModuleDef !== null) {
22209 // Register the NgModule with Angular's module registry. The location (and hence timing) of
22210 // this call is critical to ensure this works correctly (modules get registered when expected)
22211 // without bloating bundles (modules are registered when otherwise not referenced).
22212 //
22213 // In View Engine, registration occurs in the .ngfactory.js file as a side effect. This has
22214 // several practical consequences:
22215 //
22216 // - If an .ngfactory file is not imported from, the module won't be registered (and can be
22217 // tree shaken).
22218 // - If an .ngfactory file is imported from, the module will be registered even if an instance
22219 // is not actually created (via `create` below).
22220 // - Since an .ngfactory file in View Engine references the .ngfactory files of the NgModule's
22221 // imports,
22222 //
22223 // In Ivy, things are a bit different. .ngfactory files still exist for compatibility, but are
22224 // not a required API to use - there are other ways to obtain an NgModuleFactory for a given
22225 // NgModule. Thus, relying on a side effect in the .ngfactory file is not sufficient. Instead,
22226 // the side effect of registration is added here, in the constructor of NgModuleFactory,
22227 // ensuring no matter how a factory is created, the module is registered correctly.
22228 //
22229 // An alternative would be to include the registration side effect inline following the actual
22230 // NgModule definition. This also has the correct timing, but breaks tree-shaking - modules
22231 // will be registered and retained even if they're otherwise never referenced.
22232 registerNgModuleType(moduleType);
22233 }
22234 }
22235 create(parentInjector) {
22236 return new NgModuleRef(this.moduleType, parentInjector);
22237 }
22238}
22239
22240/**
22241 * @license
22242 * Copyright Google LLC All Rights Reserved.
22243 *
22244 * Use of this source code is governed by an MIT-style license that can be
22245 * found in the LICENSE file at https://angular.io/license
22246 */
22247/**
22248 * Bindings for pure functions are stored after regular bindings.
22249 *
22250 * |-------decls------|---------vars---------| |----- hostVars (dir1) ------|
22251 * ------------------------------------------------------------------------------------------
22252 * | nodes/refs/pipes | bindings | fn slots | injector | dir1 | host bindings | host slots |
22253 * ------------------------------------------------------------------------------------------
22254 * ^ ^
22255 * TView.bindingStartIndex TView.expandoStartIndex
22256 *
22257 * Pure function instructions are given an offset from the binding root. Adding the offset to the
22258 * binding root gives the first index where the bindings are stored. In component views, the binding
22259 * root is the bindingStartIndex. In host bindings, the binding root is the expandoStartIndex +
22260 * any directive instances + any hostVars in directives evaluated before it.
22261 *
22262 * See VIEW_DATA.md for more information about host binding resolution.
22263 */
22264/**
22265 * If the value hasn't been saved, calls the pure function to store and return the
22266 * value. If it has been saved, returns the saved value.
22267 *
22268 * @param slotOffset the offset from binding root to the reserved slot
22269 * @param pureFn Function that returns a value
22270 * @param thisArg Optional calling context of pureFn
22271 * @returns value
22272 *
22273 * @codeGenApi
22274 */
22275function ɵɵpureFunction0(slotOffset, pureFn, thisArg) {
22276 const bindingIndex = getBindingRoot() + slotOffset;
22277 const lView = getLView();
22278 return lView[bindingIndex] === NO_CHANGE ?
22279 updateBinding(lView, bindingIndex, thisArg ? pureFn.call(thisArg) : pureFn()) :
22280 getBinding(lView, bindingIndex);
22281}
22282/**
22283 * If the value of the provided exp has changed, calls the pure function to return
22284 * an updated value. Or if the value has not changed, returns cached value.
22285 *
22286 * @param slotOffset the offset from binding root to the reserved slot
22287 * @param pureFn Function that returns an updated value
22288 * @param exp Updated expression value
22289 * @param thisArg Optional calling context of pureFn
22290 * @returns Updated or cached value
22291 *
22292 * @codeGenApi
22293 */
22294function ɵɵpureFunction1(slotOffset, pureFn, exp, thisArg) {
22295 return pureFunction1Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp, thisArg);
22296}
22297/**
22298 * If the value of any provided exp has changed, calls the pure function to return
22299 * an updated value. Or if no values have changed, returns cached value.
22300 *
22301 * @param slotOffset the offset from binding root to the reserved slot
22302 * @param pureFn
22303 * @param exp1
22304 * @param exp2
22305 * @param thisArg Optional calling context of pureFn
22306 * @returns Updated or cached value
22307 *
22308 * @codeGenApi
22309 */
22310function ɵɵpureFunction2(slotOffset, pureFn, exp1, exp2, thisArg) {
22311 return pureFunction2Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, thisArg);
22312}
22313/**
22314 * If the value of any provided exp has changed, calls the pure function to return
22315 * an updated value. Or if no values have changed, returns cached value.
22316 *
22317 * @param slotOffset the offset from binding root to the reserved slot
22318 * @param pureFn
22319 * @param exp1
22320 * @param exp2
22321 * @param exp3
22322 * @param thisArg Optional calling context of pureFn
22323 * @returns Updated or cached value
22324 *
22325 * @codeGenApi
22326 */
22327function ɵɵpureFunction3(slotOffset, pureFn, exp1, exp2, exp3, thisArg) {
22328 return pureFunction3Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, thisArg);
22329}
22330/**
22331 * If the value of any provided exp has changed, calls the pure function to return
22332 * an updated value. Or if no values have changed, returns cached value.
22333 *
22334 * @param slotOffset the offset from binding root to the reserved slot
22335 * @param pureFn
22336 * @param exp1
22337 * @param exp2
22338 * @param exp3
22339 * @param exp4
22340 * @param thisArg Optional calling context of pureFn
22341 * @returns Updated or cached value
22342 *
22343 * @codeGenApi
22344 */
22345function ɵɵpureFunction4(slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) {
22346 return pureFunction4Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg);
22347}
22348/**
22349 * If the value of any provided exp has changed, calls the pure function to return
22350 * an updated value. Or if no values have changed, returns cached value.
22351 *
22352 * @param slotOffset the offset from binding root to the reserved slot
22353 * @param pureFn
22354 * @param exp1
22355 * @param exp2
22356 * @param exp3
22357 * @param exp4
22358 * @param exp5
22359 * @param thisArg Optional calling context of pureFn
22360 * @returns Updated or cached value
22361 *
22362 * @codeGenApi
22363 */
22364function ɵɵpureFunction5(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, thisArg) {
22365 const bindingIndex = getBindingRoot() + slotOffset;
22366 const lView = getLView();
22367 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22368 return bindingUpdated(lView, bindingIndex + 4, exp5) || different ?
22369 updateBinding(lView, bindingIndex + 5, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) :
22370 pureFn(exp1, exp2, exp3, exp4, exp5)) :
22371 getBinding(lView, bindingIndex + 5);
22372}
22373/**
22374 * If the value of any provided exp has changed, calls the pure function to return
22375 * an updated value. Or if no values have changed, returns cached value.
22376 *
22377 * @param slotOffset the offset from binding root to the reserved slot
22378 * @param pureFn
22379 * @param exp1
22380 * @param exp2
22381 * @param exp3
22382 * @param exp4
22383 * @param exp5
22384 * @param exp6
22385 * @param thisArg Optional calling context of pureFn
22386 * @returns Updated or cached value
22387 *
22388 * @codeGenApi
22389 */
22390function ɵɵpureFunction6(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, thisArg) {
22391 const bindingIndex = getBindingRoot() + slotOffset;
22392 const lView = getLView();
22393 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22394 return bindingUpdated2(lView, bindingIndex + 4, exp5, exp6) || different ?
22395 updateBinding(lView, bindingIndex + 6, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) :
22396 pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) :
22397 getBinding(lView, bindingIndex + 6);
22398}
22399/**
22400 * If the value of any provided exp has changed, calls the pure function to return
22401 * an updated value. Or if no values have changed, returns cached value.
22402 *
22403 * @param slotOffset the offset from binding root to the reserved slot
22404 * @param pureFn
22405 * @param exp1
22406 * @param exp2
22407 * @param exp3
22408 * @param exp4
22409 * @param exp5
22410 * @param exp6
22411 * @param exp7
22412 * @param thisArg Optional calling context of pureFn
22413 * @returns Updated or cached value
22414 *
22415 * @codeGenApi
22416 */
22417function ɵɵpureFunction7(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, thisArg) {
22418 const bindingIndex = getBindingRoot() + slotOffset;
22419 const lView = getLView();
22420 let different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22421 return bindingUpdated3(lView, bindingIndex + 4, exp5, exp6, exp7) || different ?
22422 updateBinding(lView, bindingIndex + 7, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) :
22423 pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) :
22424 getBinding(lView, bindingIndex + 7);
22425}
22426/**
22427 * If the value of any provided exp has changed, calls the pure function to return
22428 * an updated value. Or if no values have changed, returns cached value.
22429 *
22430 * @param slotOffset the offset from binding root to the reserved slot
22431 * @param pureFn
22432 * @param exp1
22433 * @param exp2
22434 * @param exp3
22435 * @param exp4
22436 * @param exp5
22437 * @param exp6
22438 * @param exp7
22439 * @param exp8
22440 * @param thisArg Optional calling context of pureFn
22441 * @returns Updated or cached value
22442 *
22443 * @codeGenApi
22444 */
22445function ɵɵpureFunction8(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, thisArg) {
22446 const bindingIndex = getBindingRoot() + slotOffset;
22447 const lView = getLView();
22448 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22449 return bindingUpdated4(lView, bindingIndex + 4, exp5, exp6, exp7, exp8) || different ?
22450 updateBinding(lView, bindingIndex + 8, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) :
22451 pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) :
22452 getBinding(lView, bindingIndex + 8);
22453}
22454/**
22455 * pureFunction instruction that can support any number of bindings.
22456 *
22457 * If the value of any provided exp has changed, calls the pure function to return
22458 * an updated value. Or if no values have changed, returns cached value.
22459 *
22460 * @param slotOffset the offset from binding root to the reserved slot
22461 * @param pureFn A pure function that takes binding values and builds an object or array
22462 * containing those values.
22463 * @param exps An array of binding values
22464 * @param thisArg Optional calling context of pureFn
22465 * @returns Updated or cached value
22466 *
22467 * @codeGenApi
22468 */
22469function ɵɵpureFunctionV(slotOffset, pureFn, exps, thisArg) {
22470 return pureFunctionVInternal(getLView(), getBindingRoot(), slotOffset, pureFn, exps, thisArg);
22471}
22472/**
22473 * Results of a pure function invocation are stored in LView in a dedicated slot that is initialized
22474 * to NO_CHANGE. In rare situations a pure pipe might throw an exception on the very first
22475 * invocation and not produce any valid results. In this case LView would keep holding the NO_CHANGE
22476 * value. The NO_CHANGE is not something that we can use in expressions / bindings thus we convert
22477 * it to `undefined`.
22478 */
22479function getPureFunctionReturnValue(lView, returnValueIndex) {
22480 ngDevMode && assertIndexInRange(lView, returnValueIndex);
22481 const lastReturnValue = lView[returnValueIndex];
22482 return lastReturnValue === NO_CHANGE ? undefined : lastReturnValue;
22483}
22484/**
22485 * If the value of the provided exp has changed, calls the pure function to return
22486 * an updated value. Or if the value has not changed, returns cached value.
22487 *
22488 * @param lView LView in which the function is being executed.
22489 * @param bindingRoot Binding root index.
22490 * @param slotOffset the offset from binding root to the reserved slot
22491 * @param pureFn Function that returns an updated value
22492 * @param exp Updated expression value
22493 * @param thisArg Optional calling context of pureFn
22494 * @returns Updated or cached value
22495 */
22496function pureFunction1Internal(lView, bindingRoot, slotOffset, pureFn, exp, thisArg) {
22497 const bindingIndex = bindingRoot + slotOffset;
22498 return bindingUpdated(lView, bindingIndex, exp) ?
22499 updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) :
22500 getPureFunctionReturnValue(lView, bindingIndex + 1);
22501}
22502/**
22503 * If the value of any provided exp has changed, calls the pure function to return
22504 * an updated value. Or if no values have changed, returns cached value.
22505 *
22506 * @param lView LView in which the function is being executed.
22507 * @param bindingRoot Binding root index.
22508 * @param slotOffset the offset from binding root to the reserved slot
22509 * @param pureFn
22510 * @param exp1
22511 * @param exp2
22512 * @param thisArg Optional calling context of pureFn
22513 * @returns Updated or cached value
22514 */
22515function pureFunction2Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, thisArg) {
22516 const bindingIndex = bindingRoot + slotOffset;
22517 return bindingUpdated2(lView, bindingIndex, exp1, exp2) ?
22518 updateBinding(lView, bindingIndex + 2, thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) :
22519 getPureFunctionReturnValue(lView, bindingIndex + 2);
22520}
22521/**
22522 * If the value of any provided exp has changed, calls the pure function to return
22523 * an updated value. Or if no values have changed, returns cached value.
22524 *
22525 * @param lView LView in which the function is being executed.
22526 * @param bindingRoot Binding root index.
22527 * @param slotOffset the offset from binding root to the reserved slot
22528 * @param pureFn
22529 * @param exp1
22530 * @param exp2
22531 * @param exp3
22532 * @param thisArg Optional calling context of pureFn
22533 * @returns Updated or cached value
22534 */
22535function pureFunction3Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, thisArg) {
22536 const bindingIndex = bindingRoot + slotOffset;
22537 return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ?
22538 updateBinding(lView, bindingIndex + 3, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) :
22539 getPureFunctionReturnValue(lView, bindingIndex + 3);
22540}
22541/**
22542 * If the value of any provided exp has changed, calls the pure function to return
22543 * an updated value. Or if no values have changed, returns cached value.
22544 *
22545 * @param lView LView in which the function is being executed.
22546 * @param bindingRoot Binding root index.
22547 * @param slotOffset the offset from binding root to the reserved slot
22548 * @param pureFn
22549 * @param exp1
22550 * @param exp2
22551 * @param exp3
22552 * @param exp4
22553 * @param thisArg Optional calling context of pureFn
22554 * @returns Updated or cached value
22555 *
22556 */
22557function pureFunction4Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) {
22558 const bindingIndex = bindingRoot + slotOffset;
22559 return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ?
22560 updateBinding(lView, bindingIndex + 4, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) :
22561 getPureFunctionReturnValue(lView, bindingIndex + 4);
22562}
22563/**
22564 * pureFunction instruction that can support any number of bindings.
22565 *
22566 * If the value of any provided exp has changed, calls the pure function to return
22567 * an updated value. Or if no values have changed, returns cached value.
22568 *
22569 * @param lView LView in which the function is being executed.
22570 * @param bindingRoot Binding root index.
22571 * @param slotOffset the offset from binding root to the reserved slot
22572 * @param pureFn A pure function that takes binding values and builds an object or array
22573 * containing those values.
22574 * @param exps An array of binding values
22575 * @param thisArg Optional calling context of pureFn
22576 * @returns Updated or cached value
22577 */
22578function pureFunctionVInternal(lView, bindingRoot, slotOffset, pureFn, exps, thisArg) {
22579 let bindingIndex = bindingRoot + slotOffset;
22580 let different = false;
22581 for (let i = 0; i < exps.length; i++) {
22582 bindingUpdated(lView, bindingIndex++, exps[i]) && (different = true);
22583 }
22584 return different ? updateBinding(lView, bindingIndex, pureFn.apply(thisArg, exps)) :
22585 getPureFunctionReturnValue(lView, bindingIndex);
22586}
22587
22588/**
22589 * @license
22590 * Copyright Google LLC All Rights Reserved.
22591 *
22592 * Use of this source code is governed by an MIT-style license that can be
22593 * found in the LICENSE file at https://angular.io/license
22594 */
22595/**
22596 * Create a pipe.
22597 *
22598 * @param index Pipe index where the pipe will be stored.
22599 * @param pipeName The name of the pipe
22600 * @returns T the instance of the pipe.
22601 *
22602 * @codeGenApi
22603 */
22604function ɵɵpipe(index, pipeName) {
22605 const tView = getTView();
22606 let pipeDef;
22607 const adjustedIndex = index + HEADER_OFFSET;
22608 if (tView.firstCreatePass) {
22609 pipeDef = getPipeDef(pipeName, tView.pipeRegistry);
22610 tView.data[adjustedIndex] = pipeDef;
22611 if (pipeDef.onDestroy) {
22612 (tView.destroyHooks || (tView.destroyHooks = [])).push(adjustedIndex, pipeDef.onDestroy);
22613 }
22614 }
22615 else {
22616 pipeDef = tView.data[adjustedIndex];
22617 }
22618 const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));
22619 const previousInjectImplementation = setInjectImplementation(ɵɵdirectiveInject);
22620 try {
22621 // DI for pipes is supposed to behave like directives when placed on a component
22622 // host node, which means that we have to disable access to `viewProviders`.
22623 const previousIncludeViewProviders = setIncludeViewProviders(false);
22624 const pipeInstance = pipeFactory();
22625 setIncludeViewProviders(previousIncludeViewProviders);
22626 store(tView, getLView(), adjustedIndex, pipeInstance);
22627 return pipeInstance;
22628 }
22629 finally {
22630 // we have to restore the injector implementation in finally, just in case the creation of the
22631 // pipe throws an error.
22632 setInjectImplementation(previousInjectImplementation);
22633 }
22634}
22635/**
22636 * Searches the pipe registry for a pipe with the given name. If one is found,
22637 * returns the pipe. Otherwise, an error is thrown because the pipe cannot be resolved.
22638 *
22639 * @param name Name of pipe to resolve
22640 * @param registry Full list of available pipes
22641 * @returns Matching PipeDef
22642 */
22643function getPipeDef(name, registry) {
22644 if (registry) {
22645 for (let i = registry.length - 1; i >= 0; i--) {
22646 const pipeDef = registry[i];
22647 if (name === pipeDef.name) {
22648 return pipeDef;
22649 }
22650 }
22651 }
22652 throw new RuntimeError("302" /* PIPE_NOT_FOUND */, `The pipe '${name}' could not be found!`);
22653}
22654/**
22655 * Invokes a pipe with 1 arguments.
22656 *
22657 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22658 * the pipe only when an input to the pipe changes.
22659 *
22660 * @param index Pipe index where the pipe was stored on creation.
22661 * @param slotOffset the offset in the reserved slot space
22662 * @param v1 1st argument to {@link PipeTransform#transform}.
22663 *
22664 * @codeGenApi
22665 */
22666function ɵɵpipeBind1(index, slotOffset, v1) {
22667 const adjustedIndex = index + HEADER_OFFSET;
22668 const lView = getLView();
22669 const pipeInstance = load(lView, adjustedIndex);
22670 return isPure(lView, adjustedIndex) ?
22671 pureFunction1Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, pipeInstance) :
22672 pipeInstance.transform(v1);
22673}
22674/**
22675 * Invokes a pipe with 2 arguments.
22676 *
22677 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22678 * the pipe only when an input to the pipe changes.
22679 *
22680 * @param index Pipe index where the pipe was stored on creation.
22681 * @param slotOffset the offset in the reserved slot space
22682 * @param v1 1st argument to {@link PipeTransform#transform}.
22683 * @param v2 2nd argument to {@link PipeTransform#transform}.
22684 *
22685 * @codeGenApi
22686 */
22687function ɵɵpipeBind2(index, slotOffset, v1, v2) {
22688 const adjustedIndex = index + HEADER_OFFSET;
22689 const lView = getLView();
22690 const pipeInstance = load(lView, adjustedIndex);
22691 return isPure(lView, adjustedIndex) ?
22692 pureFunction2Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, pipeInstance) :
22693 pipeInstance.transform(v1, v2);
22694}
22695/**
22696 * Invokes a pipe with 3 arguments.
22697 *
22698 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22699 * the pipe only when an input to the pipe changes.
22700 *
22701 * @param index Pipe index where the pipe was stored on creation.
22702 * @param slotOffset the offset in the reserved slot space
22703 * @param v1 1st argument to {@link PipeTransform#transform}.
22704 * @param v2 2nd argument to {@link PipeTransform#transform}.
22705 * @param v3 4rd argument to {@link PipeTransform#transform}.
22706 *
22707 * @codeGenApi
22708 */
22709function ɵɵpipeBind3(index, slotOffset, v1, v2, v3) {
22710 const adjustedIndex = index + HEADER_OFFSET;
22711 const lView = getLView();
22712 const pipeInstance = load(lView, adjustedIndex);
22713 return isPure(lView, adjustedIndex) ?
22714 pureFunction3Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, pipeInstance) :
22715 pipeInstance.transform(v1, v2, v3);
22716}
22717/**
22718 * Invokes a pipe with 4 arguments.
22719 *
22720 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22721 * the pipe only when an input to the pipe changes.
22722 *
22723 * @param index Pipe index where the pipe was stored on creation.
22724 * @param slotOffset the offset in the reserved slot space
22725 * @param v1 1st argument to {@link PipeTransform#transform}.
22726 * @param v2 2nd argument to {@link PipeTransform#transform}.
22727 * @param v3 3rd argument to {@link PipeTransform#transform}.
22728 * @param v4 4th argument to {@link PipeTransform#transform}.
22729 *
22730 * @codeGenApi
22731 */
22732function ɵɵpipeBind4(index, slotOffset, v1, v2, v3, v4) {
22733 const adjustedIndex = index + HEADER_OFFSET;
22734 const lView = getLView();
22735 const pipeInstance = load(lView, adjustedIndex);
22736 return isPure(lView, adjustedIndex) ? pureFunction4Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, v4, pipeInstance) :
22737 pipeInstance.transform(v1, v2, v3, v4);
22738}
22739/**
22740 * Invokes a pipe with variable number of arguments.
22741 *
22742 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22743 * the pipe only when an input to the pipe changes.
22744 *
22745 * @param index Pipe index where the pipe was stored on creation.
22746 * @param slotOffset the offset in the reserved slot space
22747 * @param values Array of arguments to pass to {@link PipeTransform#transform} method.
22748 *
22749 * @codeGenApi
22750 */
22751function ɵɵpipeBindV(index, slotOffset, values) {
22752 const adjustedIndex = index + HEADER_OFFSET;
22753 const lView = getLView();
22754 const pipeInstance = load(lView, adjustedIndex);
22755 return isPure(lView, adjustedIndex) ?
22756 pureFunctionVInternal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) :
22757 pipeInstance.transform.apply(pipeInstance, values);
22758}
22759function isPure(lView, index) {
22760 return lView[TVIEW].data[index].pure;
22761}
22762
22763/**
22764 * @license
22765 * Copyright Google LLC All Rights Reserved.
22766 *
22767 * Use of this source code is governed by an MIT-style license that can be
22768 * found in the LICENSE file at https://angular.io/license
22769 */
22770class EventEmitter_ extends Subject {
22771 constructor(isAsync = false) {
22772 super();
22773 this.__isAsync = isAsync;
22774 }
22775 emit(value) {
22776 super.next(value);
22777 }
22778 subscribe(observerOrNext, error, complete) {
22779 let nextFn = observerOrNext;
22780 let errorFn = error || (() => null);
22781 let completeFn = complete;
22782 if (observerOrNext && typeof observerOrNext === 'object') {
22783 const observer = observerOrNext;
22784 nextFn = observer.next?.bind(observer);
22785 errorFn = observer.error?.bind(observer);
22786 completeFn = observer.complete?.bind(observer);
22787 }
22788 if (this.__isAsync) {
22789 errorFn = _wrapInTimeout(errorFn);
22790 if (nextFn) {
22791 nextFn = _wrapInTimeout(nextFn);
22792 }
22793 if (completeFn) {
22794 completeFn = _wrapInTimeout(completeFn);
22795 }
22796 }
22797 const sink = super.subscribe({ next: nextFn, error: errorFn, complete: completeFn });
22798 if (observerOrNext instanceof Subscription) {
22799 observerOrNext.add(sink);
22800 }
22801 return sink;
22802 }
22803}
22804function _wrapInTimeout(fn) {
22805 return (value) => {
22806 setTimeout(fn, undefined, value);
22807 };
22808}
22809/**
22810 * @publicApi
22811 */
22812const EventEmitter = EventEmitter_;
22813
22814/**
22815 * @license
22816 * Copyright Google LLC All Rights Reserved.
22817 *
22818 * Use of this source code is governed by an MIT-style license that can be
22819 * found in the LICENSE file at https://angular.io/license
22820 */
22821function symbolIterator() {
22822 return this._results[getSymbolIterator()]();
22823}
22824/**
22825 * An unmodifiable list of items that Angular keeps up to date when the state
22826 * of the application changes.
22827 *
22828 * The type of object that {@link ViewChildren}, {@link ContentChildren}, and {@link QueryList}
22829 * provide.
22830 *
22831 * Implements an iterable interface, therefore it can be used in both ES6
22832 * javascript `for (var i of items)` loops as well as in Angular templates with
22833 * `*ngFor="let i of myList"`.
22834 *
22835 * Changes can be observed by subscribing to the changes `Observable`.
22836 *
22837 * NOTE: In the future this class will implement an `Observable` interface.
22838 *
22839 * @usageNotes
22840 * ### Example
22841 * ```typescript
22842 * @Component({...})
22843 * class Container {
22844 * @ViewChildren(Item) items:QueryList<Item>;
22845 * }
22846 * ```
22847 *
22848 * @publicApi
22849 */
22850class QueryList {
22851 /**
22852 * @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change
22853 * has occurred. Or if it should fire when query is recomputed. (recomputing could resolve in
22854 * the same result)
22855 */
22856 constructor(_emitDistinctChangesOnly = false) {
22857 this._emitDistinctChangesOnly = _emitDistinctChangesOnly;
22858 this.dirty = true;
22859 this._results = [];
22860 this._changesDetected = false;
22861 this._changes = null;
22862 this.length = 0;
22863 this.first = undefined;
22864 this.last = undefined;
22865 // This function should be declared on the prototype, but doing so there will cause the class
22866 // declaration to have side-effects and become not tree-shakable. For this reason we do it in
22867 // the constructor.
22868 // [getSymbolIterator()](): Iterator<T> { ... }
22869 const symbol = getSymbolIterator();
22870 const proto = QueryList.prototype;
22871 if (!proto[symbol])
22872 proto[symbol] = symbolIterator;
22873 }
22874 /**
22875 * Returns `Observable` of `QueryList` notifying the subscriber of changes.
22876 */
22877 get changes() {
22878 return this._changes || (this._changes = new EventEmitter());
22879 }
22880 /**
22881 * Returns the QueryList entry at `index`.
22882 */
22883 get(index) {
22884 return this._results[index];
22885 }
22886 /**
22887 * See
22888 * [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
22889 */
22890 map(fn) {
22891 return this._results.map(fn);
22892 }
22893 /**
22894 * See
22895 * [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
22896 */
22897 filter(fn) {
22898 return this._results.filter(fn);
22899 }
22900 /**
22901 * See
22902 * [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
22903 */
22904 find(fn) {
22905 return this._results.find(fn);
22906 }
22907 /**
22908 * See
22909 * [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
22910 */
22911 reduce(fn, init) {
22912 return this._results.reduce(fn, init);
22913 }
22914 /**
22915 * See
22916 * [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
22917 */
22918 forEach(fn) {
22919 this._results.forEach(fn);
22920 }
22921 /**
22922 * See
22923 * [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
22924 */
22925 some(fn) {
22926 return this._results.some(fn);
22927 }
22928 /**
22929 * Returns a copy of the internal results list as an Array.
22930 */
22931 toArray() {
22932 return this._results.slice();
22933 }
22934 toString() {
22935 return this._results.toString();
22936 }
22937 /**
22938 * Updates the stored data of the query list, and resets the `dirty` flag to `false`, so that
22939 * on change detection, it will not notify of changes to the queries, unless a new change
22940 * occurs.
22941 *
22942 * @param resultsTree The query results to store
22943 * @param identityAccessor Optional function for extracting stable object identity from a value
22944 * in the array. This function is executed for each element of the query result list while
22945 * comparing current query list with the new one (provided as a first argument of the `reset`
22946 * function) to detect if the lists are different. If the function is not provided, elements
22947 * are compared as is (without any pre-processing).
22948 */
22949 reset(resultsTree, identityAccessor) {
22950 // Cast to `QueryListInternal` so that we can mutate fields which are readonly for the usage of
22951 // QueryList (but not for QueryList itself.)
22952 const self = this;
22953 self.dirty = false;
22954 const newResultFlat = flatten(resultsTree);
22955 if (this._changesDetected = !arrayEquals(self._results, newResultFlat, identityAccessor)) {
22956 self._results = newResultFlat;
22957 self.length = newResultFlat.length;
22958 self.last = newResultFlat[this.length - 1];
22959 self.first = newResultFlat[0];
22960 }
22961 }
22962 /**
22963 * Triggers a change event by emitting on the `changes` {@link EventEmitter}.
22964 */
22965 notifyOnChanges() {
22966 if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly))
22967 this._changes.emit(this);
22968 }
22969 /** internal */
22970 setDirty() {
22971 this.dirty = true;
22972 }
22973 /** internal */
22974 destroy() {
22975 this.changes.complete();
22976 this.changes.unsubscribe();
22977 }
22978}
22979Symbol.iterator;
22980
22981/**
22982 * @license
22983 * Copyright Google LLC All Rights Reserved.
22984 *
22985 * Use of this source code is governed by an MIT-style license that can be
22986 * found in the LICENSE file at https://angular.io/license
22987 */
22988const SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef;
22989const SWITCH_TEMPLATE_REF_FACTORY__PRE_R3__ = noop;
22990const SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__;
22991/**
22992 * Represents an embedded template that can be used to instantiate embedded views.
22993 * To instantiate embedded views based on a template, use the `ViewContainerRef`
22994 * method `createEmbeddedView()`.
22995 *
22996 * Access a `TemplateRef` instance by placing a directive on an `<ng-template>`
22997 * element (or directive prefixed with `*`). The `TemplateRef` for the embedded view
22998 * is injected into the constructor of the directive,
22999 * using the `TemplateRef` token.
23000 *
23001 * You can also use a `Query` to find a `TemplateRef` associated with
23002 * a component or a directive.
23003 *
23004 * @see `ViewContainerRef`
23005 * @see [Navigate the Component Tree with DI](guide/dependency-injection-navtree)
23006 *
23007 * @publicApi
23008 */
23009class TemplateRef {
23010}
23011/**
23012 * @internal
23013 * @nocollapse
23014 */
23015TemplateRef.__NG_ELEMENT_ID__ = SWITCH_TEMPLATE_REF_FACTORY;
23016const ViewEngineTemplateRef = TemplateRef;
23017const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
23018 constructor(_declarationLView, _declarationTContainer, elementRef) {
23019 super();
23020 this._declarationLView = _declarationLView;
23021 this._declarationTContainer = _declarationTContainer;
23022 this.elementRef = elementRef;
23023 }
23024 createEmbeddedView(context) {
23025 const embeddedTView = this._declarationTContainer.tViews;
23026 const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* CheckAlways */, null, embeddedTView.declTNode, null, null, null, null);
23027 const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
23028 ngDevMode && assertLContainer(declarationLContainer);
23029 embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
23030 const declarationViewLQueries = this._declarationLView[QUERIES];
23031 if (declarationViewLQueries !== null) {
23032 embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
23033 }
23034 renderView(embeddedTView, embeddedLView, context);
23035 return new ViewRef$1(embeddedLView);
23036 }
23037};
23038/**
23039 * Creates a TemplateRef given a node.
23040 *
23041 * @returns The TemplateRef instance to use
23042 */
23043function injectTemplateRef() {
23044 return createTemplateRef(getCurrentTNode(), getLView());
23045}
23046/**
23047 * Creates a TemplateRef and stores it on the injector.
23048 *
23049 * @param hostTNode The node on which a TemplateRef is requested
23050 * @param hostLView The `LView` to which the node belongs
23051 * @returns The TemplateRef instance or null if we can't create a TemplateRef on a given node type
23052 */
23053function createTemplateRef(hostTNode, hostLView) {
23054 if (hostTNode.type & 4 /* Container */) {
23055 ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
23056 return new R3TemplateRef(hostLView, hostTNode, createElementRef(hostTNode, hostLView));
23057 }
23058 return null;
23059}
23060
23061const SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__ = injectViewContainerRef;
23062const SWITCH_VIEW_CONTAINER_REF_FACTORY__PRE_R3__ = noop;
23063const SWITCH_VIEW_CONTAINER_REF_FACTORY = SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__;
23064/**
23065 * Represents a container where one or more views can be attached to a component.
23066 *
23067 * Can contain *host views* (created by instantiating a
23068 * component with the `createComponent()` method), and *embedded views*
23069 * (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method).
23070 *
23071 * A view container instance can contain other view containers,
23072 * creating a [view hierarchy](guide/glossary#view-tree).
23073 *
23074 * @see `ComponentRef`
23075 * @see `EmbeddedViewRef`
23076 *
23077 * @publicApi
23078 */
23079class ViewContainerRef {
23080}
23081/**
23082 * @internal
23083 * @nocollapse
23084 */
23085ViewContainerRef.__NG_ELEMENT_ID__ = SWITCH_VIEW_CONTAINER_REF_FACTORY;
23086/**
23087 * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef
23088 * already exists, retrieves the existing ViewContainerRef.
23089 *
23090 * @returns The ViewContainerRef instance to use
23091 */
23092function injectViewContainerRef() {
23093 const previousTNode = getCurrentTNode();
23094 return createContainerRef(previousTNode, getLView());
23095}
23096const VE_ViewContainerRef = ViewContainerRef;
23097const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
23098 constructor(_lContainer, _hostTNode, _hostLView) {
23099 super();
23100 this._lContainer = _lContainer;
23101 this._hostTNode = _hostTNode;
23102 this._hostLView = _hostLView;
23103 }
23104 get element() {
23105 return createElementRef(this._hostTNode, this._hostLView);
23106 }
23107 get injector() {
23108 return new NodeInjector(this._hostTNode, this._hostLView);
23109 }
23110 /** @deprecated No replacement */
23111 get parentInjector() {
23112 const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostLView);
23113 if (hasParentInjector(parentLocation)) {
23114 const parentView = getParentInjectorView(parentLocation, this._hostLView);
23115 const injectorIndex = getParentInjectorIndex(parentLocation);
23116 ngDevMode && assertNodeInjector(parentView, injectorIndex);
23117 const parentTNode = parentView[TVIEW].data[injectorIndex + 8 /* TNODE */];
23118 return new NodeInjector(parentTNode, parentView);
23119 }
23120 else {
23121 return new NodeInjector(null, this._hostLView);
23122 }
23123 }
23124 clear() {
23125 while (this.length > 0) {
23126 this.remove(this.length - 1);
23127 }
23128 }
23129 get(index) {
23130 const viewRefs = getViewRefs(this._lContainer);
23131 return viewRefs !== null && viewRefs[index] || null;
23132 }
23133 get length() {
23134 return this._lContainer.length - CONTAINER_HEADER_OFFSET;
23135 }
23136 createEmbeddedView(templateRef, context, index) {
23137 const viewRef = templateRef.createEmbeddedView(context || {});
23138 this.insert(viewRef, index);
23139 return viewRef;
23140 }
23141 createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, ngModuleRef) {
23142 const isComponentFactory = componentFactoryOrType && !isType(componentFactoryOrType);
23143 let index;
23144 // This function supports 2 signatures and we need to handle options correctly for both:
23145 // 1. When first argument is a Component type. This signature also requires extra
23146 // options to be provided as as object (more ergonomic option).
23147 // 2. First argument is a Component factory. In this case extra options are represented as
23148 // positional arguments. This signature is less ergonomic and will be deprecated.
23149 if (isComponentFactory) {
23150 if (ngDevMode) {
23151 assertEqual(typeof indexOrOptions !== 'object', true, 'It looks like Component factory was provided as the first argument ' +
23152 'and an options object as the second argument. This combination of arguments ' +
23153 'is incompatible. You can either change the first argument to provide Component ' +
23154 'type or change the second argument to be a number (representing an index at ' +
23155 'which to insert the new component\'s host view into this container)');
23156 }
23157 index = indexOrOptions;
23158 }
23159 else {
23160 if (ngDevMode) {
23161 assertDefined(getComponentDef(componentFactoryOrType), `Provided Component class doesn't contain Component definition. ` +
23162 `Please check whether provided class has @Component decorator.`);
23163 assertEqual(typeof indexOrOptions !== 'number', true, 'It looks like Component type was provided as the first argument ' +
23164 'and a number (representing an index at which to insert the new component\'s ' +
23165 'host view into this container as the second argument. This combination of arguments ' +
23166 'is incompatible. Please use an object as the second argument instead.');
23167 }
23168 const options = (indexOrOptions || {});
23169 index = options.index;
23170 injector = options.injector;
23171 projectableNodes = options.projectableNodes;
23172 ngModuleRef = options.ngModuleRef;
23173 }
23174 const componentFactory = isComponentFactory ?
23175 componentFactoryOrType :
23176 new ComponentFactory(getComponentDef(componentFactoryOrType));
23177 const contextInjector = injector || this.parentInjector;
23178 if (!ngModuleRef && componentFactory.ngModule == null && contextInjector) {
23179 // DO NOT REFACTOR. The code here used to have a `value || undefined` expression
23180 // which seems to cause internal google apps to fail. This is documented in the
23181 // following internal bug issue: go/b/142967802
23182 const result = contextInjector.get(NgModuleRef$1, null);
23183 if (result) {
23184 ngModuleRef = result;
23185 }
23186 }
23187 const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
23188 this.insert(componentRef.hostView, index);
23189 return componentRef;
23190 }
23191 insert(viewRef, index) {
23192 const lView = viewRef._lView;
23193 const tView = lView[TVIEW];
23194 if (ngDevMode && viewRef.destroyed) {
23195 throw new Error('Cannot insert a destroyed View in a ViewContainer!');
23196 }
23197 if (viewAttachedToContainer(lView)) {
23198 // If view is already attached, detach it first so we clean up references appropriately.
23199 const prevIdx = this.indexOf(viewRef);
23200 // A view might be attached either to this or a different container. The `prevIdx` for
23201 // those cases will be:
23202 // equal to -1 for views attached to this ViewContainerRef
23203 // >= 0 for views attached to a different ViewContainerRef
23204 if (prevIdx !== -1) {
23205 this.detach(prevIdx);
23206 }
23207 else {
23208 const prevLContainer = lView[PARENT];
23209 ngDevMode &&
23210 assertEqual(isLContainer(prevLContainer), true, 'An attached view should have its PARENT point to a container.');
23211 // We need to re-create a R3ViewContainerRef instance since those are not stored on
23212 // LView (nor anywhere else).
23213 const prevVCRef = new R3ViewContainerRef(prevLContainer, prevLContainer[T_HOST], prevLContainer[PARENT]);
23214 prevVCRef.detach(prevVCRef.indexOf(viewRef));
23215 }
23216 }
23217 // Logical operation of adding `LView` to `LContainer`
23218 const adjustedIdx = this._adjustIndex(index);
23219 const lContainer = this._lContainer;
23220 insertView(tView, lView, lContainer, adjustedIdx);
23221 // Physical operation of adding the DOM nodes.
23222 const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);
23223 const renderer = lView[RENDERER];
23224 const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);
23225 if (parentRNode !== null) {
23226 addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
23227 }
23228 viewRef.attachToViewContainerRef();
23229 addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);
23230 return viewRef;
23231 }
23232 move(viewRef, newIndex) {
23233 if (ngDevMode && viewRef.destroyed) {
23234 throw new Error('Cannot move a destroyed View in a ViewContainer!');
23235 }
23236 return this.insert(viewRef, newIndex);
23237 }
23238 indexOf(viewRef) {
23239 const viewRefsArr = getViewRefs(this._lContainer);
23240 return viewRefsArr !== null ? viewRefsArr.indexOf(viewRef) : -1;
23241 }
23242 remove(index) {
23243 const adjustedIdx = this._adjustIndex(index, -1);
23244 const detachedView = detachView(this._lContainer, adjustedIdx);
23245 if (detachedView) {
23246 // Before destroying the view, remove it from the container's array of `ViewRef`s.
23247 // This ensures the view container length is updated before calling
23248 // `destroyLView`, which could recursively call view container methods that
23249 // rely on an accurate container length.
23250 // (e.g. a method on this view container being called by a child directive's OnDestroy
23251 // lifecycle hook)
23252 removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx);
23253 destroyLView(detachedView[TVIEW], detachedView);
23254 }
23255 }
23256 detach(index) {
23257 const adjustedIdx = this._adjustIndex(index, -1);
23258 const view = detachView(this._lContainer, adjustedIdx);
23259 const wasDetached = view && removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx) != null;
23260 return wasDetached ? new ViewRef$1(view) : null;
23261 }
23262 _adjustIndex(index, shift = 0) {
23263 if (index == null) {
23264 return this.length + shift;
23265 }
23266 if (ngDevMode) {
23267 assertGreaterThan(index, -1, `ViewRef index must be positive, got ${index}`);
23268 // +1 because it's legal to insert at the end.
23269 assertLessThan(index, this.length + 1 + shift, 'index');
23270 }
23271 return index;
23272 }
23273};
23274function getViewRefs(lContainer) {
23275 return lContainer[VIEW_REFS];
23276}
23277function getOrCreateViewRefs(lContainer) {
23278 return (lContainer[VIEW_REFS] || (lContainer[VIEW_REFS] = []));
23279}
23280/**
23281 * Creates a ViewContainerRef and stores it on the injector.
23282 *
23283 * @param ViewContainerRefToken The ViewContainerRef type
23284 * @param ElementRefToken The ElementRef type
23285 * @param hostTNode The node that is requesting a ViewContainerRef
23286 * @param hostLView The view to which the node belongs
23287 * @returns The ViewContainerRef instance to use
23288 */
23289function createContainerRef(hostTNode, hostLView) {
23290 ngDevMode && assertTNodeType(hostTNode, 12 /* AnyContainer */ | 3 /* AnyRNode */);
23291 let lContainer;
23292 const slotValue = hostLView[hostTNode.index];
23293 if (isLContainer(slotValue)) {
23294 // If the host is a container, we don't need to create a new LContainer
23295 lContainer = slotValue;
23296 }
23297 else {
23298 let commentNode;
23299 // If the host is an element container, the native host element is guaranteed to be a
23300 // comment and we can reuse that comment as anchor element for the new LContainer.
23301 // The comment node in question is already part of the DOM structure so we don't need to append
23302 // it again.
23303 if (hostTNode.type & 8 /* ElementContainer */) {
23304 commentNode = unwrapRNode(slotValue);
23305 }
23306 else {
23307 // If the host is a regular element, we have to insert a comment node manually which will
23308 // be used as an anchor when inserting elements. In this specific case we use low-level DOM
23309 // manipulation to insert it.
23310 const renderer = hostLView[RENDERER];
23311 ngDevMode && ngDevMode.rendererCreateComment++;
23312 commentNode = renderer.createComment(ngDevMode ? 'container' : '');
23313 const hostNative = getNativeByTNode(hostTNode, hostLView);
23314 const parentOfHostNative = nativeParentNode(renderer, hostNative);
23315 nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative), false);
23316 }
23317 hostLView[hostTNode.index] = lContainer =
23318 createLContainer(slotValue, hostLView, commentNode, hostTNode);
23319 addToViewTree(hostLView, lContainer);
23320 }
23321 return new R3ViewContainerRef(lContainer, hostTNode, hostLView);
23322}
23323
23324/**
23325 * @license
23326 * Copyright Google LLC All Rights Reserved.
23327 *
23328 * Use of this source code is governed by an MIT-style license that can be
23329 * found in the LICENSE file at https://angular.io/license
23330 */
23331// Note: This hack is necessary so we don't erroneously get a circular dependency
23332// failure based on types.
23333const unusedValueExportToPlacateAjd$1 = 1;
23334
23335/**
23336 * @license
23337 * Copyright Google LLC All Rights Reserved.
23338 *
23339 * Use of this source code is governed by an MIT-style license that can be
23340 * found in the LICENSE file at https://angular.io/license
23341 */
23342// Note: This hack is necessary so we don't erroneously get a circular dependency
23343// failure based on types.
23344const unusedValueExportToPlacateAjd = 1;
23345
23346/**
23347 * @license
23348 * Copyright Google LLC All Rights Reserved.
23349 *
23350 * Use of this source code is governed by an MIT-style license that can be
23351 * found in the LICENSE file at https://angular.io/license
23352 */
23353const unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd;
23354class LQuery_ {
23355 constructor(queryList) {
23356 this.queryList = queryList;
23357 this.matches = null;
23358 }
23359 clone() {
23360 return new LQuery_(this.queryList);
23361 }
23362 setDirty() {
23363 this.queryList.setDirty();
23364 }
23365}
23366class LQueries_ {
23367 constructor(queries = []) {
23368 this.queries = queries;
23369 }
23370 createEmbeddedView(tView) {
23371 const tQueries = tView.queries;
23372 if (tQueries !== null) {
23373 const noOfInheritedQueries = tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length;
23374 const viewLQueries = [];
23375 // An embedded view has queries propagated from a declaration view at the beginning of the
23376 // TQueries collection and up until a first content query declared in the embedded view. Only
23377 // propagated LQueries are created at this point (LQuery corresponding to declared content
23378 // queries will be instantiated from the content query instructions for each directive).
23379 for (let i = 0; i < noOfInheritedQueries; i++) {
23380 const tQuery = tQueries.getByIndex(i);
23381 const parentLQuery = this.queries[tQuery.indexInDeclarationView];
23382 viewLQueries.push(parentLQuery.clone());
23383 }
23384 return new LQueries_(viewLQueries);
23385 }
23386 return null;
23387 }
23388 insertView(tView) {
23389 this.dirtyQueriesWithMatches(tView);
23390 }
23391 detachView(tView) {
23392 this.dirtyQueriesWithMatches(tView);
23393 }
23394 dirtyQueriesWithMatches(tView) {
23395 for (let i = 0; i < this.queries.length; i++) {
23396 if (getTQuery(tView, i).matches !== null) {
23397 this.queries[i].setDirty();
23398 }
23399 }
23400 }
23401}
23402class TQueryMetadata_ {
23403 constructor(predicate, flags, read = null) {
23404 this.predicate = predicate;
23405 this.flags = flags;
23406 this.read = read;
23407 }
23408}
23409class TQueries_ {
23410 constructor(queries = []) {
23411 this.queries = queries;
23412 }
23413 elementStart(tView, tNode) {
23414 ngDevMode &&
23415 assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');
23416 for (let i = 0; i < this.queries.length; i++) {
23417 this.queries[i].elementStart(tView, tNode);
23418 }
23419 }
23420 elementEnd(tNode) {
23421 for (let i = 0; i < this.queries.length; i++) {
23422 this.queries[i].elementEnd(tNode);
23423 }
23424 }
23425 embeddedTView(tNode) {
23426 let queriesForTemplateRef = null;
23427 for (let i = 0; i < this.length; i++) {
23428 const childQueryIndex = queriesForTemplateRef !== null ? queriesForTemplateRef.length : 0;
23429 const tqueryClone = this.getByIndex(i).embeddedTView(tNode, childQueryIndex);
23430 if (tqueryClone) {
23431 tqueryClone.indexInDeclarationView = i;
23432 if (queriesForTemplateRef !== null) {
23433 queriesForTemplateRef.push(tqueryClone);
23434 }
23435 else {
23436 queriesForTemplateRef = [tqueryClone];
23437 }
23438 }
23439 }
23440 return queriesForTemplateRef !== null ? new TQueries_(queriesForTemplateRef) : null;
23441 }
23442 template(tView, tNode) {
23443 ngDevMode &&
23444 assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');
23445 for (let i = 0; i < this.queries.length; i++) {
23446 this.queries[i].template(tView, tNode);
23447 }
23448 }
23449 getByIndex(index) {
23450 ngDevMode && assertIndexInRange(this.queries, index);
23451 return this.queries[index];
23452 }
23453 get length() {
23454 return this.queries.length;
23455 }
23456 track(tquery) {
23457 this.queries.push(tquery);
23458 }
23459}
23460class TQuery_ {
23461 constructor(metadata, nodeIndex = -1) {
23462 this.metadata = metadata;
23463 this.matches = null;
23464 this.indexInDeclarationView = -1;
23465 this.crossesNgTemplate = false;
23466 /**
23467 * A flag indicating if a given query still applies to nodes it is crossing. We use this flag
23468 * (alongside with _declarationNodeIndex) to know when to stop applying content queries to
23469 * elements in a template.
23470 */
23471 this._appliesToNextNode = true;
23472 this._declarationNodeIndex = nodeIndex;
23473 }
23474 elementStart(tView, tNode) {
23475 if (this.isApplyingToNode(tNode)) {
23476 this.matchTNode(tView, tNode);
23477 }
23478 }
23479 elementEnd(tNode) {
23480 if (this._declarationNodeIndex === tNode.index) {
23481 this._appliesToNextNode = false;
23482 }
23483 }
23484 template(tView, tNode) {
23485 this.elementStart(tView, tNode);
23486 }
23487 embeddedTView(tNode, childQueryIndex) {
23488 if (this.isApplyingToNode(tNode)) {
23489 this.crossesNgTemplate = true;
23490 // A marker indicating a `<ng-template>` element (a placeholder for query results from
23491 // embedded views created based on this `<ng-template>`).
23492 this.addMatch(-tNode.index, childQueryIndex);
23493 return new TQuery_(this.metadata);
23494 }
23495 return null;
23496 }
23497 isApplyingToNode(tNode) {
23498 if (this._appliesToNextNode &&
23499 (this.metadata.flags & 1 /* descendants */) !== 1 /* descendants */) {
23500 const declarationNodeIdx = this._declarationNodeIndex;
23501 let parent = tNode.parent;
23502 // Determine if a given TNode is a "direct" child of a node on which a content query was
23503 // declared (only direct children of query's host node can match with the descendants: false
23504 // option). There are 3 main use-case / conditions to consider here:
23505 // - <needs-target><i #target></i></needs-target>: here <i #target> parent node is a query
23506 // host node;
23507 // - <needs-target><ng-template [ngIf]="true"><i #target></i></ng-template></needs-target>:
23508 // here <i #target> parent node is null;
23509 // - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need
23510 // to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse
23511 // up past the query's host node!).
23512 while (parent !== null && (parent.type & 8 /* ElementContainer */) &&
23513 parent.index !== declarationNodeIdx) {
23514 parent = parent.parent;
23515 }
23516 return declarationNodeIdx === (parent !== null ? parent.index : -1);
23517 }
23518 return this._appliesToNextNode;
23519 }
23520 matchTNode(tView, tNode) {
23521 const predicate = this.metadata.predicate;
23522 if (Array.isArray(predicate)) {
23523 for (let i = 0; i < predicate.length; i++) {
23524 const name = predicate[i];
23525 this.matchTNodeWithReadOption(tView, tNode, getIdxOfMatchingSelector(tNode, name));
23526 // Also try matching the name to a provider since strings can be used as DI tokens too.
23527 this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, name, false, false));
23528 }
23529 }
23530 else {
23531 if (predicate === TemplateRef) {
23532 if (tNode.type & 4 /* Container */) {
23533 this.matchTNodeWithReadOption(tView, tNode, -1);
23534 }
23535 }
23536 else {
23537 this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, predicate, false, false));
23538 }
23539 }
23540 }
23541 matchTNodeWithReadOption(tView, tNode, nodeMatchIdx) {
23542 if (nodeMatchIdx !== null) {
23543 const read = this.metadata.read;
23544 if (read !== null) {
23545 if (read === ElementRef || read === ViewContainerRef ||
23546 read === TemplateRef && (tNode.type & 4 /* Container */)) {
23547 this.addMatch(tNode.index, -2);
23548 }
23549 else {
23550 const directiveOrProviderIdx = locateDirectiveOrProvider(tNode, tView, read, false, false);
23551 if (directiveOrProviderIdx !== null) {
23552 this.addMatch(tNode.index, directiveOrProviderIdx);
23553 }
23554 }
23555 }
23556 else {
23557 this.addMatch(tNode.index, nodeMatchIdx);
23558 }
23559 }
23560 }
23561 addMatch(tNodeIdx, matchIdx) {
23562 if (this.matches === null) {
23563 this.matches = [tNodeIdx, matchIdx];
23564 }
23565 else {
23566 this.matches.push(tNodeIdx, matchIdx);
23567 }
23568 }
23569}
23570/**
23571 * Iterates over local names for a given node and returns directive index
23572 * (or -1 if a local name points to an element).
23573 *
23574 * @param tNode static data of a node to check
23575 * @param selector selector to match
23576 * @returns directive index, -1 or null if a selector didn't match any of the local names
23577 */
23578function getIdxOfMatchingSelector(tNode, selector) {
23579 const localNames = tNode.localNames;
23580 if (localNames !== null) {
23581 for (let i = 0; i < localNames.length; i += 2) {
23582 if (localNames[i] === selector) {
23583 return localNames[i + 1];
23584 }
23585 }
23586 }
23587 return null;
23588}
23589function createResultByTNodeType(tNode, currentView) {
23590 if (tNode.type & (3 /* AnyRNode */ | 8 /* ElementContainer */)) {
23591 return createElementRef(tNode, currentView);
23592 }
23593 else if (tNode.type & 4 /* Container */) {
23594 return createTemplateRef(tNode, currentView);
23595 }
23596 return null;
23597}
23598function createResultForNode(lView, tNode, matchingIdx, read) {
23599 if (matchingIdx === -1) {
23600 // if read token and / or strategy is not specified, detect it using appropriate tNode type
23601 return createResultByTNodeType(tNode, lView);
23602 }
23603 else if (matchingIdx === -2) {
23604 // read a special token from a node injector
23605 return createSpecialToken(lView, tNode, read);
23606 }
23607 else {
23608 // read a token
23609 return getNodeInjectable(lView, lView[TVIEW], matchingIdx, tNode);
23610 }
23611}
23612function createSpecialToken(lView, tNode, read) {
23613 if (read === ElementRef) {
23614 return createElementRef(tNode, lView);
23615 }
23616 else if (read === TemplateRef) {
23617 return createTemplateRef(tNode, lView);
23618 }
23619 else if (read === ViewContainerRef) {
23620 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
23621 return createContainerRef(tNode, lView);
23622 }
23623 else {
23624 ngDevMode &&
23625 throwError(`Special token to read should be one of ElementRef, TemplateRef or ViewContainerRef but got ${stringify(read)}.`);
23626 }
23627}
23628/**
23629 * A helper function that creates query results for a given view. This function is meant to do the
23630 * processing once and only once for a given view instance (a set of results for a given view
23631 * doesn't change).
23632 */
23633function materializeViewResults(tView, lView, tQuery, queryIndex) {
23634 const lQuery = lView[QUERIES].queries[queryIndex];
23635 if (lQuery.matches === null) {
23636 const tViewData = tView.data;
23637 const tQueryMatches = tQuery.matches;
23638 const result = [];
23639 for (let i = 0; i < tQueryMatches.length; i += 2) {
23640 const matchedNodeIdx = tQueryMatches[i];
23641 if (matchedNodeIdx < 0) {
23642 // we at the <ng-template> marker which might have results in views created based on this
23643 // <ng-template> - those results will be in separate views though, so here we just leave
23644 // null as a placeholder
23645 result.push(null);
23646 }
23647 else {
23648 ngDevMode && assertIndexInRange(tViewData, matchedNodeIdx);
23649 const tNode = tViewData[matchedNodeIdx];
23650 result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read));
23651 }
23652 }
23653 lQuery.matches = result;
23654 }
23655 return lQuery.matches;
23656}
23657/**
23658 * A helper function that collects (already materialized) query results from a tree of views,
23659 * starting with a provided LView.
23660 */
23661function collectQueryResults(tView, lView, queryIndex, result) {
23662 const tQuery = tView.queries.getByIndex(queryIndex);
23663 const tQueryMatches = tQuery.matches;
23664 if (tQueryMatches !== null) {
23665 const lViewResults = materializeViewResults(tView, lView, tQuery, queryIndex);
23666 for (let i = 0; i < tQueryMatches.length; i += 2) {
23667 const tNodeIdx = tQueryMatches[i];
23668 if (tNodeIdx > 0) {
23669 result.push(lViewResults[i / 2]);
23670 }
23671 else {
23672 const childQueryIndex = tQueryMatches[i + 1];
23673 const declarationLContainer = lView[-tNodeIdx];
23674 ngDevMode && assertLContainer(declarationLContainer);
23675 // collect matches for views inserted in this container
23676 for (let i = CONTAINER_HEADER_OFFSET; i < declarationLContainer.length; i++) {
23677 const embeddedLView = declarationLContainer[i];
23678 if (embeddedLView[DECLARATION_LCONTAINER] === embeddedLView[PARENT]) {
23679 collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
23680 }
23681 }
23682 // collect matches for views created from this declaration container and inserted into
23683 // different containers
23684 if (declarationLContainer[MOVED_VIEWS] !== null) {
23685 const embeddedLViews = declarationLContainer[MOVED_VIEWS];
23686 for (let i = 0; i < embeddedLViews.length; i++) {
23687 const embeddedLView = embeddedLViews[i];
23688 collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
23689 }
23690 }
23691 }
23692 }
23693 }
23694 return result;
23695}
23696/**
23697 * Refreshes a query by combining matches from all active views and removing matches from deleted
23698 * views.
23699 *
23700 * @returns `true` if a query got dirty during change detection or if this is a static query
23701 * resolving in creation mode, `false` otherwise.
23702 *
23703 * @codeGenApi
23704 */
23705function ɵɵqueryRefresh(queryList) {
23706 const lView = getLView();
23707 const tView = getTView();
23708 const queryIndex = getCurrentQueryIndex();
23709 setCurrentQueryIndex(queryIndex + 1);
23710 const tQuery = getTQuery(tView, queryIndex);
23711 if (queryList.dirty &&
23712 (isCreationMode(lView) ===
23713 ((tQuery.metadata.flags & 2 /* isStatic */) === 2 /* isStatic */))) {
23714 if (tQuery.matches === null) {
23715 queryList.reset([]);
23716 }
23717 else {
23718 const result = tQuery.crossesNgTemplate ?
23719 collectQueryResults(tView, lView, queryIndex, []) :
23720 materializeViewResults(tView, lView, tQuery, queryIndex);
23721 queryList.reset(result, unwrapElementRef);
23722 queryList.notifyOnChanges();
23723 }
23724 return true;
23725 }
23726 return false;
23727}
23728/**
23729 * Creates new QueryList, stores the reference in LView and returns QueryList.
23730 *
23731 * @param predicate The type for which the query will search
23732 * @param flags Flags associated with the query
23733 * @param read What to save in the query
23734 *
23735 * @codeGenApi
23736 */
23737function ɵɵviewQuery(predicate, flags, read) {
23738 ngDevMode && assertNumber(flags, 'Expecting flags');
23739 const tView = getTView();
23740 if (tView.firstCreatePass) {
23741 createTQuery(tView, new TQueryMetadata_(predicate, flags, read), -1);
23742 if ((flags & 2 /* isStatic */) === 2 /* isStatic */) {
23743 tView.staticViewQueries = true;
23744 }
23745 }
23746 createLQuery(tView, getLView(), flags);
23747}
23748/**
23749 * Registers a QueryList, associated with a content query, for later refresh (part of a view
23750 * refresh).
23751 *
23752 * @param directiveIndex Current directive index
23753 * @param predicate The type for which the query will search
23754 * @param flags Flags associated with the query
23755 * @param read What to save in the query
23756 * @returns QueryList<T>
23757 *
23758 * @codeGenApi
23759 */
23760function ɵɵcontentQuery(directiveIndex, predicate, flags, read) {
23761 ngDevMode && assertNumber(flags, 'Expecting flags');
23762 const tView = getTView();
23763 if (tView.firstCreatePass) {
23764 const tNode = getCurrentTNode();
23765 createTQuery(tView, new TQueryMetadata_(predicate, flags, read), tNode.index);
23766 saveContentQueryAndDirectiveIndex(tView, directiveIndex);
23767 if ((flags & 2 /* isStatic */) === 2 /* isStatic */) {
23768 tView.staticContentQueries = true;
23769 }
23770 }
23771 createLQuery(tView, getLView(), flags);
23772}
23773/**
23774 * Loads a QueryList corresponding to the current view or content query.
23775 *
23776 * @codeGenApi
23777 */
23778function ɵɵloadQuery() {
23779 return loadQueryInternal(getLView(), getCurrentQueryIndex());
23780}
23781function loadQueryInternal(lView, queryIndex) {
23782 ngDevMode &&
23783 assertDefined(lView[QUERIES], 'LQueries should be defined when trying to load a query');
23784 ngDevMode && assertIndexInRange(lView[QUERIES].queries, queryIndex);
23785 return lView[QUERIES].queries[queryIndex].queryList;
23786}
23787function createLQuery(tView, lView, flags) {
23788 const queryList = new QueryList((flags & 4 /* emitDistinctChangesOnly */) === 4 /* emitDistinctChangesOnly */);
23789 storeCleanupWithContext(tView, lView, queryList, queryList.destroy);
23790 if (lView[QUERIES] === null)
23791 lView[QUERIES] = new LQueries_();
23792 lView[QUERIES].queries.push(new LQuery_(queryList));
23793}
23794function createTQuery(tView, metadata, nodeIndex) {
23795 if (tView.queries === null)
23796 tView.queries = new TQueries_();
23797 tView.queries.track(new TQuery_(metadata, nodeIndex));
23798}
23799function saveContentQueryAndDirectiveIndex(tView, directiveIndex) {
23800 const tViewContentQueries = tView.contentQueries || (tView.contentQueries = []);
23801 const lastSavedDirectiveIndex = tViewContentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] : -1;
23802 if (directiveIndex !== lastSavedDirectiveIndex) {
23803 tViewContentQueries.push(tView.queries.length - 1, directiveIndex);
23804 }
23805}
23806function getTQuery(tView, index) {
23807 ngDevMode && assertDefined(tView.queries, 'TQueries must be defined to retrieve a TQuery');
23808 return tView.queries.getByIndex(index);
23809}
23810
23811/**
23812 * @license
23813 * Copyright Google LLC All Rights Reserved.
23814 *
23815 * Use of this source code is governed by an MIT-style license that can be
23816 * found in the LICENSE file at https://angular.io/license
23817 */
23818/**
23819 * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
23820 * `<ng-template>` element.
23821 *
23822 * @codeGenApi
23823 */
23824function ɵɵtemplateRefExtractor(tNode, lView) {
23825 return createTemplateRef(tNode, lView);
23826}
23827
23828/**
23829 * @license
23830 * Copyright Google LLC All Rights Reserved.
23831 *
23832 * Use of this source code is governed by an MIT-style license that can be
23833 * found in the LICENSE file at https://angular.io/license
23834 */
23835
23836/**
23837 * @license
23838 * Copyright Google LLC All Rights Reserved.
23839 *
23840 * Use of this source code is governed by an MIT-style license that can be
23841 * found in the LICENSE file at https://angular.io/license
23842 */
23843/**
23844 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
23845 *
23846 * This should be kept up to date with the public exports of @angular/core.
23847 */
23848const angularCoreEnv = (() => ({
23849 'ɵɵattribute': ɵɵattribute,
23850 'ɵɵattributeInterpolate1': ɵɵattributeInterpolate1,
23851 'ɵɵattributeInterpolate2': ɵɵattributeInterpolate2,
23852 'ɵɵattributeInterpolate3': ɵɵattributeInterpolate3,
23853 'ɵɵattributeInterpolate4': ɵɵattributeInterpolate4,
23854 'ɵɵattributeInterpolate5': ɵɵattributeInterpolate5,
23855 'ɵɵattributeInterpolate6': ɵɵattributeInterpolate6,
23856 'ɵɵattributeInterpolate7': ɵɵattributeInterpolate7,
23857 'ɵɵattributeInterpolate8': ɵɵattributeInterpolate8,
23858 'ɵɵattributeInterpolateV': ɵɵattributeInterpolateV,
23859 'ɵɵdefineComponent': ɵɵdefineComponent,
23860 'ɵɵdefineDirective': ɵɵdefineDirective,
23861 'ɵɵdefineInjectable': ɵɵdefineInjectable,
23862 'ɵɵdefineInjector': ɵɵdefineInjector,
23863 'ɵɵdefineNgModule': ɵɵdefineNgModule,
23864 'ɵɵdefinePipe': ɵɵdefinePipe,
23865 'ɵɵdirectiveInject': ɵɵdirectiveInject,
23866 'ɵɵgetInheritedFactory': ɵɵgetInheritedFactory,
23867 'ɵɵinject': ɵɵinject,
23868 'ɵɵinjectAttribute': ɵɵinjectAttribute,
23869 'ɵɵinvalidFactory': ɵɵinvalidFactory,
23870 'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
23871 'ɵɵtemplateRefExtractor': ɵɵtemplateRefExtractor,
23872 'ɵɵNgOnChangesFeature': ɵɵNgOnChangesFeature,
23873 'ɵɵProvidersFeature': ɵɵProvidersFeature,
23874 'ɵɵCopyDefinitionFeature': ɵɵCopyDefinitionFeature,
23875 'ɵɵInheritDefinitionFeature': ɵɵInheritDefinitionFeature,
23876 'ɵɵnextContext': ɵɵnextContext,
23877 'ɵɵnamespaceHTML': ɵɵnamespaceHTML,
23878 'ɵɵnamespaceMathML': ɵɵnamespaceMathML,
23879 'ɵɵnamespaceSVG': ɵɵnamespaceSVG,
23880 'ɵɵenableBindings': ɵɵenableBindings,
23881 'ɵɵdisableBindings': ɵɵdisableBindings,
23882 'ɵɵelementStart': ɵɵelementStart,
23883 'ɵɵelementEnd': ɵɵelementEnd,
23884 'ɵɵelement': ɵɵelement,
23885 'ɵɵelementContainerStart': ɵɵelementContainerStart,
23886 'ɵɵelementContainerEnd': ɵɵelementContainerEnd,
23887 'ɵɵelementContainer': ɵɵelementContainer,
23888 'ɵɵpureFunction0': ɵɵpureFunction0,
23889 'ɵɵpureFunction1': ɵɵpureFunction1,
23890 'ɵɵpureFunction2': ɵɵpureFunction2,
23891 'ɵɵpureFunction3': ɵɵpureFunction3,
23892 'ɵɵpureFunction4': ɵɵpureFunction4,
23893 'ɵɵpureFunction5': ɵɵpureFunction5,
23894 'ɵɵpureFunction6': ɵɵpureFunction6,
23895 'ɵɵpureFunction7': ɵɵpureFunction7,
23896 'ɵɵpureFunction8': ɵɵpureFunction8,
23897 'ɵɵpureFunctionV': ɵɵpureFunctionV,
23898 'ɵɵgetCurrentView': ɵɵgetCurrentView,
23899 'ɵɵrestoreView': ɵɵrestoreView,
23900 'ɵɵlistener': ɵɵlistener,
23901 'ɵɵprojection': ɵɵprojection,
23902 'ɵɵsyntheticHostProperty': ɵɵsyntheticHostProperty,
23903 'ɵɵsyntheticHostListener': ɵɵsyntheticHostListener,
23904 'ɵɵpipeBind1': ɵɵpipeBind1,
23905 'ɵɵpipeBind2': ɵɵpipeBind2,
23906 'ɵɵpipeBind3': ɵɵpipeBind3,
23907 'ɵɵpipeBind4': ɵɵpipeBind4,
23908 'ɵɵpipeBindV': ɵɵpipeBindV,
23909 'ɵɵprojectionDef': ɵɵprojectionDef,
23910 'ɵɵhostProperty': ɵɵhostProperty,
23911 'ɵɵproperty': ɵɵproperty,
23912 'ɵɵpropertyInterpolate': ɵɵpropertyInterpolate,
23913 'ɵɵpropertyInterpolate1': ɵɵpropertyInterpolate1,
23914 'ɵɵpropertyInterpolate2': ɵɵpropertyInterpolate2,
23915 'ɵɵpropertyInterpolate3': ɵɵpropertyInterpolate3,
23916 'ɵɵpropertyInterpolate4': ɵɵpropertyInterpolate4,
23917 'ɵɵpropertyInterpolate5': ɵɵpropertyInterpolate5,
23918 'ɵɵpropertyInterpolate6': ɵɵpropertyInterpolate6,
23919 'ɵɵpropertyInterpolate7': ɵɵpropertyInterpolate7,
23920 'ɵɵpropertyInterpolate8': ɵɵpropertyInterpolate8,
23921 'ɵɵpropertyInterpolateV': ɵɵpropertyInterpolateV,
23922 'ɵɵpipe': ɵɵpipe,
23923 'ɵɵqueryRefresh': ɵɵqueryRefresh,
23924 'ɵɵviewQuery': ɵɵviewQuery,
23925 'ɵɵloadQuery': ɵɵloadQuery,
23926 'ɵɵcontentQuery': ɵɵcontentQuery,
23927 'ɵɵreference': ɵɵreference,
23928 'ɵɵclassMap': ɵɵclassMap,
23929 'ɵɵclassMapInterpolate1': ɵɵclassMapInterpolate1,
23930 'ɵɵclassMapInterpolate2': ɵɵclassMapInterpolate2,
23931 'ɵɵclassMapInterpolate3': ɵɵclassMapInterpolate3,
23932 'ɵɵclassMapInterpolate4': ɵɵclassMapInterpolate4,
23933 'ɵɵclassMapInterpolate5': ɵɵclassMapInterpolate5,
23934 'ɵɵclassMapInterpolate6': ɵɵclassMapInterpolate6,
23935 'ɵɵclassMapInterpolate7': ɵɵclassMapInterpolate7,
23936 'ɵɵclassMapInterpolate8': ɵɵclassMapInterpolate8,
23937 'ɵɵclassMapInterpolateV': ɵɵclassMapInterpolateV,
23938 'ɵɵstyleMap': ɵɵstyleMap,
23939 'ɵɵstyleMapInterpolate1': ɵɵstyleMapInterpolate1,
23940 'ɵɵstyleMapInterpolate2': ɵɵstyleMapInterpolate2,
23941 'ɵɵstyleMapInterpolate3': ɵɵstyleMapInterpolate3,
23942 'ɵɵstyleMapInterpolate4': ɵɵstyleMapInterpolate4,
23943 'ɵɵstyleMapInterpolate5': ɵɵstyleMapInterpolate5,
23944 'ɵɵstyleMapInterpolate6': ɵɵstyleMapInterpolate6,
23945 'ɵɵstyleMapInterpolate7': ɵɵstyleMapInterpolate7,
23946 'ɵɵstyleMapInterpolate8': ɵɵstyleMapInterpolate8,
23947 'ɵɵstyleMapInterpolateV': ɵɵstyleMapInterpolateV,
23948 'ɵɵstyleProp': ɵɵstyleProp,
23949 'ɵɵstylePropInterpolate1': ɵɵstylePropInterpolate1,
23950 'ɵɵstylePropInterpolate2': ɵɵstylePropInterpolate2,
23951 'ɵɵstylePropInterpolate3': ɵɵstylePropInterpolate3,
23952 'ɵɵstylePropInterpolate4': ɵɵstylePropInterpolate4,
23953 'ɵɵstylePropInterpolate5': ɵɵstylePropInterpolate5,
23954 'ɵɵstylePropInterpolate6': ɵɵstylePropInterpolate6,
23955 'ɵɵstylePropInterpolate7': ɵɵstylePropInterpolate7,
23956 'ɵɵstylePropInterpolate8': ɵɵstylePropInterpolate8,
23957 'ɵɵstylePropInterpolateV': ɵɵstylePropInterpolateV,
23958 'ɵɵclassProp': ɵɵclassProp,
23959 'ɵɵadvance': ɵɵadvance,
23960 'ɵɵtemplate': ɵɵtemplate,
23961 'ɵɵtext': ɵɵtext,
23962 'ɵɵtextInterpolate': ɵɵtextInterpolate,
23963 'ɵɵtextInterpolate1': ɵɵtextInterpolate1,
23964 'ɵɵtextInterpolate2': ɵɵtextInterpolate2,
23965 'ɵɵtextInterpolate3': ɵɵtextInterpolate3,
23966 'ɵɵtextInterpolate4': ɵɵtextInterpolate4,
23967 'ɵɵtextInterpolate5': ɵɵtextInterpolate5,
23968 'ɵɵtextInterpolate6': ɵɵtextInterpolate6,
23969 'ɵɵtextInterpolate7': ɵɵtextInterpolate7,
23970 'ɵɵtextInterpolate8': ɵɵtextInterpolate8,
23971 'ɵɵtextInterpolateV': ɵɵtextInterpolateV,
23972 'ɵɵi18n': ɵɵi18n,
23973 'ɵɵi18nAttributes': ɵɵi18nAttributes,
23974 'ɵɵi18nExp': ɵɵi18nExp,
23975 'ɵɵi18nStart': ɵɵi18nStart,
23976 'ɵɵi18nEnd': ɵɵi18nEnd,
23977 'ɵɵi18nApply': ɵɵi18nApply,
23978 'ɵɵi18nPostprocess': ɵɵi18nPostprocess,
23979 'ɵɵresolveWindow': ɵɵresolveWindow,
23980 'ɵɵresolveDocument': ɵɵresolveDocument,
23981 'ɵɵresolveBody': ɵɵresolveBody,
23982 'ɵɵsetComponentScope': ɵɵsetComponentScope,
23983 'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope,
23984 'ɵɵsanitizeHtml': ɵɵsanitizeHtml,
23985 'ɵɵsanitizeStyle': ɵɵsanitizeStyle,
23986 'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl,
23987 'ɵɵsanitizeScript': ɵɵsanitizeScript,
23988 'ɵɵsanitizeUrl': ɵɵsanitizeUrl,
23989 'ɵɵsanitizeUrlOrResourceUrl': ɵɵsanitizeUrlOrResourceUrl,
23990 'ɵɵtrustConstantHtml': ɵɵtrustConstantHtml,
23991 'ɵɵtrustConstantResourceUrl': ɵɵtrustConstantResourceUrl,
23992 'forwardRef': forwardRef,
23993 'resolveForwardRef': resolveForwardRef,
23994}))();
23995
23996let jitOptions = null;
23997function setJitOptions(options) {
23998 if (jitOptions !== null) {
23999 if (options.defaultEncapsulation !== jitOptions.defaultEncapsulation) {
24000 ngDevMode &&
24001 console.error('Provided value for `defaultEncapsulation` can not be changed once it has been set.');
24002 return;
24003 }
24004 if (options.preserveWhitespaces !== jitOptions.preserveWhitespaces) {
24005 ngDevMode &&
24006 console.error('Provided value for `preserveWhitespaces` can not be changed once it has been set.');
24007 return;
24008 }
24009 }
24010 jitOptions = options;
24011}
24012function getJitOptions() {
24013 return jitOptions;
24014}
24015function resetJitOptions() {
24016 jitOptions = null;
24017}
24018
24019/**
24020 * @license
24021 * Copyright Google LLC All Rights Reserved.
24022 *
24023 * Use of this source code is governed by an MIT-style license that can be
24024 * found in the LICENSE file at https://angular.io/license
24025 */
24026const moduleQueue = [];
24027/**
24028 * Enqueues moduleDef to be checked later to see if scope can be set on its
24029 * component declarations.
24030 */
24031function enqueueModuleForDelayedScoping(moduleType, ngModule) {
24032 moduleQueue.push({ moduleType, ngModule });
24033}
24034let flushingModuleQueue = false;
24035/**
24036 * Loops over queued module definitions, if a given module definition has all of its
24037 * declarations resolved, it dequeues that module definition and sets the scope on
24038 * its declarations.
24039 */
24040function flushModuleScopingQueueAsMuchAsPossible() {
24041 if (!flushingModuleQueue) {
24042 flushingModuleQueue = true;
24043 try {
24044 for (let i = moduleQueue.length - 1; i >= 0; i--) {
24045 const { moduleType, ngModule } = moduleQueue[i];
24046 if (ngModule.declarations && ngModule.declarations.every(isResolvedDeclaration)) {
24047 // dequeue
24048 moduleQueue.splice(i, 1);
24049 setScopeOnDeclaredComponents(moduleType, ngModule);
24050 }
24051 }
24052 }
24053 finally {
24054 flushingModuleQueue = false;
24055 }
24056 }
24057}
24058/**
24059 * Returns truthy if a declaration has resolved. If the declaration happens to be
24060 * an array of declarations, it will recurse to check each declaration in that array
24061 * (which may also be arrays).
24062 */
24063function isResolvedDeclaration(declaration) {
24064 if (Array.isArray(declaration)) {
24065 return declaration.every(isResolvedDeclaration);
24066 }
24067 return !!resolveForwardRef(declaration);
24068}
24069/**
24070 * Compiles a module in JIT mode.
24071 *
24072 * This function automatically gets called when a class has a `@NgModule` decorator.
24073 */
24074function compileNgModule(moduleType, ngModule = {}) {
24075 compileNgModuleDefs(moduleType, ngModule);
24076 // Because we don't know if all declarations have resolved yet at the moment the
24077 // NgModule decorator is executing, we're enqueueing the setting of module scope
24078 // on its declarations to be run at a later time when all declarations for the module,
24079 // including forward refs, have resolved.
24080 enqueueModuleForDelayedScoping(moduleType, ngModule);
24081}
24082/**
24083 * Compiles and adds the `ɵmod`, `ɵfac` and `ɵinj` properties to the module class.
24084 *
24085 * It's possible to compile a module via this API which will allow duplicate declarations in its
24086 * root.
24087 */
24088function compileNgModuleDefs(moduleType, ngModule, allowDuplicateDeclarationsInRoot = false) {
24089 ngDevMode && assertDefined(moduleType, 'Required value moduleType');
24090 ngDevMode && assertDefined(ngModule, 'Required value ngModule');
24091 const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
24092 let ngModuleDef = null;
24093 Object.defineProperty(moduleType, NG_MOD_DEF, {
24094 configurable: true,
24095 get: () => {
24096 if (ngModuleDef === null) {
24097 if (ngDevMode && ngModule.imports && ngModule.imports.indexOf(moduleType) > -1) {
24098 // We need to assert this immediately, because allowing it to continue will cause it to
24099 // go into an infinite loop before we've reached the point where we throw all the errors.
24100 throw new Error(`'${stringifyForError(moduleType)}' module can't import itself`);
24101 }
24102 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'NgModule', type: moduleType });
24103 ngModuleDef = compiler.compileNgModule(angularCoreEnv, `ng:///${moduleType.name}/ɵmod.js`, {
24104 type: moduleType,
24105 bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(resolveForwardRef),
24106 declarations: declarations.map(resolveForwardRef),
24107 imports: flatten(ngModule.imports || EMPTY_ARRAY)
24108 .map(resolveForwardRef)
24109 .map(expandModuleWithProviders),
24110 exports: flatten(ngModule.exports || EMPTY_ARRAY)
24111 .map(resolveForwardRef)
24112 .map(expandModuleWithProviders),
24113 schemas: ngModule.schemas ? flatten(ngModule.schemas) : null,
24114 id: ngModule.id || null,
24115 });
24116 // Set `schemas` on ngModuleDef to an empty array in JIT mode to indicate that runtime
24117 // should verify that there are no unknown elements in a template. In AOT mode, that check
24118 // happens at compile time and `schemas` information is not present on Component and Module
24119 // defs after compilation (so the check doesn't happen the second time at runtime).
24120 if (!ngModuleDef.schemas) {
24121 ngModuleDef.schemas = [];
24122 }
24123 }
24124 return ngModuleDef;
24125 }
24126 });
24127 let ngFactoryDef = null;
24128 Object.defineProperty(moduleType, NG_FACTORY_DEF, {
24129 get: () => {
24130 if (ngFactoryDef === null) {
24131 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'NgModule', type: moduleType });
24132 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${moduleType.name}/ɵfac.js`, {
24133 name: moduleType.name,
24134 type: moduleType,
24135 deps: reflectDependencies(moduleType),
24136 target: compiler.FactoryTarget.NgModule,
24137 typeArgumentCount: 0,
24138 });
24139 }
24140 return ngFactoryDef;
24141 },
24142 // Make the property configurable in dev mode to allow overriding in tests
24143 configurable: !!ngDevMode,
24144 });
24145 let ngInjectorDef = null;
24146 Object.defineProperty(moduleType, NG_INJ_DEF, {
24147 get: () => {
24148 if (ngInjectorDef === null) {
24149 ngDevMode &&
24150 verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot);
24151 const meta = {
24152 name: moduleType.name,
24153 type: moduleType,
24154 providers: ngModule.providers || EMPTY_ARRAY,
24155 imports: [
24156 (ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef),
24157 (ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef),
24158 ],
24159 };
24160 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'NgModule', type: moduleType });
24161 ngInjectorDef =
24162 compiler.compileInjector(angularCoreEnv, `ng:///${moduleType.name}/ɵinj.js`, meta);
24163 }
24164 return ngInjectorDef;
24165 },
24166 // Make the property configurable in dev mode to allow overriding in tests
24167 configurable: !!ngDevMode,
24168 });
24169}
24170function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot, importingModule) {
24171 if (verifiedNgModule.get(moduleType))
24172 return;
24173 verifiedNgModule.set(moduleType, true);
24174 moduleType = resolveForwardRef(moduleType);
24175 let ngModuleDef;
24176 if (importingModule) {
24177 ngModuleDef = getNgModuleDef(moduleType);
24178 if (!ngModuleDef) {
24179 throw new Error(`Unexpected value '${moduleType.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
24180 }
24181 }
24182 else {
24183 ngModuleDef = getNgModuleDef(moduleType, true);
24184 }
24185 const errors = [];
24186 const declarations = maybeUnwrapFn(ngModuleDef.declarations);
24187 const imports = maybeUnwrapFn(ngModuleDef.imports);
24188 flatten(imports).map(unwrapModuleWithProvidersImports).forEach(mod => {
24189 verifySemanticsOfNgModuleImport(mod, moduleType);
24190 verifySemanticsOfNgModuleDef(mod, false, moduleType);
24191 });
24192 const exports = maybeUnwrapFn(ngModuleDef.exports);
24193 declarations.forEach(verifyDeclarationsHaveDefinitions);
24194 declarations.forEach(verifyDirectivesHaveSelector);
24195 const combinedDeclarations = [
24196 ...declarations.map(resolveForwardRef),
24197 ...flatten(imports.map(computeCombinedExports)).map(resolveForwardRef),
24198 ];
24199 exports.forEach(verifyExportsAreDeclaredOrReExported);
24200 declarations.forEach(decl => verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot));
24201 declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule);
24202 const ngModule = getAnnotation(moduleType, 'NgModule');
24203 if (ngModule) {
24204 ngModule.imports &&
24205 flatten(ngModule.imports).map(unwrapModuleWithProvidersImports).forEach(mod => {
24206 verifySemanticsOfNgModuleImport(mod, moduleType);
24207 verifySemanticsOfNgModuleDef(mod, false, moduleType);
24208 });
24209 ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyCorrectBootstrapType);
24210 ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyComponentIsPartOfNgModule);
24211 ngModule.entryComponents &&
24212 deepForEach(ngModule.entryComponents, verifyComponentIsPartOfNgModule);
24213 }
24214 // Throw Error if any errors were detected.
24215 if (errors.length) {
24216 throw new Error(errors.join('\n'));
24217 }
24218 ////////////////////////////////////////////////////////////////////////////////////////////////
24219 function verifyDeclarationsHaveDefinitions(type) {
24220 type = resolveForwardRef(type);
24221 const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);
24222 if (!def) {
24223 errors.push(`Unexpected value '${stringifyForError(type)}' declared by the module '${stringifyForError(moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`);
24224 }
24225 }
24226 function verifyDirectivesHaveSelector(type) {
24227 type = resolveForwardRef(type);
24228 const def = getDirectiveDef(type);
24229 if (!getComponentDef(type) && def && def.selectors.length == 0) {
24230 errors.push(`Directive ${stringifyForError(type)} has no selector, please add it!`);
24231 }
24232 }
24233 function verifyExportsAreDeclaredOrReExported(type) {
24234 type = resolveForwardRef(type);
24235 const kind = getComponentDef(type) && 'component' || getDirectiveDef(type) && 'directive' ||
24236 getPipeDef$1(type) && 'pipe';
24237 if (kind) {
24238 // only checked if we are declared as Component, Directive, or Pipe
24239 // Modules don't need to be declared or imported.
24240 if (combinedDeclarations.lastIndexOf(type) === -1) {
24241 // We are exporting something which we don't explicitly declare or import.
24242 errors.push(`Can't export ${kind} ${stringifyForError(type)} from ${stringifyForError(moduleType)} as it was neither declared nor imported!`);
24243 }
24244 }
24245 }
24246 function verifyDeclarationIsUnique(type, suppressErrors) {
24247 type = resolveForwardRef(type);
24248 const existingModule = ownerNgModule.get(type);
24249 if (existingModule && existingModule !== moduleType) {
24250 if (!suppressErrors) {
24251 const modules = [existingModule, moduleType].map(stringifyForError).sort();
24252 errors.push(`Type ${stringifyForError(type)} is part of the declarations of 2 modules: ${modules[0]} and ${modules[1]}! ` +
24253 `Please consider moving ${stringifyForError(type)} to a higher module that imports ${modules[0]} and ${modules[1]}. ` +
24254 `You can also create a new NgModule that exports and includes ${stringifyForError(type)} then import that NgModule in ${modules[0]} and ${modules[1]}.`);
24255 }
24256 }
24257 else {
24258 // Mark type as having owner.
24259 ownerNgModule.set(type, moduleType);
24260 }
24261 }
24262 function verifyComponentIsPartOfNgModule(type) {
24263 type = resolveForwardRef(type);
24264 const existingModule = ownerNgModule.get(type);
24265 if (!existingModule) {
24266 errors.push(`Component ${stringifyForError(type)} is not part of any NgModule or the module has not been imported into your module.`);
24267 }
24268 }
24269 function verifyCorrectBootstrapType(type) {
24270 type = resolveForwardRef(type);
24271 if (!getComponentDef(type)) {
24272 errors.push(`${stringifyForError(type)} cannot be used as an entry component.`);
24273 }
24274 }
24275 function verifyComponentEntryComponentsIsPartOfNgModule(type) {
24276 type = resolveForwardRef(type);
24277 if (getComponentDef(type)) {
24278 // We know we are component
24279 const component = getAnnotation(type, 'Component');
24280 if (component && component.entryComponents) {
24281 deepForEach(component.entryComponents, verifyComponentIsPartOfNgModule);
24282 }
24283 }
24284 }
24285 function verifySemanticsOfNgModuleImport(type, importingModule) {
24286 type = resolveForwardRef(type);
24287 if (getComponentDef(type) || getDirectiveDef(type)) {
24288 throw new Error(`Unexpected directive '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
24289 }
24290 if (getPipeDef$1(type)) {
24291 throw new Error(`Unexpected pipe '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
24292 }
24293 }
24294}
24295function unwrapModuleWithProvidersImports(typeOrWithProviders) {
24296 typeOrWithProviders = resolveForwardRef(typeOrWithProviders);
24297 return typeOrWithProviders.ngModule || typeOrWithProviders;
24298}
24299function getAnnotation(type, name) {
24300 let annotation = null;
24301 collect(type.__annotations__);
24302 collect(type.decorators);
24303 return annotation;
24304 function collect(annotations) {
24305 if (annotations) {
24306 annotations.forEach(readAnnotation);
24307 }
24308 }
24309 function readAnnotation(decorator) {
24310 if (!annotation) {
24311 const proto = Object.getPrototypeOf(decorator);
24312 if (proto.ngMetadataName == name) {
24313 annotation = decorator;
24314 }
24315 else if (decorator.type) {
24316 const proto = Object.getPrototypeOf(decorator.type);
24317 if (proto.ngMetadataName == name) {
24318 annotation = decorator.args[0];
24319 }
24320 }
24321 }
24322 }
24323}
24324/**
24325 * Keep track of compiled components. This is needed because in tests we often want to compile the
24326 * same component with more than one NgModule. This would cause an error unless we reset which
24327 * NgModule the component belongs to. We keep the list of compiled components here so that the
24328 * TestBed can reset it later.
24329 */
24330let ownerNgModule = new WeakMap();
24331let verifiedNgModule = new WeakMap();
24332function resetCompiledComponents() {
24333 ownerNgModule = new WeakMap();
24334 verifiedNgModule = new WeakMap();
24335 moduleQueue.length = 0;
24336}
24337/**
24338 * Computes the combined declarations of explicit declarations, as well as declarations inherited by
24339 * traversing the exports of imported modules.
24340 * @param type
24341 */
24342function computeCombinedExports(type) {
24343 type = resolveForwardRef(type);
24344 const ngModuleDef = getNgModuleDef(type, true);
24345 return [...flatten(maybeUnwrapFn(ngModuleDef.exports).map((type) => {
24346 const ngModuleDef = getNgModuleDef(type);
24347 if (ngModuleDef) {
24348 verifySemanticsOfNgModuleDef(type, false);
24349 return computeCombinedExports(type);
24350 }
24351 else {
24352 return type;
24353 }
24354 }))];
24355}
24356/**
24357 * Some declared components may be compiled asynchronously, and thus may not have their
24358 * ɵcmp set yet. If this is the case, then a reference to the module is written into
24359 * the `ngSelectorScope` property of the declared type.
24360 */
24361function setScopeOnDeclaredComponents(moduleType, ngModule) {
24362 const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
24363 const transitiveScopes = transitiveScopesFor(moduleType);
24364 declarations.forEach(declaration => {
24365 if (declaration.hasOwnProperty(NG_COMP_DEF)) {
24366 // A `ɵcmp` field exists - go ahead and patch the component directly.
24367 const component = declaration;
24368 const componentDef = getComponentDef(component);
24369 patchComponentDefWithScope(componentDef, transitiveScopes);
24370 }
24371 else if (!declaration.hasOwnProperty(NG_DIR_DEF) && !declaration.hasOwnProperty(NG_PIPE_DEF)) {
24372 // Set `ngSelectorScope` for future reference when the component compilation finishes.
24373 declaration.ngSelectorScope = moduleType;
24374 }
24375 });
24376}
24377/**
24378 * Patch the definition of a component with directives and pipes from the compilation scope of
24379 * a given module.
24380 */
24381function patchComponentDefWithScope(componentDef, transitiveScopes) {
24382 componentDef.directiveDefs = () => Array.from(transitiveScopes.compilation.directives)
24383 .map(dir => dir.hasOwnProperty(NG_COMP_DEF) ? getComponentDef(dir) : getDirectiveDef(dir))
24384 .filter(def => !!def);
24385 componentDef.pipeDefs = () => Array.from(transitiveScopes.compilation.pipes).map(pipe => getPipeDef$1(pipe));
24386 componentDef.schemas = transitiveScopes.schemas;
24387 // Since we avoid Components/Directives/Pipes recompiling in case there are no overrides, we
24388 // may face a problem where previously compiled defs available to a given Component/Directive
24389 // are cached in TView and may become stale (in case any of these defs gets recompiled). In
24390 // order to avoid this problem, we force fresh TView to be created.
24391 componentDef.tView = null;
24392}
24393/**
24394 * Compute the pair of transitive scopes (compilation scope and exported scope) for a given module.
24395 *
24396 * This operation is memoized and the result is cached on the module's definition. This function can
24397 * be called on modules with components that have not fully compiled yet, but the result should not
24398 * be used until they have.
24399 *
24400 * @param moduleType module that transitive scope should be calculated for.
24401 */
24402function transitiveScopesFor(moduleType) {
24403 if (!isNgModule(moduleType)) {
24404 throw new Error(`${moduleType.name} does not have a module def (ɵmod property)`);
24405 }
24406 const def = getNgModuleDef(moduleType);
24407 if (def.transitiveCompileScopes !== null) {
24408 return def.transitiveCompileScopes;
24409 }
24410 const scopes = {
24411 schemas: def.schemas || null,
24412 compilation: {
24413 directives: new Set(),
24414 pipes: new Set(),
24415 },
24416 exported: {
24417 directives: new Set(),
24418 pipes: new Set(),
24419 },
24420 };
24421 maybeUnwrapFn(def.imports).forEach((imported) => {
24422 const importedType = imported;
24423 if (!isNgModule(importedType)) {
24424 throw new Error(`Importing ${importedType.name} which does not have a ɵmod property`);
24425 }
24426 // When this module imports another, the imported module's exported directives and pipes are
24427 // added to the compilation scope of this module.
24428 const importedScope = transitiveScopesFor(importedType);
24429 importedScope.exported.directives.forEach(entry => scopes.compilation.directives.add(entry));
24430 importedScope.exported.pipes.forEach(entry => scopes.compilation.pipes.add(entry));
24431 });
24432 maybeUnwrapFn(def.declarations).forEach(declared => {
24433 const declaredWithDefs = declared;
24434 if (getPipeDef$1(declaredWithDefs)) {
24435 scopes.compilation.pipes.add(declared);
24436 }
24437 else {
24438 // Either declared has a ɵcmp or ɵdir, or it's a component which hasn't
24439 // had its template compiled yet. In either case, it gets added to the compilation's
24440 // directives.
24441 scopes.compilation.directives.add(declared);
24442 }
24443 });
24444 maybeUnwrapFn(def.exports).forEach((exported) => {
24445 const exportedType = exported;
24446 // Either the type is a module, a pipe, or a component/directive (which may not have a
24447 // ɵcmp as it might be compiled asynchronously).
24448 if (isNgModule(exportedType)) {
24449 // When this module exports another, the exported module's exported directives and pipes are
24450 // added to both the compilation and exported scopes of this module.
24451 const exportedScope = transitiveScopesFor(exportedType);
24452 exportedScope.exported.directives.forEach(entry => {
24453 scopes.compilation.directives.add(entry);
24454 scopes.exported.directives.add(entry);
24455 });
24456 exportedScope.exported.pipes.forEach(entry => {
24457 scopes.compilation.pipes.add(entry);
24458 scopes.exported.pipes.add(entry);
24459 });
24460 }
24461 else if (getPipeDef$1(exportedType)) {
24462 scopes.exported.pipes.add(exportedType);
24463 }
24464 else {
24465 scopes.exported.directives.add(exportedType);
24466 }
24467 });
24468 def.transitiveCompileScopes = scopes;
24469 return scopes;
24470}
24471function expandModuleWithProviders(value) {
24472 if (isModuleWithProviders(value)) {
24473 return value.ngModule;
24474 }
24475 return value;
24476}
24477function isModuleWithProviders(value) {
24478 return value.ngModule !== undefined;
24479}
24480function isNgModule(value) {
24481 return !!getNgModuleDef(value);
24482}
24483
24484/**
24485 * @license
24486 * Copyright Google LLC All Rights Reserved.
24487 *
24488 * Use of this source code is governed by an MIT-style license that can be
24489 * found in the LICENSE file at https://angular.io/license
24490 */
24491/**
24492 * Keep track of the compilation depth to avoid reentrancy issues during JIT compilation. This
24493 * matters in the following scenario:
24494 *
24495 * Consider a component 'A' that extends component 'B', both declared in module 'M'. During
24496 * the compilation of 'A' the definition of 'B' is requested to capture the inheritance chain,
24497 * potentially triggering compilation of 'B'. If this nested compilation were to trigger
24498 * `flushModuleScopingQueueAsMuchAsPossible` it may happen that module 'M' is still pending in the
24499 * queue, resulting in 'A' and 'B' to be patched with the NgModule scope. As the compilation of
24500 * 'A' is still in progress, this would introduce a circular dependency on its compilation. To avoid
24501 * this issue, the module scope queue is only flushed for compilations at the depth 0, to ensure
24502 * all compilations have finished.
24503 */
24504let compilationDepth = 0;
24505/**
24506 * Compile an Angular component according to its decorator metadata, and patch the resulting
24507 * component def (ɵcmp) onto the component type.
24508 *
24509 * Compilation may be asynchronous (due to the need to resolve URLs for the component template or
24510 * other resources, for example). In the event that compilation is not immediate, `compileComponent`
24511 * will enqueue resource resolution into a global queue and will fail to return the `ɵcmp`
24512 * until the global queue has been resolved with a call to `resolveComponentResources`.
24513 */
24514function compileComponent(type, metadata) {
24515 // Initialize ngDevMode. This must be the first statement in compileComponent.
24516 // See the `initNgDevMode` docstring for more information.
24517 (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
24518 let ngComponentDef = null;
24519 // Metadata may have resources which need to be resolved.
24520 maybeQueueResolutionOfComponentResources(type, metadata);
24521 // Note that we're using the same function as `Directive`, because that's only subset of metadata
24522 // that we need to create the ngFactoryDef. We're avoiding using the component metadata
24523 // because we'd have to resolve the asynchronous templates.
24524 addDirectiveFactoryDef(type, metadata);
24525 Object.defineProperty(type, NG_COMP_DEF, {
24526 get: () => {
24527 if (ngComponentDef === null) {
24528 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'component', type: type });
24529 if (componentNeedsResolution(metadata)) {
24530 const error = [`Component '${type.name}' is not resolved:`];
24531 if (metadata.templateUrl) {
24532 error.push(` - templateUrl: ${metadata.templateUrl}`);
24533 }
24534 if (metadata.styleUrls && metadata.styleUrls.length) {
24535 error.push(` - styleUrls: ${JSON.stringify(metadata.styleUrls)}`);
24536 }
24537 error.push(`Did you run and wait for 'resolveComponentResources()'?`);
24538 throw new Error(error.join('\n'));
24539 }
24540 // This const was called `jitOptions` previously but had to be renamed to `options` because
24541 // of a bug with Terser that caused optimized JIT builds to throw a `ReferenceError`.
24542 // This bug was investigated in https://github.com/angular/angular-cli/issues/17264.
24543 // We should not rename it back until https://github.com/terser/terser/issues/615 is fixed.
24544 const options = getJitOptions();
24545 let preserveWhitespaces = metadata.preserveWhitespaces;
24546 if (preserveWhitespaces === undefined) {
24547 if (options !== null && options.preserveWhitespaces !== undefined) {
24548 preserveWhitespaces = options.preserveWhitespaces;
24549 }
24550 else {
24551 preserveWhitespaces = false;
24552 }
24553 }
24554 let encapsulation = metadata.encapsulation;
24555 if (encapsulation === undefined) {
24556 if (options !== null && options.defaultEncapsulation !== undefined) {
24557 encapsulation = options.defaultEncapsulation;
24558 }
24559 else {
24560 encapsulation = ViewEncapsulation$1.Emulated;
24561 }
24562 }
24563 const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
24564 const meta = {
24565 ...directiveMetadata(type, metadata),
24566 typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl),
24567 template: metadata.template || '',
24568 preserveWhitespaces,
24569 styles: metadata.styles || EMPTY_ARRAY,
24570 animations: metadata.animations,
24571 directives: [],
24572 changeDetection: metadata.changeDetection,
24573 pipes: new Map(),
24574 encapsulation,
24575 interpolation: metadata.interpolation,
24576 viewProviders: metadata.viewProviders || null,
24577 };
24578 compilationDepth++;
24579 try {
24580 if (meta.usesInheritance) {
24581 addDirectiveDefToUndecoratedParents(type);
24582 }
24583 ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
24584 }
24585 finally {
24586 // Ensure that the compilation depth is decremented even when the compilation failed.
24587 compilationDepth--;
24588 }
24589 if (compilationDepth === 0) {
24590 // When NgModule decorator executed, we enqueued the module definition such that
24591 // it would only dequeue and add itself as module scope to all of its declarations,
24592 // but only if if all of its declarations had resolved. This call runs the check
24593 // to see if any modules that are in the queue can be dequeued and add scope to
24594 // their declarations.
24595 flushModuleScopingQueueAsMuchAsPossible();
24596 }
24597 // If component compilation is async, then the @NgModule annotation which declares the
24598 // component may execute and set an ngSelectorScope property on the component type. This
24599 // allows the component to patch itself with directiveDefs from the module after it
24600 // finishes compiling.
24601 if (hasSelectorScope(type)) {
24602 const scopes = transitiveScopesFor(type.ngSelectorScope);
24603 patchComponentDefWithScope(ngComponentDef, scopes);
24604 }
24605 }
24606 return ngComponentDef;
24607 },
24608 // Make the property configurable in dev mode to allow overriding in tests
24609 configurable: !!ngDevMode,
24610 });
24611}
24612function hasSelectorScope(component) {
24613 return component.ngSelectorScope !== undefined;
24614}
24615/**
24616 * Compile an Angular directive according to its decorator metadata, and patch the resulting
24617 * directive def onto the component type.
24618 *
24619 * In the event that compilation is not immediate, `compileDirective` will return a `Promise` which
24620 * will resolve when compilation completes and the directive becomes usable.
24621 */
24622function compileDirective(type, directive) {
24623 let ngDirectiveDef = null;
24624 addDirectiveFactoryDef(type, directive || {});
24625 Object.defineProperty(type, NG_DIR_DEF, {
24626 get: () => {
24627 if (ngDirectiveDef === null) {
24628 // `directive` can be null in the case of abstract directives as a base class
24629 // that use `@Directive()` with no selector. In that case, pass empty object to the
24630 // `directiveMetadata` function instead of null.
24631 const meta = getDirectiveMetadata(type, directive || {});
24632 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'directive', type });
24633 ngDirectiveDef =
24634 compiler.compileDirective(angularCoreEnv, meta.sourceMapUrl, meta.metadata);
24635 }
24636 return ngDirectiveDef;
24637 },
24638 // Make the property configurable in dev mode to allow overriding in tests
24639 configurable: !!ngDevMode,
24640 });
24641}
24642function getDirectiveMetadata(type, metadata) {
24643 const name = type && type.name;
24644 const sourceMapUrl = `ng:///${name}/ɵdir.js`;
24645 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'directive', type });
24646 const facade = directiveMetadata(type, metadata);
24647 facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl);
24648 if (facade.usesInheritance) {
24649 addDirectiveDefToUndecoratedParents(type);
24650 }
24651 return { metadata: facade, sourceMapUrl };
24652}
24653function addDirectiveFactoryDef(type, metadata) {
24654 let ngFactoryDef = null;
24655 Object.defineProperty(type, NG_FACTORY_DEF, {
24656 get: () => {
24657 if (ngFactoryDef === null) {
24658 const meta = getDirectiveMetadata(type, metadata);
24659 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'directive', type });
24660 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${type.name}/ɵfac.js`, {
24661 name: meta.metadata.name,
24662 type: meta.metadata.type,
24663 typeArgumentCount: 0,
24664 deps: reflectDependencies(type),
24665 target: compiler.FactoryTarget.Directive
24666 });
24667 }
24668 return ngFactoryDef;
24669 },
24670 // Make the property configurable in dev mode to allow overriding in tests
24671 configurable: !!ngDevMode,
24672 });
24673}
24674function extendsDirectlyFromObject(type) {
24675 return Object.getPrototypeOf(type.prototype) === Object.prototype;
24676}
24677/**
24678 * Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
24679 * `Component`).
24680 */
24681function directiveMetadata(type, metadata) {
24682 // Reflect inputs and outputs.
24683 const reflect = getReflect();
24684 const propMetadata = reflect.ownPropMetadata(type);
24685 return {
24686 name: type.name,
24687 type: type,
24688 selector: metadata.selector !== undefined ? metadata.selector : null,
24689 host: metadata.host || EMPTY_OBJ,
24690 propMetadata: propMetadata,
24691 inputs: metadata.inputs || EMPTY_ARRAY,
24692 outputs: metadata.outputs || EMPTY_ARRAY,
24693 queries: extractQueriesMetadata(type, propMetadata, isContentQuery),
24694 lifecycle: { usesOnChanges: reflect.hasLifecycleHook(type, 'ngOnChanges') },
24695 typeSourceSpan: null,
24696 usesInheritance: !extendsDirectlyFromObject(type),
24697 exportAs: extractExportAs(metadata.exportAs),
24698 providers: metadata.providers || null,
24699 viewQueries: extractQueriesMetadata(type, propMetadata, isViewQuery)
24700 };
24701}
24702/**
24703 * Adds a directive definition to all parent classes of a type that don't have an Angular decorator.
24704 */
24705function addDirectiveDefToUndecoratedParents(type) {
24706 const objPrototype = Object.prototype;
24707 let parent = Object.getPrototypeOf(type.prototype).constructor;
24708 // Go up the prototype until we hit `Object`.
24709 while (parent && parent !== objPrototype) {
24710 // Since inheritance works if the class was annotated already, we only need to add
24711 // the def if there are no annotations and the def hasn't been created already.
24712 if (!getDirectiveDef(parent) && !getComponentDef(parent) &&
24713 shouldAddAbstractDirective(parent)) {
24714 compileDirective(parent, null);
24715 }
24716 parent = Object.getPrototypeOf(parent);
24717 }
24718}
24719function convertToR3QueryPredicate(selector) {
24720 return typeof selector === 'string' ? splitByComma(selector) : resolveForwardRef(selector);
24721}
24722function convertToR3QueryMetadata(propertyName, ann) {
24723 return {
24724 propertyName: propertyName,
24725 predicate: convertToR3QueryPredicate(ann.selector),
24726 descendants: ann.descendants,
24727 first: ann.first,
24728 read: ann.read ? ann.read : null,
24729 static: !!ann.static,
24730 emitDistinctChangesOnly: !!ann.emitDistinctChangesOnly,
24731 };
24732}
24733function extractQueriesMetadata(type, propMetadata, isQueryAnn) {
24734 const queriesMeta = [];
24735 for (const field in propMetadata) {
24736 if (propMetadata.hasOwnProperty(field)) {
24737 const annotations = propMetadata[field];
24738 annotations.forEach(ann => {
24739 if (isQueryAnn(ann)) {
24740 if (!ann.selector) {
24741 throw new Error(`Can't construct a query for the property "${field}" of ` +
24742 `"${stringifyForError(type)}" since the query selector wasn't defined.`);
24743 }
24744 if (annotations.some(isInputAnnotation)) {
24745 throw new Error(`Cannot combine @Input decorators with query decorators`);
24746 }
24747 queriesMeta.push(convertToR3QueryMetadata(field, ann));
24748 }
24749 });
24750 }
24751 }
24752 return queriesMeta;
24753}
24754function extractExportAs(exportAs) {
24755 return exportAs === undefined ? null : splitByComma(exportAs);
24756}
24757function isContentQuery(value) {
24758 const name = value.ngMetadataName;
24759 return name === 'ContentChild' || name === 'ContentChildren';
24760}
24761function isViewQuery(value) {
24762 const name = value.ngMetadataName;
24763 return name === 'ViewChild' || name === 'ViewChildren';
24764}
24765function isInputAnnotation(value) {
24766 return value.ngMetadataName === 'Input';
24767}
24768function splitByComma(value) {
24769 return value.split(',').map(piece => piece.trim());
24770}
24771const LIFECYCLE_HOOKS = [
24772 'ngOnChanges', 'ngOnInit', 'ngOnDestroy', 'ngDoCheck', 'ngAfterViewInit', 'ngAfterViewChecked',
24773 'ngAfterContentInit', 'ngAfterContentChecked'
24774];
24775function shouldAddAbstractDirective(type) {
24776 const reflect = getReflect();
24777 if (LIFECYCLE_HOOKS.some(hookName => reflect.hasLifecycleHook(type, hookName))) {
24778 return true;
24779 }
24780 const propMetadata = reflect.propMetadata(type);
24781 for (const field in propMetadata) {
24782 const annotations = propMetadata[field];
24783 for (let i = 0; i < annotations.length; i++) {
24784 const current = annotations[i];
24785 const metadataName = current.ngMetadataName;
24786 if (isInputAnnotation(current) || isContentQuery(current) || isViewQuery(current) ||
24787 metadataName === 'Output' || metadataName === 'HostBinding' ||
24788 metadataName === 'HostListener') {
24789 return true;
24790 }
24791 }
24792 }
24793 return false;
24794}
24795
24796/**
24797 * @license
24798 * Copyright Google LLC All Rights Reserved.
24799 *
24800 * Use of this source code is governed by an MIT-style license that can be
24801 * found in the LICENSE file at https://angular.io/license
24802 */
24803function compilePipe(type, meta) {
24804 let ngPipeDef = null;
24805 let ngFactoryDef = null;
24806 Object.defineProperty(type, NG_FACTORY_DEF, {
24807 get: () => {
24808 if (ngFactoryDef === null) {
24809 const metadata = getPipeMetadata(type, meta);
24810 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'pipe', type: metadata.type });
24811 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${metadata.name}/ɵfac.js`, {
24812 name: metadata.name,
24813 type: metadata.type,
24814 typeArgumentCount: 0,
24815 deps: reflectDependencies(type),
24816 target: compiler.FactoryTarget.Pipe
24817 });
24818 }
24819 return ngFactoryDef;
24820 },
24821 // Make the property configurable in dev mode to allow overriding in tests
24822 configurable: !!ngDevMode,
24823 });
24824 Object.defineProperty(type, NG_PIPE_DEF, {
24825 get: () => {
24826 if (ngPipeDef === null) {
24827 const metadata = getPipeMetadata(type, meta);
24828 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'pipe', type: metadata.type });
24829 ngPipeDef =
24830 compiler.compilePipe(angularCoreEnv, `ng:///${metadata.name}/ɵpipe.js`, metadata);
24831 }
24832 return ngPipeDef;
24833 },
24834 // Make the property configurable in dev mode to allow overriding in tests
24835 configurable: !!ngDevMode,
24836 });
24837}
24838function getPipeMetadata(type, meta) {
24839 return {
24840 type: type,
24841 name: type.name,
24842 pipeName: meta.name,
24843 pure: meta.pure !== undefined ? meta.pure : true
24844 };
24845}
24846
24847/**
24848 * @license
24849 * Copyright Google LLC All Rights Reserved.
24850 *
24851 * Use of this source code is governed by an MIT-style license that can be
24852 * found in the LICENSE file at https://angular.io/license
24853 */
24854/**
24855 * Type of the Directive metadata.
24856 *
24857 * @publicApi
24858 */
24859const Directive = makeDecorator('Directive', (dir = {}) => dir, undefined, undefined, (type, meta) => SWITCH_COMPILE_DIRECTIVE(type, meta));
24860/**
24861 * Component decorator and metadata.
24862 *
24863 * @Annotation
24864 * @publicApi
24865 */
24866const Component = makeDecorator('Component', (c = {}) => ({ changeDetection: ChangeDetectionStrategy.Default, ...c }), Directive, undefined, (type, meta) => SWITCH_COMPILE_COMPONENT(type, meta));
24867/**
24868 * @Annotation
24869 * @publicApi
24870 */
24871const Pipe = makeDecorator('Pipe', (p) => ({ pure: true, ...p }), undefined, undefined, (type, meta) => SWITCH_COMPILE_PIPE(type, meta));
24872/**
24873 * @Annotation
24874 * @publicApi
24875 */
24876const Input = makePropDecorator('Input', (bindingPropertyName) => ({ bindingPropertyName }));
24877/**
24878 * @Annotation
24879 * @publicApi
24880 */
24881const Output = makePropDecorator('Output', (bindingPropertyName) => ({ bindingPropertyName }));
24882/**
24883 * @Annotation
24884 * @publicApi
24885 */
24886const HostBinding = makePropDecorator('HostBinding', (hostPropertyName) => ({ hostPropertyName }));
24887/**
24888 * Decorator that binds a DOM event to a host listener and supplies configuration metadata.
24889 * Angular invokes the supplied handler method when the host element emits the specified event,
24890 * and updates the bound element with the result.
24891 *
24892 * If the handler method returns false, applies `preventDefault` on the bound element.
24893 *
24894 * @usageNotes
24895 *
24896 * The following example declares a directive
24897 * that attaches a click listener to a button and counts clicks.
24898 *
24899 * ```ts
24900 * @Directive({selector: 'button[counting]'})
24901 * class CountClicks {
24902 * numberOfClicks = 0;
24903 *
24904 * @HostListener('click', ['$event.target'])
24905 * onClick(btn) {
24906 * console.log('button', btn, 'number of clicks:', this.numberOfClicks++);
24907 * }
24908 * }
24909 *
24910 * @Component({
24911 * selector: 'app',
24912 * template: '<button counting>Increment</button>',
24913 * })
24914 * class App {}
24915 *
24916 * ```
24917 *
24918 * The following example registers another DOM event handler that listens for key-press events.
24919 * ``` ts
24920 * import { HostListener, Component } from "@angular/core";
24921 *
24922 * @Component({
24923 * selector: 'app',
24924 * template: `<h1>Hello, you have pressed keys {{counter}} number of times!</h1> Press any key to
24925 * increment the counter.
24926 * <button (click)="resetCounter()">Reset Counter</button>`
24927 * })
24928 * class AppComponent {
24929 * counter = 0;
24930 * @HostListener('window:keydown', ['$event'])
24931 * handleKeyDown(event: KeyboardEvent) {
24932 * this.counter++;
24933 * }
24934 * resetCounter() {
24935 * this.counter = 0;
24936 * }
24937 * }
24938 * ```
24939 *
24940 * @Annotation
24941 * @publicApi
24942 */
24943const HostListener = makePropDecorator('HostListener', (eventName, args) => ({ eventName, args }));
24944const SWITCH_COMPILE_COMPONENT__POST_R3__ = compileComponent;
24945const SWITCH_COMPILE_DIRECTIVE__POST_R3__ = compileDirective;
24946const SWITCH_COMPILE_PIPE__POST_R3__ = compilePipe;
24947const SWITCH_COMPILE_COMPONENT__PRE_R3__ = noop;
24948const SWITCH_COMPILE_DIRECTIVE__PRE_R3__ = noop;
24949const SWITCH_COMPILE_PIPE__PRE_R3__ = noop;
24950const SWITCH_COMPILE_COMPONENT = SWITCH_COMPILE_COMPONENT__POST_R3__;
24951const SWITCH_COMPILE_DIRECTIVE = SWITCH_COMPILE_DIRECTIVE__POST_R3__;
24952const SWITCH_COMPILE_PIPE = SWITCH_COMPILE_PIPE__POST_R3__;
24953
24954/**
24955 * @license
24956 * Copyright Google LLC All Rights Reserved.
24957 *
24958 * Use of this source code is governed by an MIT-style license that can be
24959 * found in the LICENSE file at https://angular.io/license
24960 */
24961/**
24962 * @Annotation
24963 * @publicApi
24964 */
24965const NgModule = makeDecorator('NgModule', (ngModule) => ngModule, undefined, undefined,
24966/**
24967 * Decorator that marks the following class as an NgModule, and supplies
24968 * configuration metadata for it.
24969 *
24970 * * The `declarations` and `entryComponents` options configure the compiler
24971 * with information about what belongs to the NgModule.
24972 * * The `providers` options configures the NgModule's injector to provide
24973 * dependencies the NgModule members.
24974 * * The `imports` and `exports` options bring in members from other modules, and make
24975 * this module's members available to others.
24976 */
24977(type, meta) => SWITCH_COMPILE_NGMODULE(type, meta));
24978function preR3NgModuleCompile(moduleType, metadata) {
24979 let imports = (metadata && metadata.imports) || [];
24980 if (metadata && metadata.exports) {
24981 imports = [...imports, metadata.exports];
24982 }
24983 const moduleInjectorType = moduleType;
24984 moduleInjectorType.ɵfac = convertInjectableProviderToFactory(moduleType, { useClass: moduleType });
24985 moduleInjectorType.ɵinj =
24986 ɵɵdefineInjector({ providers: metadata && metadata.providers, imports: imports });
24987}
24988const SWITCH_COMPILE_NGMODULE__POST_R3__ = compileNgModule;
24989const SWITCH_COMPILE_NGMODULE__PRE_R3__ = preR3NgModuleCompile;
24990const SWITCH_COMPILE_NGMODULE = SWITCH_COMPILE_NGMODULE__POST_R3__;
24991
24992/**
24993 * @license
24994 * Copyright Google LLC All Rights Reserved.
24995 *
24996 * Use of this source code is governed by an MIT-style license that can be
24997 * found in the LICENSE file at https://angular.io/license
24998 */
24999
25000/**
25001 * @license
25002 * Copyright Google LLC All Rights Reserved.
25003 *
25004 * Use of this source code is governed by an MIT-style license that can be
25005 * found in the LICENSE file at https://angular.io/license
25006 */
25007
25008/**
25009 * @license
25010 * Copyright Google LLC All Rights Reserved.
25011 *
25012 * Use of this source code is governed by an MIT-style license that can be
25013 * found in the LICENSE file at https://angular.io/license
25014 */
25015/**
25016 * The existence of this constant (in this particular file) informs the Angular compiler that the
25017 * current program is actually @angular/core, which needs to be compiled specially.
25018 */
25019const ITS_JUST_ANGULAR = true;
25020
25021/**
25022 * A [DI token](guide/glossary#di-token "DI token definition") that you can use to provide
25023 * one or more initialization functions.
25024 *
25025 * The provided functions are injected at application startup and executed during
25026 * app initialization. If any of these functions returns a Promise or an Observable, initialization
25027 * does not complete until the Promise is resolved or the Observable is completed.
25028 *
25029 * You can, for example, create a factory function that loads language data
25030 * or an external configuration, and provide that function to the `APP_INITIALIZER` token.
25031 * The function is executed during the application bootstrap process,
25032 * and the needed data is available on startup.
25033 *
25034 * @see `ApplicationInitStatus`
25035 *
25036 * @usageNotes
25037 *
25038 * The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
25039 * and a function returning a promise.
25040 *
25041 * ```
25042 * function initializeApp(): Promise<any> {
25043 * return new Promise((resolve, reject) => {
25044 * // Do some asynchronous stuff
25045 * resolve();
25046 * });
25047 * }
25048 *
25049 * @NgModule({
25050 * imports: [BrowserModule],
25051 * declarations: [AppComponent],
25052 * bootstrap: [AppComponent],
25053 * providers: [{
25054 * provide: APP_INITIALIZER,
25055 * useFactory: () => initializeApp,
25056 * multi: true
25057 * }]
25058 * })
25059 * export class AppModule {}
25060 * ```
25061 *
25062 * It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
25063 * returning an observable, see an example below. Note: the `HttpClient` in this example is used for
25064 * demo purposes to illustrate how the factory function can work with other providers available
25065 * through DI.
25066 *
25067 * ```
25068 * function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
25069 * return () => httpClient.get("https://someUrl.com/api/user")
25070 * .pipe(
25071 * tap(user => { ... })
25072 * );
25073 * }
25074 *
25075 * @NgModule({
25076 * imports: [BrowserModule, HttpClientModule],
25077 * declarations: [AppComponent],
25078 * bootstrap: [AppComponent],
25079 * providers: [{
25080 * provide: APP_INITIALIZER,
25081 * useFactory: initializeAppFactory,
25082 * deps: [HttpClient],
25083 * multi: true
25084 * }]
25085 * })
25086 * export class AppModule {}
25087 * ```
25088 *
25089 * @publicApi
25090 */
25091const APP_INITIALIZER = new InjectionToken('Application Initializer');
25092/**
25093 * A class that reflects the state of running {@link APP_INITIALIZER} functions.
25094 *
25095 * @publicApi
25096 */
25097class ApplicationInitStatus {
25098 constructor(appInits) {
25099 this.appInits = appInits;
25100 this.resolve = noop;
25101 this.reject = noop;
25102 this.initialized = false;
25103 this.done = false;
25104 this.donePromise = new Promise((res, rej) => {
25105 this.resolve = res;
25106 this.reject = rej;
25107 });
25108 }
25109 /** @internal */
25110 runInitializers() {
25111 if (this.initialized) {
25112 return;
25113 }
25114 const asyncInitPromises = [];
25115 const complete = () => {
25116 this.done = true;
25117 this.resolve();
25118 };
25119 if (this.appInits) {
25120 for (let i = 0; i < this.appInits.length; i++) {
25121 const initResult = this.appInits[i]();
25122 if (isPromise(initResult)) {
25123 asyncInitPromises.push(initResult);
25124 }
25125 else if (isObservable(initResult)) {
25126 const observableAsPromise = new Promise((resolve, reject) => {
25127 initResult.subscribe({ complete: resolve, error: reject });
25128 });
25129 asyncInitPromises.push(observableAsPromise);
25130 }
25131 }
25132 }
25133 Promise.all(asyncInitPromises)
25134 .then(() => {
25135 complete();
25136 })
25137 .catch(e => {
25138 this.reject(e);
25139 });
25140 if (asyncInitPromises.length === 0) {
25141 complete();
25142 }
25143 this.initialized = true;
25144 }
25145}
25146ApplicationInitStatus.ɵfac = function ApplicationInitStatus_Factory(t) { return new (t || ApplicationInitStatus)(ɵɵinject(APP_INITIALIZER, 8)); };
25147ApplicationInitStatus.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationInitStatus, factory: ApplicationInitStatus.ɵfac });
25148(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationInitStatus, [{
25149 type: Injectable
25150 }], function () { return [{ type: undefined, decorators: [{
25151 type: Inject,
25152 args: [APP_INITIALIZER]
25153 }, {
25154 type: Optional
25155 }] }]; }, null); })();
25156
25157/**
25158 * @license
25159 * Copyright Google LLC All Rights Reserved.
25160 *
25161 * Use of this source code is governed by an MIT-style license that can be
25162 * found in the LICENSE file at https://angular.io/license
25163 */
25164/**
25165 * A [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used
25166 * primarily for prefixing application attributes and CSS styles when
25167 * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
25168 *
25169 * BY default, the value is randomly generated and assigned to the application by Angular.
25170 * To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure
25171 * the root {@link Injector} that uses this token.
25172 *
25173 * @publicApi
25174 */
25175const APP_ID = new InjectionToken('AppId');
25176function _appIdRandomProviderFactory() {
25177 return `${_randomChar()}${_randomChar()}${_randomChar()}`;
25178}
25179/**
25180 * Providers that generate a random `APP_ID_TOKEN`.
25181 * @publicApi
25182 */
25183const APP_ID_RANDOM_PROVIDER = {
25184 provide: APP_ID,
25185 useFactory: _appIdRandomProviderFactory,
25186 deps: [],
25187};
25188function _randomChar() {
25189 return String.fromCharCode(97 + Math.floor(Math.random() * 25));
25190}
25191/**
25192 * A function that is executed when a platform is initialized.
25193 * @publicApi
25194 */
25195const PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer');
25196/**
25197 * A token that indicates an opaque platform ID.
25198 * @publicApi
25199 */
25200const PLATFORM_ID = new InjectionToken('Platform ID');
25201/**
25202 * A [DI token](guide/glossary#di-token "DI token definition") that provides a set of callbacks to
25203 * be called for every component that is bootstrapped.
25204 *
25205 * Each callback must take a `ComponentRef` instance and return nothing.
25206 *
25207 * `(componentRef: ComponentRef) => void`
25208 *
25209 * @publicApi
25210 */
25211const APP_BOOTSTRAP_LISTENER = new InjectionToken('appBootstrapListener');
25212/**
25213 * A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of
25214 * the application
25215 * @publicApi
25216 */
25217const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
25218
25219/**
25220 * @license
25221 * Copyright Google LLC All Rights Reserved.
25222 *
25223 * Use of this source code is governed by an MIT-style license that can be
25224 * found in the LICENSE file at https://angular.io/license
25225 */
25226class Console {
25227 log(message) {
25228 // tslint:disable-next-line:no-console
25229 console.log(message);
25230 }
25231 // Note: for reporting errors use `DOM.logError()` as it is platform specific
25232 warn(message) {
25233 // tslint:disable-next-line:no-console
25234 console.warn(message);
25235 }
25236}
25237Console.ɵfac = function Console_Factory(t) { return new (t || Console)(); };
25238Console.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Console, factory: Console.ɵfac });
25239(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Console, [{
25240 type: Injectable
25241 }], null, null); })();
25242
25243/**
25244 * @license
25245 * Copyright Google LLC All Rights Reserved.
25246 *
25247 * Use of this source code is governed by an MIT-style license that can be
25248 * found in the LICENSE file at https://angular.io/license
25249 */
25250/**
25251 * Provide this token to set the locale of your application.
25252 * It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe,
25253 * DecimalPipe and PercentPipe) and by ICU expressions.
25254 *
25255 * See the [i18n guide](guide/i18n-common-locale-id) for more information.
25256 *
25257 * @usageNotes
25258 * ### Example
25259 *
25260 * ```typescript
25261 * import { LOCALE_ID } from '@angular/core';
25262 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25263 * import { AppModule } from './app/app.module';
25264 *
25265 * platformBrowserDynamic().bootstrapModule(AppModule, {
25266 * providers: [{provide: LOCALE_ID, useValue: 'en-US' }]
25267 * });
25268 * ```
25269 *
25270 * @publicApi
25271 */
25272const LOCALE_ID = new InjectionToken('LocaleId');
25273/**
25274 * Provide this token to set the default currency code your application uses for
25275 * CurrencyPipe when there is no currency code passed into it. This is only used by
25276 * CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured.
25277 *
25278 * See the [i18n guide](guide/i18n-common-locale-id) for more information.
25279 *
25280 * <div class="alert is-helpful">
25281 *
25282 * **Deprecation notice:**
25283 *
25284 * The default currency code is currently always `USD` but this is deprecated from v9.
25285 *
25286 * **In v10 the default currency code will be taken from the current locale.**
25287 *
25288 * If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in
25289 * your application `NgModule`:
25290 *
25291 * ```ts
25292 * {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}
25293 * ```
25294 *
25295 * </div>
25296 *
25297 * @usageNotes
25298 * ### Example
25299 *
25300 * ```typescript
25301 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25302 * import { AppModule } from './app/app.module';
25303 *
25304 * platformBrowserDynamic().bootstrapModule(AppModule, {
25305 * providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }]
25306 * });
25307 * ```
25308 *
25309 * @publicApi
25310 */
25311const DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode');
25312/**
25313 * Use this token at bootstrap to provide the content of your translation file (`xtb`,
25314 * `xlf` or `xlf2`) when you want to translate your application in another language.
25315 *
25316 * See the [i18n guide](guide/i18n-common-merge) for more information.
25317 *
25318 * @usageNotes
25319 * ### Example
25320 *
25321 * ```typescript
25322 * import { TRANSLATIONS } from '@angular/core';
25323 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25324 * import { AppModule } from './app/app.module';
25325 *
25326 * // content of your translation file
25327 * const translations = '....';
25328 *
25329 * platformBrowserDynamic().bootstrapModule(AppModule, {
25330 * providers: [{provide: TRANSLATIONS, useValue: translations }]
25331 * });
25332 * ```
25333 *
25334 * @publicApi
25335 */
25336const TRANSLATIONS = new InjectionToken('Translations');
25337/**
25338 * Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`,
25339 * `xlf` or `xlf2`.
25340 *
25341 * See the [i18n guide](guide/i18n-common-merge) for more information.
25342 *
25343 * @usageNotes
25344 * ### Example
25345 *
25346 * ```typescript
25347 * import { TRANSLATIONS_FORMAT } from '@angular/core';
25348 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25349 * import { AppModule } from './app/app.module';
25350 *
25351 * platformBrowserDynamic().bootstrapModule(AppModule, {
25352 * providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }]
25353 * });
25354 * ```
25355 *
25356 * @publicApi
25357 */
25358const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat');
25359/**
25360 * Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy
25361 * that the compiler should use in case of missing translations:
25362 * - Error: throw if you have missing translations.
25363 * - Warning (default): show a warning in the console and/or shell.
25364 * - Ignore: do nothing.
25365 *
25366 * See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information.
25367 *
25368 * @usageNotes
25369 * ### Example
25370 * ```typescript
25371 * import { MissingTranslationStrategy } from '@angular/core';
25372 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25373 * import { AppModule } from './app/app.module';
25374 *
25375 * platformBrowserDynamic().bootstrapModule(AppModule, {
25376 * missingTranslation: MissingTranslationStrategy.Error
25377 * });
25378 * ```
25379 *
25380 * @publicApi
25381 */
25382var MissingTranslationStrategy;
25383(function (MissingTranslationStrategy) {
25384 MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
25385 MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
25386 MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
25387})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
25388
25389/**
25390 * @license
25391 * Copyright Google LLC All Rights Reserved.
25392 *
25393 * Use of this source code is governed by an MIT-style license that can be
25394 * found in the LICENSE file at https://angular.io/license
25395 */
25396const SWITCH_IVY_ENABLED__POST_R3__ = true;
25397const SWITCH_IVY_ENABLED__PRE_R3__ = false;
25398const ivyEnabled = SWITCH_IVY_ENABLED__POST_R3__;
25399
25400/**
25401 * @license
25402 * Copyright Google LLC All Rights Reserved.
25403 *
25404 * Use of this source code is governed by an MIT-style license that can be
25405 * found in the LICENSE file at https://angular.io/license
25406 */
25407/**
25408 * Combination of NgModuleFactory and ComponentFactories.
25409 *
25410 * @publicApi
25411 *
25412 * @deprecated
25413 * Ivy JIT mode doesn't require accessing this symbol.
25414 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
25415 * additional context.
25416 */
25417class ModuleWithComponentFactories {
25418 constructor(ngModuleFactory, componentFactories) {
25419 this.ngModuleFactory = ngModuleFactory;
25420 this.componentFactories = componentFactories;
25421 }
25422}
25423function _throwError() {
25424 throw new Error(`Runtime compiler is not loaded`);
25425}
25426const Compiler_compileModuleSync__PRE_R3__ = _throwError;
25427const Compiler_compileModuleSync__POST_R3__ = function (moduleType) {
25428 return new NgModuleFactory(moduleType);
25429};
25430const Compiler_compileModuleSync = Compiler_compileModuleSync__POST_R3__;
25431const Compiler_compileModuleAsync__PRE_R3__ = _throwError;
25432const Compiler_compileModuleAsync__POST_R3__ = function (moduleType) {
25433 return Promise.resolve(Compiler_compileModuleSync__POST_R3__(moduleType));
25434};
25435const Compiler_compileModuleAsync = Compiler_compileModuleAsync__POST_R3__;
25436const Compiler_compileModuleAndAllComponentsSync__PRE_R3__ = _throwError;
25437const Compiler_compileModuleAndAllComponentsSync__POST_R3__ = function (moduleType) {
25438 const ngModuleFactory = Compiler_compileModuleSync__POST_R3__(moduleType);
25439 const moduleDef = getNgModuleDef(moduleType);
25440 const componentFactories = maybeUnwrapFn(moduleDef.declarations)
25441 .reduce((factories, declaration) => {
25442 const componentDef = getComponentDef(declaration);
25443 componentDef && factories.push(new ComponentFactory(componentDef));
25444 return factories;
25445 }, []);
25446 return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
25447};
25448const Compiler_compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync__POST_R3__;
25449const Compiler_compileModuleAndAllComponentsAsync__PRE_R3__ = _throwError;
25450const Compiler_compileModuleAndAllComponentsAsync__POST_R3__ = function (moduleType) {
25451 return Promise.resolve(Compiler_compileModuleAndAllComponentsSync__POST_R3__(moduleType));
25452};
25453const Compiler_compileModuleAndAllComponentsAsync = Compiler_compileModuleAndAllComponentsAsync__POST_R3__;
25454/**
25455 * Low-level service for running the angular compiler during runtime
25456 * to create {@link ComponentFactory}s, which
25457 * can later be used to create and render a Component instance.
25458 *
25459 * Each `@NgModule` provides an own `Compiler` to its injector,
25460 * that will use the directives/pipes of the ng module for compilation
25461 * of components.
25462 *
25463 * @publicApi
25464 *
25465 * @deprecated
25466 * Ivy JIT mode doesn't require accessing this symbol.
25467 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
25468 * additional context.
25469 */
25470class Compiler {
25471 constructor() {
25472 /**
25473 * Compiles the given NgModule and all of its components. All templates of the components listed
25474 * in `entryComponents` have to be inlined.
25475 */
25476 this.compileModuleSync = Compiler_compileModuleSync;
25477 /**
25478 * Compiles the given NgModule and all of its components
25479 */
25480 this.compileModuleAsync = Compiler_compileModuleAsync;
25481 /**
25482 * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
25483 */
25484 this.compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync;
25485 /**
25486 * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
25487 */
25488 this.compileModuleAndAllComponentsAsync = Compiler_compileModuleAndAllComponentsAsync;
25489 }
25490 /**
25491 * Clears all caches.
25492 */
25493 clearCache() { }
25494 /**
25495 * Clears the cache for the given component/ngModule.
25496 */
25497 clearCacheFor(type) { }
25498 /**
25499 * Returns the id for a given NgModule, if one is defined and known to the compiler.
25500 */
25501 getModuleId(moduleType) {
25502 return undefined;
25503 }
25504}
25505Compiler.ɵfac = function Compiler_Factory(t) { return new (t || Compiler)(); };
25506Compiler.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Compiler, factory: Compiler.ɵfac });
25507(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Compiler, [{
25508 type: Injectable
25509 }], null, null); })();
25510/**
25511 * Token to provide CompilerOptions in the platform injector.
25512 *
25513 * @publicApi
25514 */
25515const COMPILER_OPTIONS = new InjectionToken('compilerOptions');
25516/**
25517 * A factory for creating a Compiler
25518 *
25519 * @publicApi
25520 *
25521 * @deprecated
25522 * Ivy JIT mode doesn't require accessing this symbol.
25523 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
25524 * additional context.
25525 */
25526class CompilerFactory {
25527}
25528
25529/**
25530 * @license
25531 * Copyright Google LLC All Rights Reserved.
25532 *
25533 * Use of this source code is governed by an MIT-style license that can be
25534 * found in the LICENSE file at https://angular.io/license
25535 */
25536const promise = (() => Promise.resolve(0))();
25537function scheduleMicroTask(fn) {
25538 if (typeof Zone === 'undefined') {
25539 // use promise to schedule microTask instead of use Zone
25540 promise.then(() => {
25541 fn && fn.apply(null, null);
25542 });
25543 }
25544 else {
25545 Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
25546 }
25547}
25548
25549/**
25550 * @license
25551 * Copyright Google LLC All Rights Reserved.
25552 *
25553 * Use of this source code is governed by an MIT-style license that can be
25554 * found in the LICENSE file at https://angular.io/license
25555 */
25556function getNativeRequestAnimationFrame() {
25557 let nativeRequestAnimationFrame = _global['requestAnimationFrame'];
25558 let nativeCancelAnimationFrame = _global['cancelAnimationFrame'];
25559 if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
25560 // use unpatched version of requestAnimationFrame(native delegate) if possible
25561 // to avoid another Change detection
25562 const unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')];
25563 if (unpatchedRequestAnimationFrame) {
25564 nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
25565 }
25566 const unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')];
25567 if (unpatchedCancelAnimationFrame) {
25568 nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
25569 }
25570 }
25571 return { nativeRequestAnimationFrame, nativeCancelAnimationFrame };
25572}
25573
25574/**
25575 * @license
25576 * Copyright Google LLC All Rights Reserved.
25577 *
25578 * Use of this source code is governed by an MIT-style license that can be
25579 * found in the LICENSE file at https://angular.io/license
25580 */
25581/**
25582 * An injectable service for executing work inside or outside of the Angular zone.
25583 *
25584 * The most common use of this service is to optimize performance when starting a work consisting of
25585 * one or more asynchronous tasks that don't require UI updates or error handling to be handled by
25586 * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks
25587 * can reenter the Angular zone via {@link #run}.
25588 *
25589 * <!-- TODO: add/fix links to:
25590 * - docs explaining zones and the use of zones in Angular and change-detection
25591 * - link to runOutsideAngular/run (throughout this file!)
25592 * -->
25593 *
25594 * @usageNotes
25595 * ### Example
25596 *
25597 * ```
25598 * import {Component, NgZone} from '@angular/core';
25599 * import {NgIf} from '@angular/common';
25600 *
25601 * @Component({
25602 * selector: 'ng-zone-demo',
25603 * template: `
25604 * <h2>Demo: NgZone</h2>
25605 *
25606 * <p>Progress: {{progress}}%</p>
25607 * <p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p>
25608 *
25609 * <button (click)="processWithinAngularZone()">Process within Angular zone</button>
25610 * <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
25611 * `,
25612 * })
25613 * export class NgZoneDemo {
25614 * progress: number = 0;
25615 * label: string;
25616 *
25617 * constructor(private _ngZone: NgZone) {}
25618 *
25619 * // Loop inside the Angular zone
25620 * // so the UI DOES refresh after each setTimeout cycle
25621 * processWithinAngularZone() {
25622 * this.label = 'inside';
25623 * this.progress = 0;
25624 * this._increaseProgress(() => console.log('Inside Done!'));
25625 * }
25626 *
25627 * // Loop outside of the Angular zone
25628 * // so the UI DOES NOT refresh after each setTimeout cycle
25629 * processOutsideOfAngularZone() {
25630 * this.label = 'outside';
25631 * this.progress = 0;
25632 * this._ngZone.runOutsideAngular(() => {
25633 * this._increaseProgress(() => {
25634 * // reenter the Angular zone and display done
25635 * this._ngZone.run(() => { console.log('Outside Done!'); });
25636 * });
25637 * });
25638 * }
25639 *
25640 * _increaseProgress(doneCallback: () => void) {
25641 * this.progress += 1;
25642 * console.log(`Current progress: ${this.progress}%`);
25643 *
25644 * if (this.progress < 100) {
25645 * window.setTimeout(() => this._increaseProgress(doneCallback), 10);
25646 * } else {
25647 * doneCallback();
25648 * }
25649 * }
25650 * }
25651 * ```
25652 *
25653 * @publicApi
25654 */
25655class NgZone {
25656 constructor({ enableLongStackTrace = false, shouldCoalesceEventChangeDetection = false, shouldCoalesceRunChangeDetection = false }) {
25657 this.hasPendingMacrotasks = false;
25658 this.hasPendingMicrotasks = false;
25659 /**
25660 * Whether there are no outstanding microtasks or macrotasks.
25661 */
25662 this.isStable = true;
25663 /**
25664 * Notifies when code enters Angular Zone. This gets fired first on VM Turn.
25665 */
25666 this.onUnstable = new EventEmitter(false);
25667 /**
25668 * Notifies when there is no more microtasks enqueued in the current VM Turn.
25669 * This is a hint for Angular to do change detection, which may enqueue more microtasks.
25670 * For this reason this event can fire multiple times per VM Turn.
25671 */
25672 this.onMicrotaskEmpty = new EventEmitter(false);
25673 /**
25674 * Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
25675 * implies we are about to relinquish VM turn.
25676 * This event gets called just once.
25677 */
25678 this.onStable = new EventEmitter(false);
25679 /**
25680 * Notifies that an error has been delivered.
25681 */
25682 this.onError = new EventEmitter(false);
25683 if (typeof Zone == 'undefined') {
25684 throw new Error(`In this configuration Angular requires Zone.js`);
25685 }
25686 Zone.assertZonePatched();
25687 const self = this;
25688 self._nesting = 0;
25689 self._outer = self._inner = Zone.current;
25690 if (Zone['TaskTrackingZoneSpec']) {
25691 self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']);
25692 }
25693 if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
25694 self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
25695 }
25696 // if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be
25697 // coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.
25698 self.shouldCoalesceEventChangeDetection =
25699 !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
25700 self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
25701 self.lastRequestAnimationFrameId = -1;
25702 self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
25703 forkInnerZoneWithAngularBehavior(self);
25704 }
25705 static isInAngularZone() {
25706 return Zone.current.get('isAngularZone') === true;
25707 }
25708 static assertInAngularZone() {
25709 if (!NgZone.isInAngularZone()) {
25710 throw new Error('Expected to be in Angular Zone, but it is not!');
25711 }
25712 }
25713 static assertNotInAngularZone() {
25714 if (NgZone.isInAngularZone()) {
25715 throw new Error('Expected to not be in Angular Zone, but it is!');
25716 }
25717 }
25718 /**
25719 * Executes the `fn` function synchronously within the Angular zone and returns value returned by
25720 * the function.
25721 *
25722 * Running functions via `run` allows you to reenter Angular zone from a task that was executed
25723 * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
25724 *
25725 * Any future tasks or microtasks scheduled from within this function will continue executing from
25726 * within the Angular zone.
25727 *
25728 * If a synchronous error happens it will be rethrown and not reported via `onError`.
25729 */
25730 run(fn, applyThis, applyArgs) {
25731 return this._inner.run(fn, applyThis, applyArgs);
25732 }
25733 /**
25734 * Executes the `fn` function synchronously within the Angular zone as a task and returns value
25735 * returned by the function.
25736 *
25737 * Running functions via `run` allows you to reenter Angular zone from a task that was executed
25738 * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
25739 *
25740 * Any future tasks or microtasks scheduled from within this function will continue executing from
25741 * within the Angular zone.
25742 *
25743 * If a synchronous error happens it will be rethrown and not reported via `onError`.
25744 */
25745 runTask(fn, applyThis, applyArgs, name) {
25746 const zone = this._inner;
25747 const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);
25748 try {
25749 return zone.runTask(task, applyThis, applyArgs);
25750 }
25751 finally {
25752 zone.cancelTask(task);
25753 }
25754 }
25755 /**
25756 * Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
25757 * rethrown.
25758 */
25759 runGuarded(fn, applyThis, applyArgs) {
25760 return this._inner.runGuarded(fn, applyThis, applyArgs);
25761 }
25762 /**
25763 * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
25764 * the function.
25765 *
25766 * Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do
25767 * work that
25768 * doesn't trigger Angular change-detection or is subject to Angular's error handling.
25769 *
25770 * Any future tasks or microtasks scheduled from within this function will continue executing from
25771 * outside of the Angular zone.
25772 *
25773 * Use {@link #run} to reenter the Angular zone and do work that updates the application model.
25774 */
25775 runOutsideAngular(fn) {
25776 return this._outer.run(fn);
25777 }
25778}
25779const EMPTY_PAYLOAD = {};
25780function checkStable(zone) {
25781 // TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent
25782 // re-entry. The case is:
25783 //
25784 // @Component({...})
25785 // export class AppComponent {
25786 // constructor(private ngZone: NgZone) {
25787 // this.ngZone.onStable.subscribe(() => {
25788 // this.ngZone.run(() => console.log('stable'););
25789 // });
25790 // }
25791 //
25792 // The onStable subscriber run another function inside ngZone
25793 // which causes `checkStable()` re-entry.
25794 // But this fix causes some issues in g3, so this fix will be
25795 // launched in another PR.
25796 if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
25797 try {
25798 zone._nesting++;
25799 zone.onMicrotaskEmpty.emit(null);
25800 }
25801 finally {
25802 zone._nesting--;
25803 if (!zone.hasPendingMicrotasks) {
25804 try {
25805 zone.runOutsideAngular(() => zone.onStable.emit(null));
25806 }
25807 finally {
25808 zone.isStable = true;
25809 }
25810 }
25811 }
25812 }
25813}
25814function delayChangeDetectionForEvents(zone) {
25815 /**
25816 * We also need to check _nesting here
25817 * Consider the following case with shouldCoalesceRunChangeDetection = true
25818 *
25819 * ngZone.run(() => {});
25820 * ngZone.run(() => {});
25821 *
25822 * We want the two `ngZone.run()` only trigger one change detection
25823 * when shouldCoalesceRunChangeDetection is true.
25824 * And because in this case, change detection run in async way(requestAnimationFrame),
25825 * so we also need to check the _nesting here to prevent multiple
25826 * change detections.
25827 */
25828 if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
25829 return;
25830 }
25831 zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => {
25832 // This is a work around for https://github.com/angular/angular/issues/36839.
25833 // The core issue is that when event coalescing is enabled it is possible for microtasks
25834 // to get flushed too early (As is the case with `Promise.then`) between the
25835 // coalescing eventTasks.
25836 //
25837 // To workaround this we schedule a "fake" eventTask before we process the
25838 // coalescing eventTasks. The benefit of this is that the "fake" container eventTask
25839 // will prevent the microtasks queue from getting drained in between the coalescing
25840 // eventTask execution.
25841 if (!zone.fakeTopEventTask) {
25842 zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
25843 zone.lastRequestAnimationFrameId = -1;
25844 updateMicroTaskStatus(zone);
25845 zone.isCheckStableRunning = true;
25846 checkStable(zone);
25847 zone.isCheckStableRunning = false;
25848 }, undefined, () => { }, () => { });
25849 }
25850 zone.fakeTopEventTask.invoke();
25851 });
25852 updateMicroTaskStatus(zone);
25853}
25854function forkInnerZoneWithAngularBehavior(zone) {
25855 const delayChangeDetectionForEventsDelegate = () => {
25856 delayChangeDetectionForEvents(zone);
25857 };
25858 zone._inner = zone._inner.fork({
25859 name: 'angular',
25860 properties: { 'isAngularZone': true },
25861 onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
25862 try {
25863 onEnter(zone);
25864 return delegate.invokeTask(target, task, applyThis, applyArgs);
25865 }
25866 finally {
25867 if ((zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask') ||
25868 zone.shouldCoalesceRunChangeDetection) {
25869 delayChangeDetectionForEventsDelegate();
25870 }
25871 onLeave(zone);
25872 }
25873 },
25874 onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => {
25875 try {
25876 onEnter(zone);
25877 return delegate.invoke(target, callback, applyThis, applyArgs, source);
25878 }
25879 finally {
25880 if (zone.shouldCoalesceRunChangeDetection) {
25881 delayChangeDetectionForEventsDelegate();
25882 }
25883 onLeave(zone);
25884 }
25885 },
25886 onHasTask: (delegate, current, target, hasTaskState) => {
25887 delegate.hasTask(target, hasTaskState);
25888 if (current === target) {
25889 // We are only interested in hasTask events which originate from our zone
25890 // (A child hasTask event is not interesting to us)
25891 if (hasTaskState.change == 'microTask') {
25892 zone._hasPendingMicrotasks = hasTaskState.microTask;
25893 updateMicroTaskStatus(zone);
25894 checkStable(zone);
25895 }
25896 else if (hasTaskState.change == 'macroTask') {
25897 zone.hasPendingMacrotasks = hasTaskState.macroTask;
25898 }
25899 }
25900 },
25901 onHandleError: (delegate, current, target, error) => {
25902 delegate.handleError(target, error);
25903 zone.runOutsideAngular(() => zone.onError.emit(error));
25904 return false;
25905 }
25906 });
25907}
25908function updateMicroTaskStatus(zone) {
25909 if (zone._hasPendingMicrotasks ||
25910 ((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&
25911 zone.lastRequestAnimationFrameId !== -1)) {
25912 zone.hasPendingMicrotasks = true;
25913 }
25914 else {
25915 zone.hasPendingMicrotasks = false;
25916 }
25917}
25918function onEnter(zone) {
25919 zone._nesting++;
25920 if (zone.isStable) {
25921 zone.isStable = false;
25922 zone.onUnstable.emit(null);
25923 }
25924}
25925function onLeave(zone) {
25926 zone._nesting--;
25927 checkStable(zone);
25928}
25929/**
25930 * Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls
25931 * to framework to perform rendering.
25932 */
25933class NoopNgZone {
25934 constructor() {
25935 this.hasPendingMicrotasks = false;
25936 this.hasPendingMacrotasks = false;
25937 this.isStable = true;
25938 this.onUnstable = new EventEmitter();
25939 this.onMicrotaskEmpty = new EventEmitter();
25940 this.onStable = new EventEmitter();
25941 this.onError = new EventEmitter();
25942 }
25943 run(fn, applyThis, applyArgs) {
25944 return fn.apply(applyThis, applyArgs);
25945 }
25946 runGuarded(fn, applyThis, applyArgs) {
25947 return fn.apply(applyThis, applyArgs);
25948 }
25949 runOutsideAngular(fn) {
25950 return fn();
25951 }
25952 runTask(fn, applyThis, applyArgs, name) {
25953 return fn.apply(applyThis, applyArgs);
25954 }
25955}
25956
25957/**
25958 * @license
25959 * Copyright Google LLC All Rights Reserved.
25960 *
25961 * Use of this source code is governed by an MIT-style license that can be
25962 * found in the LICENSE file at https://angular.io/license
25963 */
25964/**
25965 * The Testability service provides testing hooks that can be accessed from
25966 * the browser. Each bootstrapped Angular application on the page will have
25967 * an instance of Testability.
25968 * @publicApi
25969 */
25970class Testability {
25971 constructor(_ngZone) {
25972 this._ngZone = _ngZone;
25973 this._pendingCount = 0;
25974 this._isZoneStable = true;
25975 /**
25976 * Whether any work was done since the last 'whenStable' callback. This is
25977 * useful to detect if this could have potentially destabilized another
25978 * component while it is stabilizing.
25979 * @internal
25980 */
25981 this._didWork = false;
25982 this._callbacks = [];
25983 this.taskTrackingZone = null;
25984 this._watchAngularEvents();
25985 _ngZone.run(() => {
25986 this.taskTrackingZone =
25987 typeof Zone == 'undefined' ? null : Zone.current.get('TaskTrackingZone');
25988 });
25989 }
25990 _watchAngularEvents() {
25991 this._ngZone.onUnstable.subscribe({
25992 next: () => {
25993 this._didWork = true;
25994 this._isZoneStable = false;
25995 }
25996 });
25997 this._ngZone.runOutsideAngular(() => {
25998 this._ngZone.onStable.subscribe({
25999 next: () => {
26000 NgZone.assertNotInAngularZone();
26001 scheduleMicroTask(() => {
26002 this._isZoneStable = true;
26003 this._runCallbacksIfReady();
26004 });
26005 }
26006 });
26007 });
26008 }
26009 /**
26010 * Increases the number of pending request
26011 * @deprecated pending requests are now tracked with zones.
26012 */
26013 increasePendingRequestCount() {
26014 this._pendingCount += 1;
26015 this._didWork = true;
26016 return this._pendingCount;
26017 }
26018 /**
26019 * Decreases the number of pending request
26020 * @deprecated pending requests are now tracked with zones
26021 */
26022 decreasePendingRequestCount() {
26023 this._pendingCount -= 1;
26024 if (this._pendingCount < 0) {
26025 throw new Error('pending async requests below zero');
26026 }
26027 this._runCallbacksIfReady();
26028 return this._pendingCount;
26029 }
26030 /**
26031 * Whether an associated application is stable
26032 */
26033 isStable() {
26034 return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks;
26035 }
26036 _runCallbacksIfReady() {
26037 if (this.isStable()) {
26038 // Schedules the call backs in a new frame so that it is always async.
26039 scheduleMicroTask(() => {
26040 while (this._callbacks.length !== 0) {
26041 let cb = this._callbacks.pop();
26042 clearTimeout(cb.timeoutId);
26043 cb.doneCb(this._didWork);
26044 }
26045 this._didWork = false;
26046 });
26047 }
26048 else {
26049 // Still not stable, send updates.
26050 let pending = this.getPendingTasks();
26051 this._callbacks = this._callbacks.filter((cb) => {
26052 if (cb.updateCb && cb.updateCb(pending)) {
26053 clearTimeout(cb.timeoutId);
26054 return false;
26055 }
26056 return true;
26057 });
26058 this._didWork = true;
26059 }
26060 }
26061 getPendingTasks() {
26062 if (!this.taskTrackingZone) {
26063 return [];
26064 }
26065 // Copy the tasks data so that we don't leak tasks.
26066 return this.taskTrackingZone.macroTasks.map((t) => {
26067 return {
26068 source: t.source,
26069 // From TaskTrackingZone:
26070 // https://github.com/angular/zone.js/blob/master/lib/zone-spec/task-tracking.ts#L40
26071 creationLocation: t.creationLocation,
26072 data: t.data
26073 };
26074 });
26075 }
26076 addCallback(cb, timeout, updateCb) {
26077 let timeoutId = -1;
26078 if (timeout && timeout > 0) {
26079 timeoutId = setTimeout(() => {
26080 this._callbacks = this._callbacks.filter((cb) => cb.timeoutId !== timeoutId);
26081 cb(this._didWork, this.getPendingTasks());
26082 }, timeout);
26083 }
26084 this._callbacks.push({ doneCb: cb, timeoutId: timeoutId, updateCb: updateCb });
26085 }
26086 /**
26087 * Wait for the application to be stable with a timeout. If the timeout is reached before that
26088 * happens, the callback receives a list of the macro tasks that were pending, otherwise null.
26089 *
26090 * @param doneCb The callback to invoke when Angular is stable or the timeout expires
26091 * whichever comes first.
26092 * @param timeout Optional. The maximum time to wait for Angular to become stable. If not
26093 * specified, whenStable() will wait forever.
26094 * @param updateCb Optional. If specified, this callback will be invoked whenever the set of
26095 * pending macrotasks changes. If this callback returns true doneCb will not be invoked
26096 * and no further updates will be issued.
26097 */
26098 whenStable(doneCb, timeout, updateCb) {
26099 if (updateCb && !this.taskTrackingZone) {
26100 throw new Error('Task tracking zone is required when passing an update callback to ' +
26101 'whenStable(). Is "zone.js/plugins/task-tracking" loaded?');
26102 }
26103 // These arguments are 'Function' above to keep the public API simple.
26104 this.addCallback(doneCb, timeout, updateCb);
26105 this._runCallbacksIfReady();
26106 }
26107 /**
26108 * Get the number of pending requests
26109 * @deprecated pending requests are now tracked with zones
26110 */
26111 getPendingRequestCount() {
26112 return this._pendingCount;
26113 }
26114 /**
26115 * Find providers by name
26116 * @param using The root element to search from
26117 * @param provider The name of binding variable
26118 * @param exactMatch Whether using exactMatch
26119 */
26120 findProviders(using, provider, exactMatch) {
26121 // TODO(juliemr): implement.
26122 return [];
26123 }
26124}
26125Testability.ɵfac = function Testability_Factory(t) { return new (t || Testability)(ɵɵinject(NgZone)); };
26126Testability.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Testability, factory: Testability.ɵfac });
26127(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Testability, [{
26128 type: Injectable
26129 }], function () { return [{ type: NgZone }]; }, null); })();
26130/**
26131 * A global registry of {@link Testability} instances for specific elements.
26132 * @publicApi
26133 */
26134class TestabilityRegistry {
26135 constructor() {
26136 /** @internal */
26137 this._applications = new Map();
26138 _testabilityGetter.addToWindow(this);
26139 }
26140 /**
26141 * Registers an application with a testability hook so that it can be tracked
26142 * @param token token of application, root element
26143 * @param testability Testability hook
26144 */
26145 registerApplication(token, testability) {
26146 this._applications.set(token, testability);
26147 }
26148 /**
26149 * Unregisters an application.
26150 * @param token token of application, root element
26151 */
26152 unregisterApplication(token) {
26153 this._applications.delete(token);
26154 }
26155 /**
26156 * Unregisters all applications
26157 */
26158 unregisterAllApplications() {
26159 this._applications.clear();
26160 }
26161 /**
26162 * Get a testability hook associated with the application
26163 * @param elem root element
26164 */
26165 getTestability(elem) {
26166 return this._applications.get(elem) || null;
26167 }
26168 /**
26169 * Get all registered testabilities
26170 */
26171 getAllTestabilities() {
26172 return Array.from(this._applications.values());
26173 }
26174 /**
26175 * Get all registered applications(root elements)
26176 */
26177 getAllRootElements() {
26178 return Array.from(this._applications.keys());
26179 }
26180 /**
26181 * Find testability of a node in the Tree
26182 * @param elem node
26183 * @param findInAncestors whether finding testability in ancestors if testability was not found in
26184 * current node
26185 */
26186 findTestabilityInTree(elem, findInAncestors = true) {
26187 return _testabilityGetter.findTestabilityInTree(this, elem, findInAncestors);
26188 }
26189}
26190TestabilityRegistry.ɵfac = function TestabilityRegistry_Factory(t) { return new (t || TestabilityRegistry)(); };
26191TestabilityRegistry.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: TestabilityRegistry, factory: TestabilityRegistry.ɵfac });
26192(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TestabilityRegistry, [{
26193 type: Injectable
26194 }], function () { return []; }, null); })();
26195class _NoopGetTestability {
26196 addToWindow(registry) { }
26197 findTestabilityInTree(registry, elem, findInAncestors) {
26198 return null;
26199 }
26200}
26201/**
26202 * Set the {@link GetTestability} implementation used by the Angular testing framework.
26203 * @publicApi
26204 */
26205function setTestabilityGetter(getter) {
26206 _testabilityGetter = getter;
26207}
26208let _testabilityGetter = new _NoopGetTestability();
26209
26210/**
26211 * @license
26212 * Copyright Google LLC All Rights Reserved.
26213 *
26214 * Use of this source code is governed by an MIT-style license that can be
26215 * found in the LICENSE file at https://angular.io/license
26216 */
26217/**
26218 * This file is used to control if the default rendering pipeline should be `ViewEngine` or `Ivy`.
26219 *
26220 * For more information on how to run and debug tests with either Ivy or View Engine (legacy),
26221 * please see [BAZEL.md](./docs/BAZEL.md).
26222 */
26223let _devMode = true;
26224let _runModeLocked = false;
26225/**
26226 * Returns whether Angular is in development mode. After called once,
26227 * the value is locked and won't change any more.
26228 *
26229 * By default, this is true, unless a user calls `enableProdMode` before calling this.
26230 *
26231 * @publicApi
26232 */
26233function isDevMode() {
26234 _runModeLocked = true;
26235 return _devMode;
26236}
26237/**
26238 * Disable Angular's development mode, which turns off assertions and other
26239 * checks within the framework.
26240 *
26241 * One important assertion this disables verifies that a change detection pass
26242 * does not result in additional changes to any bindings (also known as
26243 * unidirectional data flow).
26244 *
26245 * @publicApi
26246 */
26247function enableProdMode() {
26248 if (_runModeLocked) {
26249 throw new Error('Cannot enable prod mode after platform setup.');
26250 }
26251 // The below check is there so when ngDevMode is set via terser
26252 // `global['ngDevMode'] = false;` is also dropped.
26253 if (typeof ngDevMode === undefined || !!ngDevMode) {
26254 _global['ngDevMode'] = false;
26255 }
26256 _devMode = false;
26257}
26258
26259/**
26260 * @license
26261 * Copyright Google LLC All Rights Reserved.
26262 *
26263 * Use of this source code is governed by an MIT-style license that can be
26264 * found in the LICENSE file at https://angular.io/license
26265 */
26266let _platform;
26267let compileNgModuleFactory = compileNgModuleFactory__POST_R3__;
26268function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
26269 const compilerFactory = injector.get(CompilerFactory);
26270 const compiler = compilerFactory.createCompiler([options]);
26271 return compiler.compileModuleAsync(moduleType);
26272}
26273function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
26274 ngDevMode && assertNgModuleType(moduleType);
26275 const moduleFactory = new NgModuleFactory(moduleType);
26276 // All of the logic below is irrelevant for AOT-compiled code.
26277 if (typeof ngJitMode !== 'undefined' && !ngJitMode) {
26278 return Promise.resolve(moduleFactory);
26279 }
26280 const compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options);
26281 // Configure the compiler to use the provided options. This call may fail when multiple modules
26282 // are bootstrapped with incompatible options, as a component can only be compiled according to
26283 // a single set of options.
26284 setJitOptions({
26285 defaultEncapsulation: _lastDefined(compilerOptions.map(opts => opts.defaultEncapsulation)),
26286 preserveWhitespaces: _lastDefined(compilerOptions.map(opts => opts.preserveWhitespaces)),
26287 });
26288 if (isComponentResourceResolutionQueueEmpty()) {
26289 return Promise.resolve(moduleFactory);
26290 }
26291 const compilerProviders = _mergeArrays(compilerOptions.map(o => o.providers));
26292 // In case there are no compiler providers, we just return the module factory as
26293 // there won't be any resource loader. This can happen with Ivy, because AOT compiled
26294 // modules can be still passed through "bootstrapModule". In that case we shouldn't
26295 // unnecessarily require the JIT compiler.
26296 if (compilerProviders.length === 0) {
26297 return Promise.resolve(moduleFactory);
26298 }
26299 const compiler = getCompilerFacade({
26300 usage: 0 /* Decorator */,
26301 kind: 'NgModule',
26302 type: moduleType,
26303 });
26304 const compilerInjector = Injector.create({ providers: compilerProviders });
26305 const resourceLoader = compilerInjector.get(compiler.ResourceLoader);
26306 // The resource loader can also return a string while the "resolveComponentResources"
26307 // always expects a promise. Therefore we need to wrap the returned value in a promise.
26308 return resolveComponentResources(url => Promise.resolve(resourceLoader.get(url)))
26309 .then(() => moduleFactory);
26310}
26311// the `window.ng` global utilities are only available in non-VE versions of
26312// Angular. The function switch below will make sure that the code is not
26313// included into Angular when PRE mode is active.
26314function publishDefaultGlobalUtils__PRE_R3__() { }
26315function publishDefaultGlobalUtils__POST_R3__() {
26316 ngDevMode && publishDefaultGlobalUtils$1();
26317}
26318let publishDefaultGlobalUtils = publishDefaultGlobalUtils__POST_R3__;
26319let isBoundToModule = isBoundToModule__POST_R3__;
26320function isBoundToModule__PRE_R3__(cf) {
26321 return cf instanceof ComponentFactoryBoundToModule;
26322}
26323function isBoundToModule__POST_R3__(cf) {
26324 return cf.isBoundToModule;
26325}
26326const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken');
26327/**
26328 * A token for third-party components that can register themselves with NgProbe.
26329 *
26330 * @publicApi
26331 */
26332class NgProbeToken {
26333 constructor(name, token) {
26334 this.name = name;
26335 this.token = token;
26336 }
26337}
26338/**
26339 * Creates a platform.
26340 * Platforms must be created on launch using this function.
26341 *
26342 * @publicApi
26343 */
26344function createPlatform(injector) {
26345 if (_platform && !_platform.destroyed &&
26346 !_platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
26347 throw new Error('There can be only one platform. Destroy the previous one to create a new one.');
26348 }
26349 publishDefaultGlobalUtils();
26350 _platform = injector.get(PlatformRef);
26351 const inits = injector.get(PLATFORM_INITIALIZER, null);
26352 if (inits)
26353 inits.forEach((init) => init());
26354 return _platform;
26355}
26356/**
26357 * Creates a factory for a platform. Can be used to provide or override `Providers` specific to
26358 * your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
26359 * @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
26360 * to build up configurations that might be required by different libraries or parts of the
26361 * application.
26362 * @param name Identifies the new platform factory.
26363 * @param providers A set of dependency providers for platforms created with the new factory.
26364 *
26365 * @publicApi
26366 */
26367function createPlatformFactory(parentPlatformFactory, name, providers = []) {
26368 const desc = `Platform: ${name}`;
26369 const marker = new InjectionToken(desc);
26370 return (extraProviders = []) => {
26371 let platform = getPlatform();
26372 if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
26373 if (parentPlatformFactory) {
26374 parentPlatformFactory(providers.concat(extraProviders).concat({ provide: marker, useValue: true }));
26375 }
26376 else {
26377 const injectedProviders = providers.concat(extraProviders).concat({ provide: marker, useValue: true }, {
26378 provide: INJECTOR_SCOPE,
26379 useValue: 'platform'
26380 });
26381 createPlatform(Injector.create({ providers: injectedProviders, name: desc }));
26382 }
26383 }
26384 return assertPlatform(marker);
26385 };
26386}
26387/**
26388 * Checks that there is currently a platform that contains the given token as a provider.
26389 *
26390 * @publicApi
26391 */
26392function assertPlatform(requiredToken) {
26393 const platform = getPlatform();
26394 if (!platform) {
26395 throw new Error('No platform exists!');
26396 }
26397 if (!platform.injector.get(requiredToken, null)) {
26398 throw new Error('A platform with a different configuration has been created. Please destroy it first.');
26399 }
26400 return platform;
26401}
26402/**
26403 * Destroys the current Angular platform and all Angular applications on the page.
26404 * Destroys all modules and listeners registered with the platform.
26405 *
26406 * @publicApi
26407 */
26408function destroyPlatform() {
26409 if (_platform && !_platform.destroyed) {
26410 _platform.destroy();
26411 }
26412}
26413/**
26414 * Returns the current platform.
26415 *
26416 * @publicApi
26417 */
26418function getPlatform() {
26419 return _platform && !_platform.destroyed ? _platform : null;
26420}
26421/**
26422 * The Angular platform is the entry point for Angular on a web page.
26423 * Each page has exactly one platform. Services (such as reflection) which are common
26424 * to every Angular application running on the page are bound in its scope.
26425 * A page's platform is initialized implicitly when a platform is created using a platform
26426 * factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.
26427 *
26428 * @publicApi
26429 */
26430class PlatformRef {
26431 /** @internal */
26432 constructor(_injector) {
26433 this._injector = _injector;
26434 this._modules = [];
26435 this._destroyListeners = [];
26436 this._destroyed = false;
26437 }
26438 /**
26439 * Creates an instance of an `@NgModule` for the given platform for offline compilation.
26440 *
26441 * @usageNotes
26442 *
26443 * The following example creates the NgModule for a browser platform.
26444 *
26445 * ```typescript
26446 * my_module.ts:
26447 *
26448 * @NgModule({
26449 * imports: [BrowserModule]
26450 * })
26451 * class MyModule {}
26452 *
26453 * main.ts:
26454 * import {MyModuleNgFactory} from './my_module.ngfactory';
26455 * import {platformBrowser} from '@angular/platform-browser';
26456 *
26457 * let moduleRef = platformBrowser().bootstrapModuleFactory(MyModuleNgFactory);
26458 * ```
26459 *
26460 * @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function
26461 * argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.
26462 */
26463 bootstrapModuleFactory(moduleFactory, options) {
26464 // Note: We need to create the NgZone _before_ we instantiate the module,
26465 // as instantiating the module creates some providers eagerly.
26466 // So we create a mini parent injector that just contains the new NgZone and
26467 // pass that as parent to the NgModuleFactory.
26468 const ngZoneOption = options ? options.ngZone : undefined;
26469 const ngZoneEventCoalescing = (options && options.ngZoneEventCoalescing) || false;
26470 const ngZoneRunCoalescing = (options && options.ngZoneRunCoalescing) || false;
26471 const ngZone = getNgZone(ngZoneOption, { ngZoneEventCoalescing, ngZoneRunCoalescing });
26472 const providers = [{ provide: NgZone, useValue: ngZone }];
26473 // Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
26474 // created within the Angular zone
26475 // Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
26476 // created outside of the Angular zone.
26477 return ngZone.run(() => {
26478 const ngZoneInjector = Injector.create({ providers: providers, parent: this.injector, name: moduleFactory.moduleType.name });
26479 const moduleRef = moduleFactory.create(ngZoneInjector);
26480 const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
26481 if (!exceptionHandler) {
26482 throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?');
26483 }
26484 ngZone.runOutsideAngular(() => {
26485 const subscription = ngZone.onError.subscribe({
26486 next: (error) => {
26487 exceptionHandler.handleError(error);
26488 }
26489 });
26490 moduleRef.onDestroy(() => {
26491 remove(this._modules, moduleRef);
26492 subscription.unsubscribe();
26493 });
26494 });
26495 return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
26496 const initStatus = moduleRef.injector.get(ApplicationInitStatus);
26497 initStatus.runInitializers();
26498 return initStatus.donePromise.then(() => {
26499 if (ivyEnabled) {
26500 // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
26501 const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
26502 setLocaleId(localeId || DEFAULT_LOCALE_ID);
26503 }
26504 this._moduleDoBootstrap(moduleRef);
26505 return moduleRef;
26506 });
26507 });
26508 });
26509 }
26510 /**
26511 * Creates an instance of an `@NgModule` for a given platform using the given runtime compiler.
26512 *
26513 * @usageNotes
26514 * ### Simple Example
26515 *
26516 * ```typescript
26517 * @NgModule({
26518 * imports: [BrowserModule]
26519 * })
26520 * class MyModule {}
26521 *
26522 * let moduleRef = platformBrowser().bootstrapModule(MyModule);
26523 * ```
26524 *
26525 */
26526 bootstrapModule(moduleType, compilerOptions = []) {
26527 const options = optionsReducer({}, compilerOptions);
26528 return compileNgModuleFactory(this.injector, options, moduleType)
26529 .then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
26530 }
26531 _moduleDoBootstrap(moduleRef) {
26532 const appRef = moduleRef.injector.get(ApplicationRef);
26533 if (moduleRef._bootstrapComponents.length > 0) {
26534 moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
26535 }
26536 else if (moduleRef.instance.ngDoBootstrap) {
26537 moduleRef.instance.ngDoBootstrap(appRef);
26538 }
26539 else {
26540 throw new Error(`The module ${stringify(moduleRef.instance
26541 .constructor)} was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
26542 `Please define one of these.`);
26543 }
26544 this._modules.push(moduleRef);
26545 }
26546 /**
26547 * Registers a listener to be called when the platform is destroyed.
26548 */
26549 onDestroy(callback) {
26550 this._destroyListeners.push(callback);
26551 }
26552 /**
26553 * Retrieves the platform {@link Injector}, which is the parent injector for
26554 * every Angular application on the page and provides singleton providers.
26555 */
26556 get injector() {
26557 return this._injector;
26558 }
26559 /**
26560 * Destroys the current Angular platform and all Angular applications on the page.
26561 * Destroys all modules and listeners registered with the platform.
26562 */
26563 destroy() {
26564 if (this._destroyed) {
26565 throw new Error('The platform has already been destroyed!');
26566 }
26567 this._modules.slice().forEach(module => module.destroy());
26568 this._destroyListeners.forEach(listener => listener());
26569 this._destroyed = true;
26570 }
26571 get destroyed() {
26572 return this._destroyed;
26573 }
26574}
26575PlatformRef.ɵfac = function PlatformRef_Factory(t) { return new (t || PlatformRef)(ɵɵinject(Injector)); };
26576PlatformRef.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: PlatformRef, factory: PlatformRef.ɵfac });
26577(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformRef, [{
26578 type: Injectable
26579 }], function () { return [{ type: Injector }]; }, null); })();
26580function getNgZone(ngZoneOption, extra) {
26581 let ngZone;
26582 if (ngZoneOption === 'noop') {
26583 ngZone = new NoopNgZone();
26584 }
26585 else {
26586 ngZone = (ngZoneOption === 'zone.js' ? undefined : ngZoneOption) || new NgZone({
26587 enableLongStackTrace: isDevMode(),
26588 shouldCoalesceEventChangeDetection: !!extra?.ngZoneEventCoalescing,
26589 shouldCoalesceRunChangeDetection: !!extra?.ngZoneRunCoalescing
26590 });
26591 }
26592 return ngZone;
26593}
26594function _callAndReportToErrorHandler(errorHandler, ngZone, callback) {
26595 try {
26596 const result = callback();
26597 if (isPromise(result)) {
26598 return result.catch((e) => {
26599 ngZone.runOutsideAngular(() => errorHandler.handleError(e));
26600 // rethrow as the exception handler might not do it
26601 throw e;
26602 });
26603 }
26604 return result;
26605 }
26606 catch (e) {
26607 ngZone.runOutsideAngular(() => errorHandler.handleError(e));
26608 // rethrow as the exception handler might not do it
26609 throw e;
26610 }
26611}
26612function optionsReducer(dst, objs) {
26613 if (Array.isArray(objs)) {
26614 dst = objs.reduce(optionsReducer, dst);
26615 }
26616 else {
26617 dst = { ...dst, ...objs };
26618 }
26619 return dst;
26620}
26621/**
26622 * A reference to an Angular application running on a page.
26623 *
26624 * @usageNotes
26625 *
26626 * {@a is-stable-examples}
26627 * ### isStable examples and caveats
26628 *
26629 * Note two important points about `isStable`, demonstrated in the examples below:
26630 * - the application will never be stable if you start any kind
26631 * of recurrent asynchronous task when the application starts
26632 * (for example for a polling process, started with a `setInterval`, a `setTimeout`
26633 * or using RxJS operators like `interval`);
26634 * - the `isStable` Observable runs outside of the Angular zone.
26635 *
26636 * Let's imagine that you start a recurrent task
26637 * (here incrementing a counter, using RxJS `interval`),
26638 * and at the same time subscribe to `isStable`.
26639 *
26640 * ```
26641 * constructor(appRef: ApplicationRef) {
26642 * appRef.isStable.pipe(
26643 * filter(stable => stable)
26644 * ).subscribe(() => console.log('App is stable now');
26645 * interval(1000).subscribe(counter => console.log(counter));
26646 * }
26647 * ```
26648 * In this example, `isStable` will never emit `true`,
26649 * and the trace "App is stable now" will never get logged.
26650 *
26651 * If you want to execute something when the app is stable,
26652 * you have to wait for the application to be stable
26653 * before starting your polling process.
26654 *
26655 * ```
26656 * constructor(appRef: ApplicationRef) {
26657 * appRef.isStable.pipe(
26658 * first(stable => stable),
26659 * tap(stable => console.log('App is stable now')),
26660 * switchMap(() => interval(1000))
26661 * ).subscribe(counter => console.log(counter));
26662 * }
26663 * ```
26664 * In this example, the trace "App is stable now" will be logged
26665 * and then the counter starts incrementing every second.
26666 *
26667 * Note also that this Observable runs outside of the Angular zone,
26668 * which means that the code in the subscription
26669 * to this Observable will not trigger the change detection.
26670 *
26671 * Let's imagine that instead of logging the counter value,
26672 * you update a field of your component
26673 * and display it in its template.
26674 *
26675 * ```
26676 * constructor(appRef: ApplicationRef) {
26677 * appRef.isStable.pipe(
26678 * first(stable => stable),
26679 * switchMap(() => interval(1000))
26680 * ).subscribe(counter => this.value = counter);
26681 * }
26682 * ```
26683 * As the `isStable` Observable runs outside the zone,
26684 * the `value` field will be updated properly,
26685 * but the template will not be refreshed!
26686 *
26687 * You'll have to manually trigger the change detection to update the template.
26688 *
26689 * ```
26690 * constructor(appRef: ApplicationRef, cd: ChangeDetectorRef) {
26691 * appRef.isStable.pipe(
26692 * first(stable => stable),
26693 * switchMap(() => interval(1000))
26694 * ).subscribe(counter => {
26695 * this.value = counter;
26696 * cd.detectChanges();
26697 * });
26698 * }
26699 * ```
26700 *
26701 * Or make the subscription callback run inside the zone.
26702 *
26703 * ```
26704 * constructor(appRef: ApplicationRef, zone: NgZone) {
26705 * appRef.isStable.pipe(
26706 * first(stable => stable),
26707 * switchMap(() => interval(1000))
26708 * ).subscribe(counter => zone.run(() => this.value = counter));
26709 * }
26710 * ```
26711 *
26712 * @publicApi
26713 */
26714class ApplicationRef {
26715 /** @internal */
26716 constructor(_zone, _injector, _exceptionHandler, _componentFactoryResolver, _initStatus) {
26717 this._zone = _zone;
26718 this._injector = _injector;
26719 this._exceptionHandler = _exceptionHandler;
26720 this._componentFactoryResolver = _componentFactoryResolver;
26721 this._initStatus = _initStatus;
26722 /** @internal */
26723 this._bootstrapListeners = [];
26724 this._views = [];
26725 this._runningTick = false;
26726 this._stable = true;
26727 /**
26728 * Get a list of component types registered to this application.
26729 * This list is populated even before the component is created.
26730 */
26731 this.componentTypes = [];
26732 /**
26733 * Get a list of components registered to this application.
26734 */
26735 this.components = [];
26736 this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({
26737 next: () => {
26738 this._zone.run(() => {
26739 this.tick();
26740 });
26741 }
26742 });
26743 const isCurrentlyStable = new Observable((observer) => {
26744 this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks &&
26745 !this._zone.hasPendingMicrotasks;
26746 this._zone.runOutsideAngular(() => {
26747 observer.next(this._stable);
26748 observer.complete();
26749 });
26750 });
26751 const isStable = new Observable((observer) => {
26752 // Create the subscription to onStable outside the Angular Zone so that
26753 // the callback is run outside the Angular Zone.
26754 let stableSub;
26755 this._zone.runOutsideAngular(() => {
26756 stableSub = this._zone.onStable.subscribe(() => {
26757 NgZone.assertNotInAngularZone();
26758 // Check whether there are no pending macro/micro tasks in the next tick
26759 // to allow for NgZone to update the state.
26760 scheduleMicroTask(() => {
26761 if (!this._stable && !this._zone.hasPendingMacrotasks &&
26762 !this._zone.hasPendingMicrotasks) {
26763 this._stable = true;
26764 observer.next(true);
26765 }
26766 });
26767 });
26768 });
26769 const unstableSub = this._zone.onUnstable.subscribe(() => {
26770 NgZone.assertInAngularZone();
26771 if (this._stable) {
26772 this._stable = false;
26773 this._zone.runOutsideAngular(() => {
26774 observer.next(false);
26775 });
26776 }
26777 });
26778 return () => {
26779 stableSub.unsubscribe();
26780 unstableSub.unsubscribe();
26781 };
26782 });
26783 this.isStable =
26784 merge$1(isCurrentlyStable, isStable.pipe(share()));
26785 }
26786 /**
26787 * Bootstrap a component onto the element identified by its selector or, optionally, to a
26788 * specified element.
26789 *
26790 * @usageNotes
26791 * ### Bootstrap process
26792 *
26793 * When bootstrapping a component, Angular mounts it onto a target DOM element
26794 * and kicks off automatic change detection. The target DOM element can be
26795 * provided using the `rootSelectorOrNode` argument.
26796 *
26797 * If the target DOM element is not provided, Angular tries to find one on a page
26798 * using the `selector` of the component that is being bootstrapped
26799 * (first matched element is used).
26800 *
26801 * ### Example
26802 *
26803 * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,
26804 * but it requires us to know the component while writing the application code.
26805 *
26806 * Imagine a situation where we have to wait for an API call to decide about the component to
26807 * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to
26808 * dynamically bootstrap a component.
26809 *
26810 * {@example core/ts/platform/platform.ts region='componentSelector'}
26811 *
26812 * Optionally, a component can be mounted onto a DOM element that does not match the
26813 * selector of the bootstrapped component.
26814 *
26815 * In the following example, we are providing a CSS selector to match the target element.
26816 *
26817 * {@example core/ts/platform/platform.ts region='cssSelector'}
26818 *
26819 * While in this example, we are providing reference to a DOM node.
26820 *
26821 * {@example core/ts/platform/platform.ts region='domNode'}
26822 */
26823 bootstrap(componentOrFactory, rootSelectorOrNode) {
26824 if (!this._initStatus.done) {
26825 throw new Error('Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.');
26826 }
26827 let componentFactory;
26828 if (componentOrFactory instanceof ComponentFactory$1) {
26829 componentFactory = componentOrFactory;
26830 }
26831 else {
26832 componentFactory =
26833 this._componentFactoryResolver.resolveComponentFactory(componentOrFactory);
26834 }
26835 this.componentTypes.push(componentFactory.componentType);
26836 // Create a factory associated with the current module if it's not bound to some other
26837 const ngModule = isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef$1);
26838 const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
26839 const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
26840 const nativeElement = compRef.location.nativeElement;
26841 const testability = compRef.injector.get(Testability, null);
26842 const testabilityRegistry = testability && compRef.injector.get(TestabilityRegistry);
26843 if (testability && testabilityRegistry) {
26844 testabilityRegistry.registerApplication(nativeElement, testability);
26845 }
26846 compRef.onDestroy(() => {
26847 this.detachView(compRef.hostView);
26848 remove(this.components, compRef);
26849 if (testabilityRegistry) {
26850 testabilityRegistry.unregisterApplication(nativeElement);
26851 }
26852 });
26853 this._loadComponent(compRef);
26854 // Note that we have still left the `isDevMode()` condition in order to avoid
26855 // creating a breaking change for projects that still use the View Engine.
26856 if ((typeof ngDevMode === 'undefined' || ngDevMode) && isDevMode()) {
26857 const _console = this._injector.get(Console);
26858 _console.log(`Angular is running in development mode. Call enableProdMode() to enable production mode.`);
26859 }
26860 return compRef;
26861 }
26862 /**
26863 * Invoke this method to explicitly process change detection and its side-effects.
26864 *
26865 * In development mode, `tick()` also performs a second change detection cycle to ensure that no
26866 * further changes are detected. If additional changes are picked up during this second cycle,
26867 * bindings in the app have side-effects that cannot be resolved in a single change detection
26868 * pass.
26869 * In this case, Angular throws an error, since an Angular application can only have one change
26870 * detection pass during which all change detection must complete.
26871 */
26872 tick() {
26873 if (this._runningTick) {
26874 throw new Error('ApplicationRef.tick is called recursively');
26875 }
26876 try {
26877 this._runningTick = true;
26878 for (let view of this._views) {
26879 view.detectChanges();
26880 }
26881 // Note that we have still left the `isDevMode()` condition in order to avoid
26882 // creating a breaking change for projects that still use the View Engine.
26883 if ((typeof ngDevMode === 'undefined' || ngDevMode) && isDevMode()) {
26884 for (let view of this._views) {
26885 view.checkNoChanges();
26886 }
26887 }
26888 }
26889 catch (e) {
26890 // Attention: Don't rethrow as it could cancel subscriptions to Observables!
26891 this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));
26892 }
26893 finally {
26894 this._runningTick = false;
26895 }
26896 }
26897 /**
26898 * Attaches a view so that it will be dirty checked.
26899 * The view will be automatically detached when it is destroyed.
26900 * This will throw if the view is already attached to a ViewContainer.
26901 */
26902 attachView(viewRef) {
26903 const view = viewRef;
26904 this._views.push(view);
26905 view.attachToAppRef(this);
26906 }
26907 /**
26908 * Detaches a view from dirty checking again.
26909 */
26910 detachView(viewRef) {
26911 const view = viewRef;
26912 remove(this._views, view);
26913 view.detachFromAppRef();
26914 }
26915 _loadComponent(componentRef) {
26916 this.attachView(componentRef.hostView);
26917 this.tick();
26918 this.components.push(componentRef);
26919 // Get the listeners lazily to prevent DI cycles.
26920 const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners);
26921 listeners.forEach((listener) => listener(componentRef));
26922 }
26923 /** @internal */
26924 ngOnDestroy() {
26925 this._views.slice().forEach((view) => view.destroy());
26926 this._onMicrotaskEmptySubscription.unsubscribe();
26927 }
26928 /**
26929 * Returns the number of attached views.
26930 */
26931 get viewCount() {
26932 return this._views.length;
26933 }
26934}
26935ApplicationRef.ɵfac = function ApplicationRef_Factory(t) { return new (t || ApplicationRef)(ɵɵinject(NgZone), ɵɵinject(Injector), ɵɵinject(ErrorHandler), ɵɵinject(ComponentFactoryResolver$1), ɵɵinject(ApplicationInitStatus)); };
26936ApplicationRef.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationRef, factory: ApplicationRef.ɵfac });
26937(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationRef, [{
26938 type: Injectable
26939 }], function () { return [{ type: NgZone }, { type: Injector }, { type: ErrorHandler }, { type: ComponentFactoryResolver$1 }, { type: ApplicationInitStatus }]; }, null); })();
26940function remove(list, el) {
26941 const index = list.indexOf(el);
26942 if (index > -1) {
26943 list.splice(index, 1);
26944 }
26945}
26946function _lastDefined(args) {
26947 for (let i = args.length - 1; i >= 0; i--) {
26948 if (args[i] !== undefined) {
26949 return args[i];
26950 }
26951 }
26952 return undefined;
26953}
26954function _mergeArrays(parts) {
26955 const result = [];
26956 parts.forEach((part) => part && result.push(...part));
26957 return result;
26958}
26959
26960/**
26961 * @license
26962 * Copyright Google LLC All Rights Reserved.
26963 *
26964 * Use of this source code is governed by an MIT-style license that can be
26965 * found in the LICENSE file at https://angular.io/license
26966 */
26967
26968/**
26969 * @license
26970 * Copyright Google LLC All Rights Reserved.
26971 *
26972 * Use of this source code is governed by an MIT-style license that can be
26973 * found in the LICENSE file at https://angular.io/license
26974 */
26975
26976function getModuleFactory__PRE_R3__(id) {
26977 const factory = getRegisteredNgModuleType(id);
26978 if (!factory)
26979 throw noModuleError(id);
26980 return factory;
26981}
26982function getModuleFactory__POST_R3__(id) {
26983 const type = getRegisteredNgModuleType(id);
26984 if (!type)
26985 throw noModuleError(id);
26986 return new NgModuleFactory(type);
26987}
26988function getNgModuleById__PRE_R3__(id) {
26989 throw new Error(`ViewEngine doesn't support retrieving NgModule classes by id`);
26990}
26991function getNgModuleById__POST_R3__(id) {
26992 const type = getRegisteredNgModuleType(id);
26993 if (!type)
26994 throw noModuleError(id);
26995 return type;
26996}
26997/**
26998 * Returns the NgModuleFactory with the given id (specified using [@NgModule.id
26999 * field](api/core/NgModule#id)), if it exists and has been loaded. Factories for NgModules that do
27000 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
27001 * @publicApi
27002 * @deprecated Use `getNgModuleById` instead.
27003 */
27004const getModuleFactory = getModuleFactory__POST_R3__;
27005/**
27006 * Returns the NgModule class with the given id (specified using [@NgModule.id
27007 * field](api/core/NgModule#id)), if it exists and has been loaded. Classes for NgModules that do
27008 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
27009 * @publicApi
27010 */
27011const getNgModuleById = getNgModuleById__POST_R3__;
27012function noModuleError(id) {
27013 return new Error(`No module with ID ${id} loaded`);
27014}
27015
27016const SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ = injectChangeDetectorRef;
27017const SWITCH_CHANGE_DETECTOR_REF_FACTORY__PRE_R3__ = noop;
27018const SWITCH_CHANGE_DETECTOR_REF_FACTORY = SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__;
27019/**
27020 * Base class that provides change detection functionality.
27021 * A change-detection tree collects all views that are to be checked for changes.
27022 * Use the methods to add and remove views from the tree, initiate change-detection,
27023 * and explicitly mark views as _dirty_, meaning that they have changed and need to be re-rendered.
27024 *
27025 * @see [Using change detection hooks](guide/lifecycle-hooks#using-change-detection-hooks)
27026 * @see [Defining custom change detection](guide/lifecycle-hooks#defining-custom-change-detection)
27027 *
27028 * @usageNotes
27029 *
27030 * The following examples demonstrate how to modify default change-detection behavior
27031 * to perform explicit detection when needed.
27032 *
27033 * ### Use `markForCheck()` with `CheckOnce` strategy
27034 *
27035 * The following example sets the `OnPush` change-detection strategy for a component
27036 * (`CheckOnce`, rather than the default `CheckAlways`), then forces a second check
27037 * after an interval. See [live demo](https://plnkr.co/edit/GC512b?p=preview).
27038 *
27039 * <code-example path="core/ts/change_detect/change-detection.ts"
27040 * region="mark-for-check"></code-example>
27041 *
27042 * ### Detach change detector to limit how often check occurs
27043 *
27044 * The following example defines a component with a large list of read-only data
27045 * that is expected to change constantly, many times per second.
27046 * To improve performance, we want to check and update the list
27047 * less often than the changes actually occur. To do that, we detach
27048 * the component's change detector and perform an explicit local check every five seconds.
27049 *
27050 * <code-example path="core/ts/change_detect/change-detection.ts" region="detach"></code-example>
27051 *
27052 *
27053 * ### Reattaching a detached component
27054 *
27055 * The following example creates a component displaying live data.
27056 * The component detaches its change detector from the main change detector tree
27057 * when the `live` property is set to false, and reattaches it when the property
27058 * becomes true.
27059 *
27060 * <code-example path="core/ts/change_detect/change-detection.ts" region="reattach"></code-example>
27061 *
27062 * @publicApi
27063 */
27064class ChangeDetectorRef {
27065}
27066/**
27067 * @internal
27068 * @nocollapse
27069 */
27070ChangeDetectorRef.__NG_ELEMENT_ID__ = SWITCH_CHANGE_DETECTOR_REF_FACTORY;
27071/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
27072function injectChangeDetectorRef(flags) {
27073 return createViewRef(getCurrentTNode(), getLView(), (flags & 16 /* ForPipe */) === 16 /* ForPipe */);
27074}
27075/**
27076 * Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias).
27077 *
27078 * @param tNode The node that is requesting a ChangeDetectorRef
27079 * @param lView The view to which the node belongs
27080 * @param isPipe Whether the view is being injected into a pipe.
27081 * @returns The ChangeDetectorRef to use
27082 */
27083function createViewRef(tNode, lView, isPipe) {
27084 if (isComponentHost(tNode) && !isPipe) {
27085 // The LView represents the location where the component is declared.
27086 // Instead we want the LView for the component View and so we need to look it up.
27087 const componentView = getComponentLViewByIndex(tNode.index, lView); // look down
27088 return new ViewRef$1(componentView, componentView);
27089 }
27090 else if (tNode.type & (3 /* AnyRNode */ | 12 /* AnyContainer */ | 32 /* Icu */)) {
27091 // The LView represents the location where the injection is requested from.
27092 // We need to locate the containing LView (in case where the `lView` is an embedded view)
27093 const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
27094 return new ViewRef$1(hostComponentView, lView);
27095 }
27096 return null;
27097}
27098
27099/**
27100 * @license
27101 * Copyright Google LLC All Rights Reserved.
27102 *
27103 * Use of this source code is governed by an MIT-style license that can be
27104 * found in the LICENSE file at https://angular.io/license
27105 */
27106/**
27107 * Represents an Angular [view](guide/glossary#view "Definition").
27108 *
27109 * @see {@link ChangeDetectorRef#usage-notes Change detection usage}
27110 *
27111 * @publicApi
27112 */
27113class ViewRef extends ChangeDetectorRef {
27114}
27115/**
27116 * Represents an Angular [view](guide/glossary#view) in a view container.
27117 * An [embedded view](guide/glossary#view-tree) can be referenced from a component
27118 * other than the hosting component whose template defines it, or it can be defined
27119 * independently by a `TemplateRef`.
27120 *
27121 * Properties of elements in a view can change, but the structure (number and order) of elements in
27122 * a view cannot. Change the structure of elements by inserting, moving, or
27123 * removing nested views in a view container.
27124 *
27125 * @see `ViewContainerRef`
27126 *
27127 * @usageNotes
27128 *
27129 * The following template breaks down into two separate `TemplateRef` instances,
27130 * an outer one and an inner one.
27131 *
27132 * ```
27133 * Count: {{items.length}}
27134 * <ul>
27135 * <li *ngFor="let item of items">{{item}}</li>
27136 * </ul>
27137 * ```
27138 *
27139 * This is the outer `TemplateRef`:
27140 *
27141 * ```
27142 * Count: {{items.length}}
27143 * <ul>
27144 * <ng-template ngFor let-item [ngForOf]="items"></ng-template>
27145 * </ul>
27146 * ```
27147 *
27148 * This is the inner `TemplateRef`:
27149 *
27150 * ```
27151 * <li>{{item}}</li>
27152 * ```
27153 *
27154 * The outer and inner `TemplateRef` instances are assembled into views as follows:
27155 *
27156 * ```
27157 * <!-- ViewRef: outer-0 -->
27158 * Count: 2
27159 * <ul>
27160 * <ng-template view-container-ref></ng-template>
27161 * <!-- ViewRef: inner-1 --><li>first</li><!-- /ViewRef: inner-1 -->
27162 * <!-- ViewRef: inner-2 --><li>second</li><!-- /ViewRef: inner-2 -->
27163 * </ul>
27164 * <!-- /ViewRef: outer-0 -->
27165 * ```
27166 * @publicApi
27167 */
27168class EmbeddedViewRef extends ViewRef {
27169}
27170
27171/**
27172 * @license
27173 * Copyright Google LLC All Rights Reserved.
27174 *
27175 * Use of this source code is governed by an MIT-style license that can be
27176 * found in the LICENSE file at https://angular.io/license
27177 */
27178
27179/**
27180 * @license
27181 * Copyright Google LLC All Rights Reserved.
27182 *
27183 * Use of this source code is governed by an MIT-style license that can be
27184 * found in the LICENSE file at https://angular.io/license
27185 */
27186// This file exists for easily patching NgModuleFactoryLoader in g3
27187var ng_module_factory_loader_impl = {};
27188
27189/**
27190 * @publicApi
27191 */
27192class DebugEventListener {
27193 constructor(name, callback) {
27194 this.name = name;
27195 this.callback = callback;
27196 }
27197}
27198class DebugNode__PRE_R3__ {
27199 constructor(nativeNode, parent, _debugContext) {
27200 this.listeners = [];
27201 this.parent = null;
27202 this._debugContext = _debugContext;
27203 this.nativeNode = nativeNode;
27204 if (parent && parent instanceof DebugElement__PRE_R3__) {
27205 parent.addChild(this);
27206 }
27207 }
27208 get injector() {
27209 return this._debugContext.injector;
27210 }
27211 get componentInstance() {
27212 return this._debugContext.component;
27213 }
27214 get context() {
27215 return this._debugContext.context;
27216 }
27217 get references() {
27218 return this._debugContext.references;
27219 }
27220 get providerTokens() {
27221 return this._debugContext.providerTokens;
27222 }
27223}
27224class DebugElement__PRE_R3__ extends DebugNode__PRE_R3__ {
27225 constructor(nativeNode, parent, _debugContext) {
27226 super(nativeNode, parent, _debugContext);
27227 this.properties = {};
27228 this.attributes = {};
27229 this.classes = {};
27230 this.styles = {};
27231 this.childNodes = [];
27232 this.nativeElement = nativeNode;
27233 }
27234 addChild(child) {
27235 if (child) {
27236 this.childNodes.push(child);
27237 child.parent = this;
27238 }
27239 }
27240 removeChild(child) {
27241 const childIndex = this.childNodes.indexOf(child);
27242 if (childIndex !== -1) {
27243 child.parent = null;
27244 this.childNodes.splice(childIndex, 1);
27245 }
27246 }
27247 insertChildrenAfter(child, newChildren) {
27248 const siblingIndex = this.childNodes.indexOf(child);
27249 if (siblingIndex !== -1) {
27250 this.childNodes.splice(siblingIndex + 1, 0, ...newChildren);
27251 newChildren.forEach(c => {
27252 if (c.parent) {
27253 c.parent.removeChild(c);
27254 }
27255 child.parent = this;
27256 });
27257 }
27258 }
27259 insertBefore(refChild, newChild) {
27260 const refIndex = this.childNodes.indexOf(refChild);
27261 if (refIndex === -1) {
27262 this.addChild(newChild);
27263 }
27264 else {
27265 if (newChild.parent) {
27266 newChild.parent.removeChild(newChild);
27267 }
27268 newChild.parent = this;
27269 this.childNodes.splice(refIndex, 0, newChild);
27270 }
27271 }
27272 query(predicate) {
27273 const results = this.queryAll(predicate);
27274 return results[0] || null;
27275 }
27276 queryAll(predicate) {
27277 const matches = [];
27278 _queryElementChildren(this, predicate, matches);
27279 return matches;
27280 }
27281 queryAllNodes(predicate) {
27282 const matches = [];
27283 _queryNodeChildren(this, predicate, matches);
27284 return matches;
27285 }
27286 get children() {
27287 return this.childNodes //
27288 .filter((node) => node instanceof DebugElement__PRE_R3__);
27289 }
27290 triggerEventHandler(eventName, eventObj) {
27291 this.listeners.forEach((listener) => {
27292 if (listener.name == eventName) {
27293 listener.callback(eventObj);
27294 }
27295 });
27296 }
27297}
27298/**
27299 * @publicApi
27300 */
27301function asNativeElements(debugEls) {
27302 return debugEls.map((el) => el.nativeElement);
27303}
27304function _queryElementChildren(element, predicate, matches) {
27305 element.childNodes.forEach(node => {
27306 if (node instanceof DebugElement__PRE_R3__) {
27307 if (predicate(node)) {
27308 matches.push(node);
27309 }
27310 _queryElementChildren(node, predicate, matches);
27311 }
27312 });
27313}
27314function _queryNodeChildren(parentNode, predicate, matches) {
27315 if (parentNode instanceof DebugElement__PRE_R3__) {
27316 parentNode.childNodes.forEach(node => {
27317 if (predicate(node)) {
27318 matches.push(node);
27319 }
27320 if (node instanceof DebugElement__PRE_R3__) {
27321 _queryNodeChildren(node, predicate, matches);
27322 }
27323 });
27324 }
27325}
27326class DebugNode__POST_R3__ {
27327 constructor(nativeNode) {
27328 this.nativeNode = nativeNode;
27329 }
27330 get parent() {
27331 const parent = this.nativeNode.parentNode;
27332 return parent ? new DebugElement__POST_R3__(parent) : null;
27333 }
27334 get injector() {
27335 return getInjector(this.nativeNode);
27336 }
27337 get componentInstance() {
27338 const nativeElement = this.nativeNode;
27339 return nativeElement &&
27340 (getComponent$1(nativeElement) || getOwningComponent(nativeElement));
27341 }
27342 get context() {
27343 return getComponent$1(this.nativeNode) || getContext(this.nativeNode);
27344 }
27345 get listeners() {
27346 return getListeners(this.nativeNode).filter(listener => listener.type === 'dom');
27347 }
27348 get references() {
27349 return getLocalRefs(this.nativeNode);
27350 }
27351 get providerTokens() {
27352 return getInjectionTokens(this.nativeNode);
27353 }
27354}
27355class DebugElement__POST_R3__ extends DebugNode__POST_R3__ {
27356 constructor(nativeNode) {
27357 ngDevMode && assertDomNode(nativeNode);
27358 super(nativeNode);
27359 }
27360 get nativeElement() {
27361 return this.nativeNode.nodeType == Node.ELEMENT_NODE ? this.nativeNode : null;
27362 }
27363 get name() {
27364 const context = getLContext(this.nativeNode);
27365 if (context !== null) {
27366 const lView = context.lView;
27367 const tData = lView[TVIEW].data;
27368 const tNode = tData[context.nodeIndex];
27369 return tNode.value;
27370 }
27371 else {
27372 return this.nativeNode.nodeName;
27373 }
27374 }
27375 /**
27376 * Gets a map of property names to property values for an element.
27377 *
27378 * This map includes:
27379 * - Regular property bindings (e.g. `[id]="id"`)
27380 * - Host property bindings (e.g. `host: { '[id]': "id" }`)
27381 * - Interpolated property bindings (e.g. `id="{{ value }}")
27382 *
27383 * It does not include:
27384 * - input property bindings (e.g. `[myCustomInput]="value"`)
27385 * - attribute bindings (e.g. `[attr.role]="menu"`)
27386 */
27387 get properties() {
27388 const context = getLContext(this.nativeNode);
27389 if (context === null) {
27390 return {};
27391 }
27392 const lView = context.lView;
27393 const tData = lView[TVIEW].data;
27394 const tNode = tData[context.nodeIndex];
27395 const properties = {};
27396 // Collect properties from the DOM.
27397 copyDomProperties(this.nativeElement, properties);
27398 // Collect properties from the bindings. This is needed for animation renderer which has
27399 // synthetic properties which don't get reflected into the DOM.
27400 collectPropertyBindings(properties, tNode, lView, tData);
27401 return properties;
27402 }
27403 get attributes() {
27404 const attributes = {};
27405 const element = this.nativeElement;
27406 if (!element) {
27407 return attributes;
27408 }
27409 const context = getLContext(element);
27410 if (context === null) {
27411 return {};
27412 }
27413 const lView = context.lView;
27414 const tNodeAttrs = lView[TVIEW].data[context.nodeIndex].attrs;
27415 const lowercaseTNodeAttrs = [];
27416 // For debug nodes we take the element's attribute directly from the DOM since it allows us
27417 // to account for ones that weren't set via bindings (e.g. ViewEngine keeps track of the ones
27418 // that are set through `Renderer2`). The problem is that the browser will lowercase all names,
27419 // however since we have the attributes already on the TNode, we can preserve the case by going
27420 // through them once, adding them to the `attributes` map and putting their lower-cased name
27421 // into an array. Afterwards when we're going through the native DOM attributes, we can check
27422 // whether we haven't run into an attribute already through the TNode.
27423 if (tNodeAttrs) {
27424 let i = 0;
27425 while (i < tNodeAttrs.length) {
27426 const attrName = tNodeAttrs[i];
27427 // Stop as soon as we hit a marker. We only care about the regular attributes. Everything
27428 // else will be handled below when we read the final attributes off the DOM.
27429 if (typeof attrName !== 'string')
27430 break;
27431 const attrValue = tNodeAttrs[i + 1];
27432 attributes[attrName] = attrValue;
27433 lowercaseTNodeAttrs.push(attrName.toLowerCase());
27434 i += 2;
27435 }
27436 }
27437 const eAttrs = element.attributes;
27438 for (let i = 0; i < eAttrs.length; i++) {
27439 const attr = eAttrs[i];
27440 const lowercaseName = attr.name.toLowerCase();
27441 // Make sure that we don't assign the same attribute both in its
27442 // case-sensitive form and the lower-cased one from the browser.
27443 if (lowercaseTNodeAttrs.indexOf(lowercaseName) === -1) {
27444 // Save the lowercase name to align the behavior between browsers.
27445 // IE preserves the case, while all other browser convert it to lower case.
27446 attributes[lowercaseName] = attr.value;
27447 }
27448 }
27449 return attributes;
27450 }
27451 get styles() {
27452 if (this.nativeElement && this.nativeElement.style) {
27453 return this.nativeElement.style;
27454 }
27455 return {};
27456 }
27457 get classes() {
27458 const result = {};
27459 const element = this.nativeElement;
27460 // SVG elements return an `SVGAnimatedString` instead of a plain string for the `className`.
27461 const className = element.className;
27462 const classes = typeof className !== 'string' ? className.baseVal.split(' ') : className.split(' ');
27463 classes.forEach((value) => result[value] = true);
27464 return result;
27465 }
27466 get childNodes() {
27467 const childNodes = this.nativeNode.childNodes;
27468 const children = [];
27469 for (let i = 0; i < childNodes.length; i++) {
27470 const element = childNodes[i];
27471 children.push(getDebugNode__POST_R3__(element));
27472 }
27473 return children;
27474 }
27475 get children() {
27476 const nativeElement = this.nativeElement;
27477 if (!nativeElement)
27478 return [];
27479 const childNodes = nativeElement.children;
27480 const children = [];
27481 for (let i = 0; i < childNodes.length; i++) {
27482 const element = childNodes[i];
27483 children.push(getDebugNode__POST_R3__(element));
27484 }
27485 return children;
27486 }
27487 query(predicate) {
27488 const results = this.queryAll(predicate);
27489 return results[0] || null;
27490 }
27491 queryAll(predicate) {
27492 const matches = [];
27493 _queryAllR3(this, predicate, matches, true);
27494 return matches;
27495 }
27496 queryAllNodes(predicate) {
27497 const matches = [];
27498 _queryAllR3(this, predicate, matches, false);
27499 return matches;
27500 }
27501 triggerEventHandler(eventName, eventObj) {
27502 const node = this.nativeNode;
27503 const invokedListeners = [];
27504 this.listeners.forEach(listener => {
27505 if (listener.name === eventName) {
27506 const callback = listener.callback;
27507 callback.call(node, eventObj);
27508 invokedListeners.push(callback);
27509 }
27510 });
27511 // We need to check whether `eventListeners` exists, because it's something
27512 // that Zone.js only adds to `EventTarget` in browser environments.
27513 if (typeof node.eventListeners === 'function') {
27514 // Note that in Ivy we wrap event listeners with a call to `event.preventDefault` in some
27515 // cases. We use '__ngUnwrap__' as a special token that gives us access to the actual event
27516 // listener.
27517 node.eventListeners(eventName).forEach((listener) => {
27518 // In order to ensure that we can detect the special __ngUnwrap__ token described above, we
27519 // use `toString` on the listener and see if it contains the token. We use this approach to
27520 // ensure that it still worked with compiled code since it cannot remove or rename string
27521 // literals. We also considered using a special function name (i.e. if(listener.name ===
27522 // special)) but that was more cumbersome and we were also concerned the compiled code could
27523 // strip the name, turning the condition in to ("" === "") and always returning true.
27524 if (listener.toString().indexOf('__ngUnwrap__') !== -1) {
27525 const unwrappedListener = listener('__ngUnwrap__');
27526 return invokedListeners.indexOf(unwrappedListener) === -1 &&
27527 unwrappedListener.call(node, eventObj);
27528 }
27529 });
27530 }
27531 }
27532}
27533function copyDomProperties(element, properties) {
27534 if (element) {
27535 // Skip own properties (as those are patched)
27536 let obj = Object.getPrototypeOf(element);
27537 const NodePrototype = Node.prototype;
27538 while (obj !== null && obj !== NodePrototype) {
27539 const descriptors = Object.getOwnPropertyDescriptors(obj);
27540 for (let key in descriptors) {
27541 if (!key.startsWith('__') && !key.startsWith('on')) {
27542 // don't include properties starting with `__` and `on`.
27543 // `__` are patched values which should not be included.
27544 // `on` are listeners which also should not be included.
27545 const value = element[key];
27546 if (isPrimitiveValue(value)) {
27547 properties[key] = value;
27548 }
27549 }
27550 }
27551 obj = Object.getPrototypeOf(obj);
27552 }
27553 }
27554}
27555function isPrimitiveValue(value) {
27556 return typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' ||
27557 value === null;
27558}
27559function _queryAllR3(parentElement, predicate, matches, elementsOnly) {
27560 const context = getLContext(parentElement.nativeNode);
27561 if (context !== null) {
27562 const parentTNode = context.lView[TVIEW].data[context.nodeIndex];
27563 _queryNodeChildrenR3(parentTNode, context.lView, predicate, matches, elementsOnly, parentElement.nativeNode);
27564 }
27565 else {
27566 // If the context is null, then `parentElement` was either created with Renderer2 or native DOM
27567 // APIs.
27568 _queryNativeNodeDescendants(parentElement.nativeNode, predicate, matches, elementsOnly);
27569 }
27570}
27571/**
27572 * Recursively match the current TNode against the predicate, and goes on with the next ones.
27573 *
27574 * @param tNode the current TNode
27575 * @param lView the LView of this TNode
27576 * @param predicate the predicate to match
27577 * @param matches the list of positive matches
27578 * @param elementsOnly whether only elements should be searched
27579 * @param rootNativeNode the root native node on which predicate should not be matched
27580 */
27581function _queryNodeChildrenR3(tNode, lView, predicate, matches, elementsOnly, rootNativeNode) {
27582 ngDevMode && assertTNodeForLView(tNode, lView);
27583 const nativeNode = getNativeByTNodeOrNull(tNode, lView);
27584 // For each type of TNode, specific logic is executed.
27585 if (tNode.type & (3 /* AnyRNode */ | 8 /* ElementContainer */)) {
27586 // Case 1: the TNode is an element
27587 // The native node has to be checked.
27588 _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
27589 if (isComponentHost(tNode)) {
27590 // If the element is the host of a component, then all nodes in its view have to be processed.
27591 // Note: the component's content (tNode.child) will be processed from the insertion points.
27592 const componentView = getComponentLViewByIndex(tNode.index, lView);
27593 if (componentView && componentView[TVIEW].firstChild) {
27594 _queryNodeChildrenR3(componentView[TVIEW].firstChild, componentView, predicate, matches, elementsOnly, rootNativeNode);
27595 }
27596 }
27597 else {
27598 if (tNode.child) {
27599 // Otherwise, its children have to be processed.
27600 _queryNodeChildrenR3(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode);
27601 }
27602 // We also have to query the DOM directly in order to catch elements inserted through
27603 // Renderer2. Note that this is __not__ optimal, because we're walking similar trees multiple
27604 // times. ViewEngine could do it more efficiently, because all the insertions go through
27605 // Renderer2, however that's not the case in Ivy. This approach is being used because:
27606 // 1. Matching the ViewEngine behavior would mean potentially introducing a depedency
27607 // from `Renderer2` to Ivy which could bring Ivy code into ViewEngine.
27608 // 2. We would have to make `Renderer3` "know" about debug nodes.
27609 // 3. It allows us to capture nodes that were inserted directly via the DOM.
27610 nativeNode && _queryNativeNodeDescendants(nativeNode, predicate, matches, elementsOnly);
27611 }
27612 // In all cases, if a dynamic container exists for this node, each view inside it has to be
27613 // processed.
27614 const nodeOrContainer = lView[tNode.index];
27615 if (isLContainer(nodeOrContainer)) {
27616 _queryNodeChildrenInContainerR3(nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
27617 }
27618 }
27619 else if (tNode.type & 4 /* Container */) {
27620 // Case 2: the TNode is a container
27621 // The native node has to be checked.
27622 const lContainer = lView[tNode.index];
27623 _addQueryMatchR3(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode);
27624 // Each view inside the container has to be processed.
27625 _queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode);
27626 }
27627 else if (tNode.type & 16 /* Projection */) {
27628 // Case 3: the TNode is a projection insertion point (i.e. a <ng-content>).
27629 // The nodes projected at this location all need to be processed.
27630 const componentView = lView[DECLARATION_COMPONENT_VIEW];
27631 const componentHost = componentView[T_HOST];
27632 const head = componentHost.projection[tNode.projection];
27633 if (Array.isArray(head)) {
27634 for (let nativeNode of head) {
27635 _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
27636 }
27637 }
27638 else if (head) {
27639 const nextLView = componentView[PARENT];
27640 const nextTNode = nextLView[TVIEW].data[head.index];
27641 _queryNodeChildrenR3(nextTNode, nextLView, predicate, matches, elementsOnly, rootNativeNode);
27642 }
27643 }
27644 else if (tNode.child) {
27645 // Case 4: the TNode is a view.
27646 _queryNodeChildrenR3(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode);
27647 }
27648 // We don't want to go to the next sibling of the root node.
27649 if (rootNativeNode !== nativeNode) {
27650 // To determine the next node to be processed, we need to use the next or the projectionNext
27651 // link, depending on whether the current node has been projected.
27652 const nextTNode = (tNode.flags & 4 /* isProjected */) ? tNode.projectionNext : tNode.next;
27653 if (nextTNode) {
27654 _queryNodeChildrenR3(nextTNode, lView, predicate, matches, elementsOnly, rootNativeNode);
27655 }
27656 }
27657}
27658/**
27659 * Process all TNodes in a given container.
27660 *
27661 * @param lContainer the container to be processed
27662 * @param predicate the predicate to match
27663 * @param matches the list of positive matches
27664 * @param elementsOnly whether only elements should be searched
27665 * @param rootNativeNode the root native node on which predicate should not be matched
27666 */
27667function _queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode) {
27668 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
27669 const childView = lContainer[i];
27670 const firstChild = childView[TVIEW].firstChild;
27671 if (firstChild) {
27672 _queryNodeChildrenR3(firstChild, childView, predicate, matches, elementsOnly, rootNativeNode);
27673 }
27674 }
27675}
27676/**
27677 * Match the current native node against the predicate.
27678 *
27679 * @param nativeNode the current native node
27680 * @param predicate the predicate to match
27681 * @param matches the list of positive matches
27682 * @param elementsOnly whether only elements should be searched
27683 * @param rootNativeNode the root native node on which predicate should not be matched
27684 */
27685function _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode) {
27686 if (rootNativeNode !== nativeNode) {
27687 const debugNode = getDebugNode(nativeNode);
27688 if (!debugNode) {
27689 return;
27690 }
27691 // Type of the "predicate and "matches" array are set based on the value of
27692 // the "elementsOnly" parameter. TypeScript is not able to properly infer these
27693 // types with generics, so we manually cast the parameters accordingly.
27694 if (elementsOnly && debugNode instanceof DebugElement__POST_R3__ && predicate(debugNode) &&
27695 matches.indexOf(debugNode) === -1) {
27696 matches.push(debugNode);
27697 }
27698 else if (!elementsOnly && predicate(debugNode) &&
27699 matches.indexOf(debugNode) === -1) {
27700 matches.push(debugNode);
27701 }
27702 }
27703}
27704/**
27705 * Match all the descendants of a DOM node against a predicate.
27706 *
27707 * @param nativeNode the current native node
27708 * @param predicate the predicate to match
27709 * @param matches the list where matches are stored
27710 * @param elementsOnly whether only elements should be searched
27711 */
27712function _queryNativeNodeDescendants(parentNode, predicate, matches, elementsOnly) {
27713 const nodes = parentNode.childNodes;
27714 const length = nodes.length;
27715 for (let i = 0; i < length; i++) {
27716 const node = nodes[i];
27717 const debugNode = getDebugNode(node);
27718 if (debugNode) {
27719 if (elementsOnly && debugNode instanceof DebugElement__POST_R3__ && predicate(debugNode) &&
27720 matches.indexOf(debugNode) === -1) {
27721 matches.push(debugNode);
27722 }
27723 else if (!elementsOnly && predicate(debugNode) &&
27724 matches.indexOf(debugNode) === -1) {
27725 matches.push(debugNode);
27726 }
27727 _queryNativeNodeDescendants(node, predicate, matches, elementsOnly);
27728 }
27729 }
27730}
27731/**
27732 * Iterates through the property bindings for a given node and generates
27733 * a map of property names to values. This map only contains property bindings
27734 * defined in templates, not in host bindings.
27735 */
27736function collectPropertyBindings(properties, tNode, lView, tData) {
27737 let bindingIndexes = tNode.propertyBindings;
27738 if (bindingIndexes !== null) {
27739 for (let i = 0; i < bindingIndexes.length; i++) {
27740 const bindingIndex = bindingIndexes[i];
27741 const propMetadata = tData[bindingIndex];
27742 const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER);
27743 const propertyName = metadataParts[0];
27744 if (metadataParts.length > 1) {
27745 let value = metadataParts[1];
27746 for (let j = 1; j < metadataParts.length - 1; j++) {
27747 value += renderStringify(lView[bindingIndex + j - 1]) + metadataParts[j + 1];
27748 }
27749 properties[propertyName] = value;
27750 }
27751 else {
27752 properties[propertyName] = lView[bindingIndex];
27753 }
27754 }
27755 }
27756}
27757// Need to keep the nodes in a global Map so that multiple angular apps are supported.
27758const _nativeNodeToDebugNode = new Map();
27759function getDebugNode__PRE_R3__(nativeNode) {
27760 return _nativeNodeToDebugNode.get(nativeNode) || null;
27761}
27762const NG_DEBUG_PROPERTY = '__ng_debug__';
27763function getDebugNode__POST_R3__(nativeNode) {
27764 if (nativeNode instanceof Node) {
27765 if (!(nativeNode.hasOwnProperty(NG_DEBUG_PROPERTY))) {
27766 nativeNode[NG_DEBUG_PROPERTY] = nativeNode.nodeType == Node.ELEMENT_NODE ?
27767 new DebugElement__POST_R3__(nativeNode) :
27768 new DebugNode__POST_R3__(nativeNode);
27769 }
27770 return nativeNode[NG_DEBUG_PROPERTY];
27771 }
27772 return null;
27773}
27774/**
27775 * @publicApi
27776 */
27777const getDebugNode = getDebugNode__POST_R3__;
27778function getDebugNodeR2__PRE_R3__(nativeNode) {
27779 return getDebugNode__PRE_R3__(nativeNode);
27780}
27781function getDebugNodeR2__POST_R3__(_nativeNode) {
27782 return null;
27783}
27784const getDebugNodeR2 = getDebugNodeR2__POST_R3__;
27785function getAllDebugNodes() {
27786 return Array.from(_nativeNodeToDebugNode.values());
27787}
27788function indexDebugNode(node) {
27789 _nativeNodeToDebugNode.set(node.nativeNode, node);
27790}
27791function removeDebugNodeFromIndex(node) {
27792 _nativeNodeToDebugNode.delete(node.nativeNode);
27793}
27794/**
27795 * @publicApi
27796 */
27797const DebugNode = DebugNode__POST_R3__;
27798/**
27799 * @publicApi
27800 */
27801const DebugElement = DebugElement__POST_R3__;
27802
27803/**
27804 * @license
27805 * Copyright Google LLC All Rights Reserved.
27806 *
27807 * Use of this source code is governed by an MIT-style license that can be
27808 * found in the LICENSE file at https://angular.io/license
27809 */
27810class DefaultIterableDifferFactory {
27811 constructor() { }
27812 supports(obj) {
27813 return isListLikeIterable(obj);
27814 }
27815 create(trackByFn) {
27816 return new DefaultIterableDiffer(trackByFn);
27817 }
27818}
27819const trackByIdentity = (index, item) => item;
27820/**
27821 * @deprecated v4.0.0 - Should not be part of public API.
27822 * @publicApi
27823 */
27824class DefaultIterableDiffer {
27825 constructor(trackByFn) {
27826 this.length = 0;
27827 // Keeps track of the used records at any point in time (during & across `_check()` calls)
27828 this._linkedRecords = null;
27829 // Keeps track of the removed records at any point in time during `_check()` calls.
27830 this._unlinkedRecords = null;
27831 this._previousItHead = null;
27832 this._itHead = null;
27833 this._itTail = null;
27834 this._additionsHead = null;
27835 this._additionsTail = null;
27836 this._movesHead = null;
27837 this._movesTail = null;
27838 this._removalsHead = null;
27839 this._removalsTail = null;
27840 // Keeps track of records where custom track by is the same, but item identity has changed
27841 this._identityChangesHead = null;
27842 this._identityChangesTail = null;
27843 this._trackByFn = trackByFn || trackByIdentity;
27844 }
27845 forEachItem(fn) {
27846 let record;
27847 for (record = this._itHead; record !== null; record = record._next) {
27848 fn(record);
27849 }
27850 }
27851 forEachOperation(fn) {
27852 let nextIt = this._itHead;
27853 let nextRemove = this._removalsHead;
27854 let addRemoveOffset = 0;
27855 let moveOffsets = null;
27856 while (nextIt || nextRemove) {
27857 // Figure out which is the next record to process
27858 // Order: remove, add, move
27859 const record = !nextRemove ||
27860 nextIt &&
27861 nextIt.currentIndex <
27862 getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets) ?
27863 nextIt :
27864 nextRemove;
27865 const adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets);
27866 const currentIndex = record.currentIndex;
27867 // consume the item, and adjust the addRemoveOffset and update moveDistance if necessary
27868 if (record === nextRemove) {
27869 addRemoveOffset--;
27870 nextRemove = nextRemove._nextRemoved;
27871 }
27872 else {
27873 nextIt = nextIt._next;
27874 if (record.previousIndex == null) {
27875 addRemoveOffset++;
27876 }
27877 else {
27878 // INVARIANT: currentIndex < previousIndex
27879 if (!moveOffsets)
27880 moveOffsets = [];
27881 const localMovePreviousIndex = adjPreviousIndex - addRemoveOffset;
27882 const localCurrentIndex = currentIndex - addRemoveOffset;
27883 if (localMovePreviousIndex != localCurrentIndex) {
27884 for (let i = 0; i < localMovePreviousIndex; i++) {
27885 const offset = i < moveOffsets.length ? moveOffsets[i] : (moveOffsets[i] = 0);
27886 const index = offset + i;
27887 if (localCurrentIndex <= index && index < localMovePreviousIndex) {
27888 moveOffsets[i] = offset + 1;
27889 }
27890 }
27891 const previousIndex = record.previousIndex;
27892 moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex;
27893 }
27894 }
27895 }
27896 if (adjPreviousIndex !== currentIndex) {
27897 fn(record, adjPreviousIndex, currentIndex);
27898 }
27899 }
27900 }
27901 forEachPreviousItem(fn) {
27902 let record;
27903 for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
27904 fn(record);
27905 }
27906 }
27907 forEachAddedItem(fn) {
27908 let record;
27909 for (record = this._additionsHead; record !== null; record = record._nextAdded) {
27910 fn(record);
27911 }
27912 }
27913 forEachMovedItem(fn) {
27914 let record;
27915 for (record = this._movesHead; record !== null; record = record._nextMoved) {
27916 fn(record);
27917 }
27918 }
27919 forEachRemovedItem(fn) {
27920 let record;
27921 for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
27922 fn(record);
27923 }
27924 }
27925 forEachIdentityChange(fn) {
27926 let record;
27927 for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {
27928 fn(record);
27929 }
27930 }
27931 diff(collection) {
27932 if (collection == null)
27933 collection = [];
27934 if (!isListLikeIterable(collection)) {
27935 throw new Error(`Error trying to diff '${stringify(collection)}'. Only arrays and iterables are allowed`);
27936 }
27937 if (this.check(collection)) {
27938 return this;
27939 }
27940 else {
27941 return null;
27942 }
27943 }
27944 onDestroy() { }
27945 check(collection) {
27946 this._reset();
27947 let record = this._itHead;
27948 let mayBeDirty = false;
27949 let index;
27950 let item;
27951 let itemTrackBy;
27952 if (Array.isArray(collection)) {
27953 this.length = collection.length;
27954 for (let index = 0; index < this.length; index++) {
27955 item = collection[index];
27956 itemTrackBy = this._trackByFn(index, item);
27957 if (record === null || !Object.is(record.trackById, itemTrackBy)) {
27958 record = this._mismatch(record, item, itemTrackBy, index);
27959 mayBeDirty = true;
27960 }
27961 else {
27962 if (mayBeDirty) {
27963 // TODO(misko): can we limit this to duplicates only?
27964 record = this._verifyReinsertion(record, item, itemTrackBy, index);
27965 }
27966 if (!Object.is(record.item, item))
27967 this._addIdentityChange(record, item);
27968 }
27969 record = record._next;
27970 }
27971 }
27972 else {
27973 index = 0;
27974 iterateListLike(collection, (item) => {
27975 itemTrackBy = this._trackByFn(index, item);
27976 if (record === null || !Object.is(record.trackById, itemTrackBy)) {
27977 record = this._mismatch(record, item, itemTrackBy, index);
27978 mayBeDirty = true;
27979 }
27980 else {
27981 if (mayBeDirty) {
27982 // TODO(misko): can we limit this to duplicates only?
27983 record = this._verifyReinsertion(record, item, itemTrackBy, index);
27984 }
27985 if (!Object.is(record.item, item))
27986 this._addIdentityChange(record, item);
27987 }
27988 record = record._next;
27989 index++;
27990 });
27991 this.length = index;
27992 }
27993 this._truncate(record);
27994 this.collection = collection;
27995 return this.isDirty;
27996 }
27997 /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity
27998 * changes.
27999 */
28000 get isDirty() {
28001 return this._additionsHead !== null || this._movesHead !== null ||
28002 this._removalsHead !== null || this._identityChangesHead !== null;
28003 }
28004 /**
28005 * Reset the state of the change objects to show no changes. This means set previousKey to
28006 * currentKey, and clear all of the queues (additions, moves, removals).
28007 * Set the previousIndexes of moved and added items to their currentIndexes
28008 * Reset the list of additions, moves and removals
28009 *
28010 * @internal
28011 */
28012 _reset() {
28013 if (this.isDirty) {
28014 let record;
28015 for (record = this._previousItHead = this._itHead; record !== null; record = record._next) {
28016 record._nextPrevious = record._next;
28017 }
28018 for (record = this._additionsHead; record !== null; record = record._nextAdded) {
28019 record.previousIndex = record.currentIndex;
28020 }
28021 this._additionsHead = this._additionsTail = null;
28022 for (record = this._movesHead; record !== null; record = record._nextMoved) {
28023 record.previousIndex = record.currentIndex;
28024 }
28025 this._movesHead = this._movesTail = null;
28026 this._removalsHead = this._removalsTail = null;
28027 this._identityChangesHead = this._identityChangesTail = null;
28028 // TODO(vicb): when assert gets supported
28029 // assert(!this.isDirty);
28030 }
28031 }
28032 /**
28033 * This is the core function which handles differences between collections.
28034 *
28035 * - `record` is the record which we saw at this position last time. If null then it is a new
28036 * item.
28037 * - `item` is the current item in the collection
28038 * - `index` is the position of the item in the collection
28039 *
28040 * @internal
28041 */
28042 _mismatch(record, item, itemTrackBy, index) {
28043 // The previous record after which we will append the current one.
28044 let previousRecord;
28045 if (record === null) {
28046 previousRecord = this._itTail;
28047 }
28048 else {
28049 previousRecord = record._prev;
28050 // Remove the record from the collection since we know it does not match the item.
28051 this._remove(record);
28052 }
28053 // See if we have evicted the item, which used to be at some anterior position of _itHead list.
28054 record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);
28055 if (record !== null) {
28056 // It is an item which we have evicted earlier: reinsert it back into the list.
28057 // But first we need to check if identity changed, so we can update in view if necessary.
28058 if (!Object.is(record.item, item))
28059 this._addIdentityChange(record, item);
28060 this._reinsertAfter(record, previousRecord, index);
28061 }
28062 else {
28063 // Attempt to see if the item is at some posterior position of _itHead list.
28064 record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
28065 if (record !== null) {
28066 // We have the item in _itHead at/after `index` position. We need to move it forward in the
28067 // collection.
28068 // But first we need to check if identity changed, so we can update in view if necessary.
28069 if (!Object.is(record.item, item))
28070 this._addIdentityChange(record, item);
28071 this._moveAfter(record, previousRecord, index);
28072 }
28073 else {
28074 // It is a new item: add it.
28075 record =
28076 this._addAfter(new IterableChangeRecord_(item, itemTrackBy), previousRecord, index);
28077 }
28078 }
28079 return record;
28080 }
28081 /**
28082 * This check is only needed if an array contains duplicates. (Short circuit of nothing dirty)
28083 *
28084 * Use case: `[a, a]` => `[b, a, a]`
28085 *
28086 * If we did not have this check then the insertion of `b` would:
28087 * 1) evict first `a`
28088 * 2) insert `b` at `0` index.
28089 * 3) leave `a` at index `1` as is. <-- this is wrong!
28090 * 3) reinsert `a` at index 2. <-- this is wrong!
28091 *
28092 * The correct behavior is:
28093 * 1) evict first `a`
28094 * 2) insert `b` at `0` index.
28095 * 3) reinsert `a` at index 1.
28096 * 3) move `a` at from `1` to `2`.
28097 *
28098 *
28099 * Double check that we have not evicted a duplicate item. We need to check if the item type may
28100 * have already been removed:
28101 * The insertion of b will evict the first 'a'. If we don't reinsert it now it will be reinserted
28102 * at the end. Which will show up as the two 'a's switching position. This is incorrect, since a
28103 * better way to think of it is as insert of 'b' rather then switch 'a' with 'b' and then add 'a'
28104 * at the end.
28105 *
28106 * @internal
28107 */
28108 _verifyReinsertion(record, item, itemTrackBy, index) {
28109 let reinsertRecord = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);
28110 if (reinsertRecord !== null) {
28111 record = this._reinsertAfter(reinsertRecord, record._prev, index);
28112 }
28113 else if (record.currentIndex != index) {
28114 record.currentIndex = index;
28115 this._addToMoves(record, index);
28116 }
28117 return record;
28118 }
28119 /**
28120 * Get rid of any excess {@link IterableChangeRecord_}s from the previous collection
28121 *
28122 * - `record` The first excess {@link IterableChangeRecord_}.
28123 *
28124 * @internal
28125 */
28126 _truncate(record) {
28127 // Anything after that needs to be removed;
28128 while (record !== null) {
28129 const nextRecord = record._next;
28130 this._addToRemovals(this._unlink(record));
28131 record = nextRecord;
28132 }
28133 if (this._unlinkedRecords !== null) {
28134 this._unlinkedRecords.clear();
28135 }
28136 if (this._additionsTail !== null) {
28137 this._additionsTail._nextAdded = null;
28138 }
28139 if (this._movesTail !== null) {
28140 this._movesTail._nextMoved = null;
28141 }
28142 if (this._itTail !== null) {
28143 this._itTail._next = null;
28144 }
28145 if (this._removalsTail !== null) {
28146 this._removalsTail._nextRemoved = null;
28147 }
28148 if (this._identityChangesTail !== null) {
28149 this._identityChangesTail._nextIdentityChange = null;
28150 }
28151 }
28152 /** @internal */
28153 _reinsertAfter(record, prevRecord, index) {
28154 if (this._unlinkedRecords !== null) {
28155 this._unlinkedRecords.remove(record);
28156 }
28157 const prev = record._prevRemoved;
28158 const next = record._nextRemoved;
28159 if (prev === null) {
28160 this._removalsHead = next;
28161 }
28162 else {
28163 prev._nextRemoved = next;
28164 }
28165 if (next === null) {
28166 this._removalsTail = prev;
28167 }
28168 else {
28169 next._prevRemoved = prev;
28170 }
28171 this._insertAfter(record, prevRecord, index);
28172 this._addToMoves(record, index);
28173 return record;
28174 }
28175 /** @internal */
28176 _moveAfter(record, prevRecord, index) {
28177 this._unlink(record);
28178 this._insertAfter(record, prevRecord, index);
28179 this._addToMoves(record, index);
28180 return record;
28181 }
28182 /** @internal */
28183 _addAfter(record, prevRecord, index) {
28184 this._insertAfter(record, prevRecord, index);
28185 if (this._additionsTail === null) {
28186 // TODO(vicb):
28187 // assert(this._additionsHead === null);
28188 this._additionsTail = this._additionsHead = record;
28189 }
28190 else {
28191 // TODO(vicb):
28192 // assert(_additionsTail._nextAdded === null);
28193 // assert(record._nextAdded === null);
28194 this._additionsTail = this._additionsTail._nextAdded = record;
28195 }
28196 return record;
28197 }
28198 /** @internal */
28199 _insertAfter(record, prevRecord, index) {
28200 // TODO(vicb):
28201 // assert(record != prevRecord);
28202 // assert(record._next === null);
28203 // assert(record._prev === null);
28204 const next = prevRecord === null ? this._itHead : prevRecord._next;
28205 // TODO(vicb):
28206 // assert(next != record);
28207 // assert(prevRecord != record);
28208 record._next = next;
28209 record._prev = prevRecord;
28210 if (next === null) {
28211 this._itTail = record;
28212 }
28213 else {
28214 next._prev = record;
28215 }
28216 if (prevRecord === null) {
28217 this._itHead = record;
28218 }
28219 else {
28220 prevRecord._next = record;
28221 }
28222 if (this._linkedRecords === null) {
28223 this._linkedRecords = new _DuplicateMap();
28224 }
28225 this._linkedRecords.put(record);
28226 record.currentIndex = index;
28227 return record;
28228 }
28229 /** @internal */
28230 _remove(record) {
28231 return this._addToRemovals(this._unlink(record));
28232 }
28233 /** @internal */
28234 _unlink(record) {
28235 if (this._linkedRecords !== null) {
28236 this._linkedRecords.remove(record);
28237 }
28238 const prev = record._prev;
28239 const next = record._next;
28240 // TODO(vicb):
28241 // assert((record._prev = null) === null);
28242 // assert((record._next = null) === null);
28243 if (prev === null) {
28244 this._itHead = next;
28245 }
28246 else {
28247 prev._next = next;
28248 }
28249 if (next === null) {
28250 this._itTail = prev;
28251 }
28252 else {
28253 next._prev = prev;
28254 }
28255 return record;
28256 }
28257 /** @internal */
28258 _addToMoves(record, toIndex) {
28259 // TODO(vicb):
28260 // assert(record._nextMoved === null);
28261 if (record.previousIndex === toIndex) {
28262 return record;
28263 }
28264 if (this._movesTail === null) {
28265 // TODO(vicb):
28266 // assert(_movesHead === null);
28267 this._movesTail = this._movesHead = record;
28268 }
28269 else {
28270 // TODO(vicb):
28271 // assert(_movesTail._nextMoved === null);
28272 this._movesTail = this._movesTail._nextMoved = record;
28273 }
28274 return record;
28275 }
28276 _addToRemovals(record) {
28277 if (this._unlinkedRecords === null) {
28278 this._unlinkedRecords = new _DuplicateMap();
28279 }
28280 this._unlinkedRecords.put(record);
28281 record.currentIndex = null;
28282 record._nextRemoved = null;
28283 if (this._removalsTail === null) {
28284 // TODO(vicb):
28285 // assert(_removalsHead === null);
28286 this._removalsTail = this._removalsHead = record;
28287 record._prevRemoved = null;
28288 }
28289 else {
28290 // TODO(vicb):
28291 // assert(_removalsTail._nextRemoved === null);
28292 // assert(record._nextRemoved === null);
28293 record._prevRemoved = this._removalsTail;
28294 this._removalsTail = this._removalsTail._nextRemoved = record;
28295 }
28296 return record;
28297 }
28298 /** @internal */
28299 _addIdentityChange(record, item) {
28300 record.item = item;
28301 if (this._identityChangesTail === null) {
28302 this._identityChangesTail = this._identityChangesHead = record;
28303 }
28304 else {
28305 this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
28306 }
28307 return record;
28308 }
28309}
28310class IterableChangeRecord_ {
28311 constructor(item, trackById) {
28312 this.item = item;
28313 this.trackById = trackById;
28314 this.currentIndex = null;
28315 this.previousIndex = null;
28316 /** @internal */
28317 this._nextPrevious = null;
28318 /** @internal */
28319 this._prev = null;
28320 /** @internal */
28321 this._next = null;
28322 /** @internal */
28323 this._prevDup = null;
28324 /** @internal */
28325 this._nextDup = null;
28326 /** @internal */
28327 this._prevRemoved = null;
28328 /** @internal */
28329 this._nextRemoved = null;
28330 /** @internal */
28331 this._nextAdded = null;
28332 /** @internal */
28333 this._nextMoved = null;
28334 /** @internal */
28335 this._nextIdentityChange = null;
28336 }
28337}
28338// A linked list of IterableChangeRecords with the same IterableChangeRecord_.item
28339class _DuplicateItemRecordList {
28340 constructor() {
28341 /** @internal */
28342 this._head = null;
28343 /** @internal */
28344 this._tail = null;
28345 }
28346 /**
28347 * Append the record to the list of duplicates.
28348 *
28349 * Note: by design all records in the list of duplicates hold the same value in record.item.
28350 */
28351 add(record) {
28352 if (this._head === null) {
28353 this._head = this._tail = record;
28354 record._nextDup = null;
28355 record._prevDup = null;
28356 }
28357 else {
28358 // TODO(vicb):
28359 // assert(record.item == _head.item ||
28360 // record.item is num && record.item.isNaN && _head.item is num && _head.item.isNaN);
28361 this._tail._nextDup = record;
28362 record._prevDup = this._tail;
28363 record._nextDup = null;
28364 this._tail = record;
28365 }
28366 }
28367 // Returns a IterableChangeRecord_ having IterableChangeRecord_.trackById == trackById and
28368 // IterableChangeRecord_.currentIndex >= atOrAfterIndex
28369 get(trackById, atOrAfterIndex) {
28370 let record;
28371 for (record = this._head; record !== null; record = record._nextDup) {
28372 if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex) &&
28373 Object.is(record.trackById, trackById)) {
28374 return record;
28375 }
28376 }
28377 return null;
28378 }
28379 /**
28380 * Remove one {@link IterableChangeRecord_} from the list of duplicates.
28381 *
28382 * Returns whether the list of duplicates is empty.
28383 */
28384 remove(record) {
28385 // TODO(vicb):
28386 // assert(() {
28387 // // verify that the record being removed is in the list.
28388 // for (IterableChangeRecord_ cursor = _head; cursor != null; cursor = cursor._nextDup) {
28389 // if (identical(cursor, record)) return true;
28390 // }
28391 // return false;
28392 //});
28393 const prev = record._prevDup;
28394 const next = record._nextDup;
28395 if (prev === null) {
28396 this._head = next;
28397 }
28398 else {
28399 prev._nextDup = next;
28400 }
28401 if (next === null) {
28402 this._tail = prev;
28403 }
28404 else {
28405 next._prevDup = prev;
28406 }
28407 return this._head === null;
28408 }
28409}
28410class _DuplicateMap {
28411 constructor() {
28412 this.map = new Map();
28413 }
28414 put(record) {
28415 const key = record.trackById;
28416 let duplicates = this.map.get(key);
28417 if (!duplicates) {
28418 duplicates = new _DuplicateItemRecordList();
28419 this.map.set(key, duplicates);
28420 }
28421 duplicates.add(record);
28422 }
28423 /**
28424 * Retrieve the `value` using key. Because the IterableChangeRecord_ value may be one which we
28425 * have already iterated over, we use the `atOrAfterIndex` to pretend it is not there.
28426 *
28427 * Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we
28428 * have any more `a`s needs to return the second `a`.
28429 */
28430 get(trackById, atOrAfterIndex) {
28431 const key = trackById;
28432 const recordList = this.map.get(key);
28433 return recordList ? recordList.get(trackById, atOrAfterIndex) : null;
28434 }
28435 /**
28436 * Removes a {@link IterableChangeRecord_} from the list of duplicates.
28437 *
28438 * The list of duplicates also is removed from the map if it gets empty.
28439 */
28440 remove(record) {
28441 const key = record.trackById;
28442 const recordList = this.map.get(key);
28443 // Remove the list of duplicates when it gets empty
28444 if (recordList.remove(record)) {
28445 this.map.delete(key);
28446 }
28447 return record;
28448 }
28449 get isEmpty() {
28450 return this.map.size === 0;
28451 }
28452 clear() {
28453 this.map.clear();
28454 }
28455}
28456function getPreviousIndex(item, addRemoveOffset, moveOffsets) {
28457 const previousIndex = item.previousIndex;
28458 if (previousIndex === null)
28459 return previousIndex;
28460 let moveOffset = 0;
28461 if (moveOffsets && previousIndex < moveOffsets.length) {
28462 moveOffset = moveOffsets[previousIndex];
28463 }
28464 return previousIndex + addRemoveOffset + moveOffset;
28465}
28466
28467/**
28468 * @license
28469 * Copyright Google LLC All Rights Reserved.
28470 *
28471 * Use of this source code is governed by an MIT-style license that can be
28472 * found in the LICENSE file at https://angular.io/license
28473 */
28474class DefaultKeyValueDifferFactory {
28475 constructor() { }
28476 supports(obj) {
28477 return obj instanceof Map || isJsObject(obj);
28478 }
28479 create() {
28480 return new DefaultKeyValueDiffer();
28481 }
28482}
28483class DefaultKeyValueDiffer {
28484 constructor() {
28485 this._records = new Map();
28486 this._mapHead = null;
28487 // _appendAfter is used in the check loop
28488 this._appendAfter = null;
28489 this._previousMapHead = null;
28490 this._changesHead = null;
28491 this._changesTail = null;
28492 this._additionsHead = null;
28493 this._additionsTail = null;
28494 this._removalsHead = null;
28495 this._removalsTail = null;
28496 }
28497 get isDirty() {
28498 return this._additionsHead !== null || this._changesHead !== null ||
28499 this._removalsHead !== null;
28500 }
28501 forEachItem(fn) {
28502 let record;
28503 for (record = this._mapHead; record !== null; record = record._next) {
28504 fn(record);
28505 }
28506 }
28507 forEachPreviousItem(fn) {
28508 let record;
28509 for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {
28510 fn(record);
28511 }
28512 }
28513 forEachChangedItem(fn) {
28514 let record;
28515 for (record = this._changesHead; record !== null; record = record._nextChanged) {
28516 fn(record);
28517 }
28518 }
28519 forEachAddedItem(fn) {
28520 let record;
28521 for (record = this._additionsHead; record !== null; record = record._nextAdded) {
28522 fn(record);
28523 }
28524 }
28525 forEachRemovedItem(fn) {
28526 let record;
28527 for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
28528 fn(record);
28529 }
28530 }
28531 diff(map) {
28532 if (!map) {
28533 map = new Map();
28534 }
28535 else if (!(map instanceof Map || isJsObject(map))) {
28536 throw new Error(`Error trying to diff '${stringify(map)}'. Only maps and objects are allowed`);
28537 }
28538 return this.check(map) ? this : null;
28539 }
28540 onDestroy() { }
28541 /**
28542 * Check the current state of the map vs the previous.
28543 * The algorithm is optimised for when the keys do no change.
28544 */
28545 check(map) {
28546 this._reset();
28547 let insertBefore = this._mapHead;
28548 this._appendAfter = null;
28549 this._forEach(map, (value, key) => {
28550 if (insertBefore && insertBefore.key === key) {
28551 this._maybeAddToChanges(insertBefore, value);
28552 this._appendAfter = insertBefore;
28553 insertBefore = insertBefore._next;
28554 }
28555 else {
28556 const record = this._getOrCreateRecordForKey(key, value);
28557 insertBefore = this._insertBeforeOrAppend(insertBefore, record);
28558 }
28559 });
28560 // Items remaining at the end of the list have been deleted
28561 if (insertBefore) {
28562 if (insertBefore._prev) {
28563 insertBefore._prev._next = null;
28564 }
28565 this._removalsHead = insertBefore;
28566 for (let record = insertBefore; record !== null; record = record._nextRemoved) {
28567 if (record === this._mapHead) {
28568 this._mapHead = null;
28569 }
28570 this._records.delete(record.key);
28571 record._nextRemoved = record._next;
28572 record.previousValue = record.currentValue;
28573 record.currentValue = null;
28574 record._prev = null;
28575 record._next = null;
28576 }
28577 }
28578 // Make sure tails have no next records from previous runs
28579 if (this._changesTail)
28580 this._changesTail._nextChanged = null;
28581 if (this._additionsTail)
28582 this._additionsTail._nextAdded = null;
28583 return this.isDirty;
28584 }
28585 /**
28586 * Inserts a record before `before` or append at the end of the list when `before` is null.
28587 *
28588 * Notes:
28589 * - This method appends at `this._appendAfter`,
28590 * - This method updates `this._appendAfter`,
28591 * - The return value is the new value for the insertion pointer.
28592 */
28593 _insertBeforeOrAppend(before, record) {
28594 if (before) {
28595 const prev = before._prev;
28596 record._next = before;
28597 record._prev = prev;
28598 before._prev = record;
28599 if (prev) {
28600 prev._next = record;
28601 }
28602 if (before === this._mapHead) {
28603 this._mapHead = record;
28604 }
28605 this._appendAfter = before;
28606 return before;
28607 }
28608 if (this._appendAfter) {
28609 this._appendAfter._next = record;
28610 record._prev = this._appendAfter;
28611 }
28612 else {
28613 this._mapHead = record;
28614 }
28615 this._appendAfter = record;
28616 return null;
28617 }
28618 _getOrCreateRecordForKey(key, value) {
28619 if (this._records.has(key)) {
28620 const record = this._records.get(key);
28621 this._maybeAddToChanges(record, value);
28622 const prev = record._prev;
28623 const next = record._next;
28624 if (prev) {
28625 prev._next = next;
28626 }
28627 if (next) {
28628 next._prev = prev;
28629 }
28630 record._next = null;
28631 record._prev = null;
28632 return record;
28633 }
28634 const record = new KeyValueChangeRecord_(key);
28635 this._records.set(key, record);
28636 record.currentValue = value;
28637 this._addToAdditions(record);
28638 return record;
28639 }
28640 /** @internal */
28641 _reset() {
28642 if (this.isDirty) {
28643 let record;
28644 // let `_previousMapHead` contain the state of the map before the changes
28645 this._previousMapHead = this._mapHead;
28646 for (record = this._previousMapHead; record !== null; record = record._next) {
28647 record._nextPrevious = record._next;
28648 }
28649 // Update `record.previousValue` with the value of the item before the changes
28650 // We need to update all changed items (that's those which have been added and changed)
28651 for (record = this._changesHead; record !== null; record = record._nextChanged) {
28652 record.previousValue = record.currentValue;
28653 }
28654 for (record = this._additionsHead; record != null; record = record._nextAdded) {
28655 record.previousValue = record.currentValue;
28656 }
28657 this._changesHead = this._changesTail = null;
28658 this._additionsHead = this._additionsTail = null;
28659 this._removalsHead = null;
28660 }
28661 }
28662 // Add the record or a given key to the list of changes only when the value has actually changed
28663 _maybeAddToChanges(record, newValue) {
28664 if (!Object.is(newValue, record.currentValue)) {
28665 record.previousValue = record.currentValue;
28666 record.currentValue = newValue;
28667 this._addToChanges(record);
28668 }
28669 }
28670 _addToAdditions(record) {
28671 if (this._additionsHead === null) {
28672 this._additionsHead = this._additionsTail = record;
28673 }
28674 else {
28675 this._additionsTail._nextAdded = record;
28676 this._additionsTail = record;
28677 }
28678 }
28679 _addToChanges(record) {
28680 if (this._changesHead === null) {
28681 this._changesHead = this._changesTail = record;
28682 }
28683 else {
28684 this._changesTail._nextChanged = record;
28685 this._changesTail = record;
28686 }
28687 }
28688 /** @internal */
28689 _forEach(obj, fn) {
28690 if (obj instanceof Map) {
28691 obj.forEach(fn);
28692 }
28693 else {
28694 Object.keys(obj).forEach(k => fn(obj[k], k));
28695 }
28696 }
28697}
28698class KeyValueChangeRecord_ {
28699 constructor(key) {
28700 this.key = key;
28701 this.previousValue = null;
28702 this.currentValue = null;
28703 /** @internal */
28704 this._nextPrevious = null;
28705 /** @internal */
28706 this._next = null;
28707 /** @internal */
28708 this._prev = null;
28709 /** @internal */
28710 this._nextAdded = null;
28711 /** @internal */
28712 this._nextRemoved = null;
28713 /** @internal */
28714 this._nextChanged = null;
28715 }
28716}
28717
28718/**
28719 * @license
28720 * Copyright Google LLC All Rights Reserved.
28721 *
28722 * Use of this source code is governed by an MIT-style license that can be
28723 * found in the LICENSE file at https://angular.io/license
28724 */
28725function defaultIterableDiffersFactory() {
28726 return new IterableDiffers([new DefaultIterableDifferFactory()]);
28727}
28728/**
28729 * A repository of different iterable diffing strategies used by NgFor, NgClass, and others.
28730 *
28731 * @publicApi
28732 */
28733class IterableDiffers {
28734 constructor(factories) {
28735 this.factories = factories;
28736 }
28737 static create(factories, parent) {
28738 if (parent != null) {
28739 const copied = parent.factories.slice();
28740 factories = factories.concat(copied);
28741 }
28742 return new IterableDiffers(factories);
28743 }
28744 /**
28745 * Takes an array of {@link IterableDifferFactory} and returns a provider used to extend the
28746 * inherited {@link IterableDiffers} instance with the provided factories and return a new
28747 * {@link IterableDiffers} instance.
28748 *
28749 * @usageNotes
28750 * ### Example
28751 *
28752 * The following example shows how to extend an existing list of factories,
28753 * which will only be applied to the injector for this component and its children.
28754 * This step is all that's required to make a new {@link IterableDiffer} available.
28755 *
28756 * ```
28757 * @Component({
28758 * viewProviders: [
28759 * IterableDiffers.extend([new ImmutableListDiffer()])
28760 * ]
28761 * })
28762 * ```
28763 */
28764 static extend(factories) {
28765 return {
28766 provide: IterableDiffers,
28767 useFactory: (parent) => {
28768 // if parent is null, it means that we are in the root injector and we have just overridden
28769 // the default injection mechanism for IterableDiffers, in such a case just assume
28770 // `defaultIterableDiffersFactory`.
28771 return IterableDiffers.create(factories, parent || defaultIterableDiffersFactory());
28772 },
28773 // Dependency technically isn't optional, but we can provide a better error message this way.
28774 deps: [[IterableDiffers, new SkipSelf(), new Optional()]]
28775 };
28776 }
28777 find(iterable) {
28778 const factory = this.factories.find(f => f.supports(iterable));
28779 if (factory != null) {
28780 return factory;
28781 }
28782 else {
28783 throw new Error(`Cannot find a differ supporting object '${iterable}' of type '${getTypeNameForDebugging(iterable)}'`);
28784 }
28785 }
28786}
28787/** @nocollapse */
28788IterableDiffers.ɵprov = ɵɵdefineInjectable({ token: IterableDiffers, providedIn: 'root', factory: defaultIterableDiffersFactory });
28789function getTypeNameForDebugging(type) {
28790 return type['name'] || typeof type;
28791}
28792
28793/**
28794 * @license
28795 * Copyright Google LLC All Rights Reserved.
28796 *
28797 * Use of this source code is governed by an MIT-style license that can be
28798 * found in the LICENSE file at https://angular.io/license
28799 */
28800function defaultKeyValueDiffersFactory() {
28801 return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
28802}
28803/**
28804 * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
28805 *
28806 * @publicApi
28807 */
28808class KeyValueDiffers {
28809 constructor(factories) {
28810 this.factories = factories;
28811 }
28812 static create(factories, parent) {
28813 if (parent) {
28814 const copied = parent.factories.slice();
28815 factories = factories.concat(copied);
28816 }
28817 return new KeyValueDiffers(factories);
28818 }
28819 /**
28820 * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the
28821 * inherited {@link KeyValueDiffers} instance with the provided factories and return a new
28822 * {@link KeyValueDiffers} instance.
28823 *
28824 * @usageNotes
28825 * ### Example
28826 *
28827 * The following example shows how to extend an existing list of factories,
28828 * which will only be applied to the injector for this component and its children.
28829 * This step is all that's required to make a new {@link KeyValueDiffer} available.
28830 *
28831 * ```
28832 * @Component({
28833 * viewProviders: [
28834 * KeyValueDiffers.extend([new ImmutableMapDiffer()])
28835 * ]
28836 * })
28837 * ```
28838 */
28839 static extend(factories) {
28840 return {
28841 provide: KeyValueDiffers,
28842 useFactory: (parent) => {
28843 // if parent is null, it means that we are in the root injector and we have just overridden
28844 // the default injection mechanism for KeyValueDiffers, in such a case just assume
28845 // `defaultKeyValueDiffersFactory`.
28846 return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
28847 },
28848 // Dependency technically isn't optional, but we can provide a better error message this way.
28849 deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
28850 };
28851 }
28852 find(kv) {
28853 const factory = this.factories.find(f => f.supports(kv));
28854 if (factory) {
28855 return factory;
28856 }
28857 throw new Error(`Cannot find a differ supporting object '${kv}'`);
28858 }
28859}
28860/** @nocollapse */
28861KeyValueDiffers.ɵprov = ɵɵdefineInjectable({ token: KeyValueDiffers, providedIn: 'root', factory: defaultKeyValueDiffersFactory });
28862
28863/**
28864 * @license
28865 * Copyright Google LLC All Rights Reserved.
28866 *
28867 * Use of this source code is governed by an MIT-style license that can be
28868 * found in the LICENSE file at https://angular.io/license
28869 */
28870/**
28871 * Structural diffing for `Object`s and `Map`s.
28872 */
28873const keyValDiff = [new DefaultKeyValueDifferFactory()];
28874/**
28875 * Structural diffing for `Iterable` types such as `Array`s.
28876 */
28877const iterableDiff = [new DefaultIterableDifferFactory()];
28878const defaultIterableDiffers = new IterableDiffers(iterableDiff);
28879const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
28880
28881/**
28882 * @license
28883 * Copyright Google LLC All Rights Reserved.
28884 *
28885 * Use of this source code is governed by an MIT-style license that can be
28886 * found in the LICENSE file at https://angular.io/license
28887 */
28888
28889/**
28890 * @license
28891 * Copyright Google LLC All Rights Reserved.
28892 *
28893 * Use of this source code is governed by an MIT-style license that can be
28894 * found in the LICENSE file at https://angular.io/license
28895 */
28896const _CORE_PLATFORM_PROVIDERS = [
28897 // Set a default platform name for platforms that don't set it explicitly.
28898 { provide: PLATFORM_ID, useValue: 'unknown' },
28899 { provide: PlatformRef, deps: [Injector] },
28900 { provide: TestabilityRegistry, deps: [] },
28901 { provide: Console, deps: [] },
28902];
28903/**
28904 * This platform has to be included in any other platform
28905 *
28906 * @publicApi
28907 */
28908const platformCore = createPlatformFactory(null, 'core', _CORE_PLATFORM_PROVIDERS);
28909
28910/**
28911 * @license
28912 * Copyright Google LLC All Rights Reserved.
28913 *
28914 * Use of this source code is governed by an MIT-style license that can be
28915 * found in the LICENSE file at https://angular.io/license
28916 */
28917function _iterableDiffersFactory() {
28918 return defaultIterableDiffers;
28919}
28920function _keyValueDiffersFactory() {
28921 return defaultKeyValueDiffers;
28922}
28923function _localeFactory(locale) {
28924 return locale || getGlobalLocale();
28925}
28926/**
28927 * Work out the locale from the potential global properties.
28928 *
28929 * * Closure Compiler: use `goog.getLocale()`.
28930 * * Ivy enabled: use `$localize.locale`
28931 */
28932function getGlobalLocale() {
28933 if (typeof ngI18nClosureMode !== 'undefined' && ngI18nClosureMode &&
28934 typeof goog !== 'undefined' && goog.getLocale() !== 'en') {
28935 // * The default `goog.getLocale()` value is `en`, while Angular used `en-US`.
28936 // * In order to preserve backwards compatibility, we use Angular default value over
28937 // Closure Compiler's one.
28938 return goog.getLocale();
28939 }
28940 else {
28941 // KEEP `typeof $localize !== 'undefined' && $localize.locale` IN SYNC WITH THE LOCALIZE
28942 // COMPILE-TIME INLINER.
28943 //
28944 // * During compile time inlining of translations the expression will be replaced
28945 // with a string literal that is the current locale. Other forms of this expression are not
28946 // guaranteed to be replaced.
28947 //
28948 // * During runtime translation evaluation, the developer is required to set `$localize.locale`
28949 // if required, or just to provide their own `LOCALE_ID` provider.
28950 return (ivyEnabled && typeof $localize !== 'undefined' && $localize.locale) ||
28951 DEFAULT_LOCALE_ID;
28952 }
28953}
28954/**
28955 * A built-in [dependency injection token](guide/glossary#di-token)
28956 * that is used to configure the root injector for bootstrapping.
28957 */
28958const APPLICATION_MODULE_PROVIDERS = [
28959 {
28960 provide: ApplicationRef,
28961 useClass: ApplicationRef,
28962 deps: [NgZone, Injector, ErrorHandler, ComponentFactoryResolver$1, ApplicationInitStatus]
28963 },
28964 { provide: SCHEDULER, deps: [NgZone], useFactory: zoneSchedulerFactory },
28965 {
28966 provide: ApplicationInitStatus,
28967 useClass: ApplicationInitStatus,
28968 deps: [[new Optional(), APP_INITIALIZER]]
28969 },
28970 { provide: Compiler, useClass: Compiler, deps: [] },
28971 APP_ID_RANDOM_PROVIDER,
28972 { provide: IterableDiffers, useFactory: _iterableDiffersFactory, deps: [] },
28973 { provide: KeyValueDiffers, useFactory: _keyValueDiffersFactory, deps: [] },
28974 {
28975 provide: LOCALE_ID,
28976 useFactory: _localeFactory,
28977 deps: [[new Inject(LOCALE_ID), new Optional(), new SkipSelf()]]
28978 },
28979 { provide: DEFAULT_CURRENCY_CODE, useValue: USD_CURRENCY_CODE },
28980];
28981/**
28982 * Schedule work at next available slot.
28983 *
28984 * In Ivy this is just `requestAnimationFrame`. For compatibility reasons when bootstrapped
28985 * using `platformRef.bootstrap` we need to use `NgZone.onStable` as the scheduling mechanism.
28986 * This overrides the scheduling mechanism in Ivy to `NgZone.onStable`.
28987 *
28988 * @param ngZone NgZone to use for scheduling.
28989 */
28990function zoneSchedulerFactory(ngZone) {
28991 let queue = [];
28992 ngZone.onStable.subscribe(() => {
28993 while (queue.length) {
28994 queue.pop()();
28995 }
28996 });
28997 return function (fn) {
28998 queue.push(fn);
28999 };
29000}
29001/**
29002 * Configures the root injector for an app with
29003 * providers of `@angular/core` dependencies that `ApplicationRef` needs
29004 * to bootstrap components.
29005 *
29006 * Re-exported by `BrowserModule`, which is included automatically in the root
29007 * `AppModule` when you create a new app with the CLI `new` command.
29008 *
29009 * @publicApi
29010 */
29011class ApplicationModule {
29012 // Inject ApplicationRef to make it eager...
29013 constructor(appRef) { }
29014}
29015ApplicationModule.ɵfac = function ApplicationModule_Factory(t) { return new (t || ApplicationModule)(ɵɵinject(ApplicationRef)); };
29016ApplicationModule.ɵmod = /*@__PURE__*/ ɵɵdefineNgModule({ type: ApplicationModule });
29017ApplicationModule.ɵinj = /*@__PURE__*/ ɵɵdefineInjector({ providers: APPLICATION_MODULE_PROVIDERS });
29018(function () { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
29019 type: NgModule,
29020 args: [{ providers: APPLICATION_MODULE_PROVIDERS }]
29021 }], function () { return [{ type: ApplicationRef }]; }, null); })();
29022
29023/**
29024 * @license
29025 * Copyright Google LLC All Rights Reserved.
29026 *
29027 * Use of this source code is governed by an MIT-style license that can be
29028 * found in the LICENSE file at https://angular.io/license
29029 */
29030// Called before each cycle of a view's check to detect whether this is in the
29031// initState for which we need to call ngOnInit, ngAfterContentInit or ngAfterViewInit
29032// lifecycle methods. Returns true if this check cycle should call lifecycle
29033// methods.
29034function shiftInitState(view, priorInitState, newInitState) {
29035 // Only update the InitState if we are currently in the prior state.
29036 // For example, only move into CallingInit if we are in BeforeInit. Only
29037 // move into CallingContentInit if we are in CallingInit. Normally this will
29038 // always be true because of how checkCycle is called in checkAndUpdateView.
29039 // However, if checkAndUpdateView is called recursively or if an exception is
29040 // thrown while checkAndUpdateView is running, checkAndUpdateView starts over
29041 // from the beginning. This ensures the state is monotonically increasing,
29042 // terminating in the AfterInit state, which ensures the Init methods are called
29043 // at least once and only once.
29044 const state = view.state;
29045 const initState = state & 1792 /* InitState_Mask */;
29046 if (initState === priorInitState) {
29047 view.state = (state & ~1792 /* InitState_Mask */) | newInitState;
29048 view.initIndex = -1;
29049 return true;
29050 }
29051 return initState === newInitState;
29052}
29053// Returns true if the lifecycle init method should be called for the node with
29054// the given init index.
29055function shouldCallLifecycleInitHook(view, initState, index) {
29056 if ((view.state & 1792 /* InitState_Mask */) === initState && view.initIndex <= index) {
29057 view.initIndex = index + 1;
29058 return true;
29059 }
29060 return false;
29061}
29062/**
29063 * Node instance data.
29064 *
29065 * We have a separate type per NodeType to save memory
29066 * (TextData | ElementData | ProviderData | PureExpressionData | QueryList<any>)
29067 *
29068 * To keep our code monomorphic,
29069 * we prohibit using `NodeData` directly but enforce the use of accessors (`asElementData`, ...).
29070 * This way, no usage site can get a `NodeData` from view.nodes and then use it for different
29071 * purposes.
29072 */
29073class NodeData {
29074}
29075/**
29076 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29077 */
29078function asTextData(view, index) {
29079 return view.nodes[index];
29080}
29081/**
29082 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29083 */
29084function asElementData(view, index) {
29085 return view.nodes[index];
29086}
29087/**
29088 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29089 */
29090function asProviderData(view, index) {
29091 return view.nodes[index];
29092}
29093/**
29094 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29095 */
29096function asPureExpressionData(view, index) {
29097 return view.nodes[index];
29098}
29099/**
29100 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29101 */
29102function asQueryList(view, index) {
29103 return view.nodes[index];
29104}
29105class DebugContext {
29106}
29107/**
29108 * This object is used to prevent cycles in the source files and to have a place where
29109 * debug mode can hook it. It is lazily filled when `isDevMode` is known.
29110 */
29111const Services = {
29112 setCurrentNode: undefined,
29113 createRootView: undefined,
29114 createEmbeddedView: undefined,
29115 createComponentView: undefined,
29116 createNgModuleRef: undefined,
29117 overrideProvider: undefined,
29118 overrideComponentView: undefined,
29119 clearOverrides: undefined,
29120 checkAndUpdateView: undefined,
29121 checkNoChangesView: undefined,
29122 destroyView: undefined,
29123 resolveDep: undefined,
29124 createDebugContext: undefined,
29125 handleEvent: undefined,
29126 updateDirectives: undefined,
29127 updateRenderer: undefined,
29128 dirtyParentQueries: undefined,
29129};
29130
29131/**
29132 * @license
29133 * Copyright Google LLC All Rights Reserved.
29134 *
29135 * Use of this source code is governed by an MIT-style license that can be
29136 * found in the LICENSE file at https://angular.io/license
29137 */
29138function expressionChangedAfterItHasBeenCheckedError(context, oldValue, currValue, isFirstCheck) {
29139 let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
29140 if (isFirstCheck) {
29141 msg +=
29142 ` It seems like the view has been created after its parent and its children have been dirty checked.` +
29143 ` Has it been created in a change detection hook ?`;
29144 }
29145 return viewDebugError(msg, context);
29146}
29147function viewWrappedDebugError(err, context) {
29148 if (!(err instanceof Error)) {
29149 // errors that are not Error instances don't have a stack,
29150 // so it is ok to wrap them into a new Error object...
29151 err = new Error(err.toString());
29152 }
29153 _addDebugContext(err, context);
29154 return err;
29155}
29156function viewDebugError(msg, context) {
29157 const err = new Error(msg);
29158 _addDebugContext(err, context);
29159 return err;
29160}
29161function _addDebugContext(err, context) {
29162 err[ERROR_DEBUG_CONTEXT] = context;
29163 err[ERROR_LOGGER] = context.logError.bind(context);
29164}
29165function isViewDebugError(err) {
29166 return !!getDebugContext(err);
29167}
29168function viewDestroyedError(action) {
29169 return new Error(`ViewDestroyedError: Attempt to use a destroyed view: ${action}`);
29170}
29171
29172/**
29173 * @license
29174 * Copyright Google LLC All Rights Reserved.
29175 *
29176 * Use of this source code is governed by an MIT-style license that can be
29177 * found in the LICENSE file at https://angular.io/license
29178 */
29179const NOOP = () => { };
29180const _tokenKeyCache = new Map();
29181function tokenKey(token) {
29182 let key = _tokenKeyCache.get(token);
29183 if (!key) {
29184 key = stringify(token) + '_' + _tokenKeyCache.size;
29185 _tokenKeyCache.set(token, key);
29186 }
29187 return key;
29188}
29189const UNDEFINED_RENDERER_TYPE_ID = '$$undefined';
29190const EMPTY_RENDERER_TYPE_ID = '$$empty';
29191// Attention: this function is called as top level function.
29192// Putting any logic in here will destroy closure tree shaking!
29193function createRendererType2(values) {
29194 return {
29195 id: UNDEFINED_RENDERER_TYPE_ID,
29196 styles: values.styles,
29197 encapsulation: values.encapsulation,
29198 data: values.data
29199 };
29200}
29201let _renderCompCount = 0;
29202function resolveRendererType2(type) {
29203 if (type && type.id === UNDEFINED_RENDERER_TYPE_ID) {
29204 // first time we see this RendererType2. Initialize it...
29205 const isFilled = ((type.encapsulation != null && type.encapsulation !== ViewEncapsulation$1.None) ||
29206 type.styles.length || Object.keys(type.data).length);
29207 if (isFilled) {
29208 type.id = `c${_renderCompCount++}`;
29209 }
29210 else {
29211 type.id = EMPTY_RENDERER_TYPE_ID;
29212 }
29213 }
29214 if (type && type.id === EMPTY_RENDERER_TYPE_ID) {
29215 type = null;
29216 }
29217 return type || null;
29218}
29219function checkBinding(view, def, bindingIdx, value) {
29220 const oldValues = view.oldValues;
29221 if ((view.state & 2 /* FirstCheck */) ||
29222 !Object.is(oldValues[def.bindingIndex + bindingIdx], value)) {
29223 return true;
29224 }
29225 return false;
29226}
29227function checkAndUpdateBinding(view, def, bindingIdx, value) {
29228 if (checkBinding(view, def, bindingIdx, value)) {
29229 view.oldValues[def.bindingIndex + bindingIdx] = value;
29230 return true;
29231 }
29232 return false;
29233}
29234function checkBindingNoChanges(view, def, bindingIdx, value) {
29235 const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
29236 if ((view.state & 1 /* BeforeFirstCheck */) || !devModeEqual(oldValue, value)) {
29237 const bindingName = def.bindings[bindingIdx].name;
29238 throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, def.nodeIndex), `${bindingName}: ${oldValue}`, `${bindingName}: ${value}`, (view.state & 1 /* BeforeFirstCheck */) !== 0);
29239 }
29240}
29241function markParentViewsForCheck(view) {
29242 let currView = view;
29243 while (currView) {
29244 if (currView.def.flags & 2 /* OnPush */) {
29245 currView.state |= 8 /* ChecksEnabled */;
29246 }
29247 currView = currView.viewContainerParent || currView.parent;
29248 }
29249}
29250function markParentViewsForCheckProjectedViews(view, endView) {
29251 let currView = view;
29252 while (currView && currView !== endView) {
29253 currView.state |= 64 /* CheckProjectedViews */;
29254 currView = currView.viewContainerParent || currView.parent;
29255 }
29256}
29257function dispatchEvent(view, nodeIndex, eventName, event) {
29258 try {
29259 const nodeDef = view.def.nodes[nodeIndex];
29260 const startView = nodeDef.flags & 33554432 /* ComponentView */ ?
29261 asElementData(view, nodeIndex).componentView :
29262 view;
29263 markParentViewsForCheck(startView);
29264 return Services.handleEvent(view, nodeIndex, eventName, event);
29265 }
29266 catch (e) {
29267 // Attention: Don't rethrow, as it would cancel Observable subscriptions!
29268 view.root.errorHandler.handleError(e);
29269 }
29270}
29271function declaredViewContainer(view) {
29272 if (view.parent) {
29273 const parentView = view.parent;
29274 return asElementData(parentView, view.parentNodeDef.nodeIndex);
29275 }
29276 return null;
29277}
29278/**
29279 * for component views, this is the host element.
29280 * for embedded views, this is the index of the parent node
29281 * that contains the view container.
29282 */
29283function viewParentEl(view) {
29284 const parentView = view.parent;
29285 if (parentView) {
29286 return view.parentNodeDef.parent;
29287 }
29288 else {
29289 return null;
29290 }
29291}
29292function renderNode(view, def) {
29293 switch (def.flags & 201347067 /* Types */) {
29294 case 1 /* TypeElement */:
29295 return asElementData(view, def.nodeIndex).renderElement;
29296 case 2 /* TypeText */:
29297 return asTextData(view, def.nodeIndex).renderText;
29298 }
29299}
29300function elementEventFullName(target, name) {
29301 return target ? `${target}:${name}` : name;
29302}
29303function isComponentView(view) {
29304 return !!view.parent && !!(view.parentNodeDef.flags & 32768 /* Component */);
29305}
29306function isEmbeddedView(view) {
29307 return !!view.parent && !(view.parentNodeDef.flags & 32768 /* Component */);
29308}
29309function filterQueryId(queryId) {
29310 return 1 << (queryId % 32);
29311}
29312function splitMatchedQueriesDsl(matchedQueriesDsl) {
29313 const matchedQueries = {};
29314 let matchedQueryIds = 0;
29315 const references = {};
29316 if (matchedQueriesDsl) {
29317 matchedQueriesDsl.forEach(([queryId, valueType]) => {
29318 if (typeof queryId === 'number') {
29319 matchedQueries[queryId] = valueType;
29320 matchedQueryIds |= filterQueryId(queryId);
29321 }
29322 else {
29323 references[queryId] = valueType;
29324 }
29325 });
29326 }
29327 return { matchedQueries, references, matchedQueryIds };
29328}
29329function splitDepsDsl(deps, sourceName) {
29330 return deps.map(value => {
29331 let token;
29332 let flags;
29333 if (Array.isArray(value)) {
29334 [flags, token] = value;
29335 }
29336 else {
29337 flags = 0 /* None */;
29338 token = value;
29339 }
29340 if (token && (typeof token === 'function' || typeof token === 'object') && sourceName) {
29341 Object.defineProperty(token, SOURCE, { value: sourceName, configurable: true });
29342 }
29343 return { flags, token, tokenKey: tokenKey(token) };
29344 });
29345}
29346function getParentRenderElement(view, renderHost, def) {
29347 let renderParent = def.renderParent;
29348 if (renderParent) {
29349 if ((renderParent.flags & 1 /* TypeElement */) === 0 ||
29350 (renderParent.flags & 33554432 /* ComponentView */) === 0 ||
29351 (renderParent.element.componentRendererType &&
29352 (renderParent.element.componentRendererType.encapsulation ===
29353 ViewEncapsulation$1.ShadowDom ||
29354 // TODO(FW-2290): remove the `encapsulation === 1` fallback logic in v12.
29355 // @ts-ignore TODO: Remove as part of FW-2290. TS complains about us dealing with an enum
29356 // value that is not known (but previously was the value for ViewEncapsulation.Native)
29357 renderParent.element.componentRendererType.encapsulation === 1))) {
29358 // only children of non components, or children of components with native encapsulation should
29359 // be attached.
29360 return asElementData(view, def.renderParent.nodeIndex).renderElement;
29361 }
29362 }
29363 else {
29364 return renderHost;
29365 }
29366}
29367const DEFINITION_CACHE = new WeakMap();
29368function resolveDefinition(factory) {
29369 let value = DEFINITION_CACHE.get(factory);
29370 if (!value) {
29371 value = factory(() => NOOP);
29372 value.factory = factory;
29373 DEFINITION_CACHE.set(factory, value);
29374 }
29375 return value;
29376}
29377function rootRenderNodes(view) {
29378 const renderNodes = [];
29379 visitRootRenderNodes(view, 0 /* Collect */, undefined, undefined, renderNodes);
29380 return renderNodes;
29381}
29382function visitRootRenderNodes(view, action, parentNode, nextSibling, target) {
29383 // We need to re-compute the parent node in case the nodes have been moved around manually
29384 if (action === 3 /* RemoveChild */) {
29385 parentNode = view.renderer.parentNode(renderNode(view, view.def.lastRenderRootNode));
29386 }
29387 visitSiblingRenderNodes(view, action, 0, view.def.nodes.length - 1, parentNode, nextSibling, target);
29388}
29389function visitSiblingRenderNodes(view, action, startIndex, endIndex, parentNode, nextSibling, target) {
29390 for (let i = startIndex; i <= endIndex; i++) {
29391 const nodeDef = view.def.nodes[i];
29392 if (nodeDef.flags & (1 /* TypeElement */ | 2 /* TypeText */ | 8 /* TypeNgContent */)) {
29393 visitRenderNode(view, nodeDef, action, parentNode, nextSibling, target);
29394 }
29395 // jump to next sibling
29396 i += nodeDef.childCount;
29397 }
29398}
29399function visitProjectedRenderNodes(view, ngContentIndex, action, parentNode, nextSibling, target) {
29400 let compView = view;
29401 while (compView && !isComponentView(compView)) {
29402 compView = compView.parent;
29403 }
29404 const hostView = compView.parent;
29405 const hostElDef = viewParentEl(compView);
29406 const startIndex = hostElDef.nodeIndex + 1;
29407 const endIndex = hostElDef.nodeIndex + hostElDef.childCount;
29408 for (let i = startIndex; i <= endIndex; i++) {
29409 const nodeDef = hostView.def.nodes[i];
29410 if (nodeDef.ngContentIndex === ngContentIndex) {
29411 visitRenderNode(hostView, nodeDef, action, parentNode, nextSibling, target);
29412 }
29413 // jump to next sibling
29414 i += nodeDef.childCount;
29415 }
29416 if (!hostView.parent) {
29417 // a root view
29418 const projectedNodes = view.root.projectableNodes[ngContentIndex];
29419 if (projectedNodes) {
29420 for (let i = 0; i < projectedNodes.length; i++) {
29421 execRenderNodeAction(view, projectedNodes[i], action, parentNode, nextSibling, target);
29422 }
29423 }
29424 }
29425}
29426function visitRenderNode(view, nodeDef, action, parentNode, nextSibling, target) {
29427 if (nodeDef.flags & 8 /* TypeNgContent */) {
29428 visitProjectedRenderNodes(view, nodeDef.ngContent.index, action, parentNode, nextSibling, target);
29429 }
29430 else {
29431 const rn = renderNode(view, nodeDef);
29432 if (action === 3 /* RemoveChild */ && (nodeDef.flags & 33554432 /* ComponentView */) &&
29433 (nodeDef.bindingFlags & 48 /* CatSyntheticProperty */)) {
29434 // Note: we might need to do both actions.
29435 if (nodeDef.bindingFlags & (16 /* SyntheticProperty */)) {
29436 execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
29437 }
29438 if (nodeDef.bindingFlags & (32 /* SyntheticHostProperty */)) {
29439 const compView = asElementData(view, nodeDef.nodeIndex).componentView;
29440 execRenderNodeAction(compView, rn, action, parentNode, nextSibling, target);
29441 }
29442 }
29443 else {
29444 execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
29445 }
29446 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
29447 const embeddedViews = asElementData(view, nodeDef.nodeIndex).viewContainer._embeddedViews;
29448 for (let k = 0; k < embeddedViews.length; k++) {
29449 visitRootRenderNodes(embeddedViews[k], action, parentNode, nextSibling, target);
29450 }
29451 }
29452 if (nodeDef.flags & 1 /* TypeElement */ && !nodeDef.element.name) {
29453 visitSiblingRenderNodes(view, action, nodeDef.nodeIndex + 1, nodeDef.nodeIndex + nodeDef.childCount, parentNode, nextSibling, target);
29454 }
29455 }
29456}
29457function execRenderNodeAction(view, renderNode, action, parentNode, nextSibling, target) {
29458 const renderer = view.renderer;
29459 switch (action) {
29460 case 1 /* AppendChild */:
29461 renderer.appendChild(parentNode, renderNode);
29462 break;
29463 case 2 /* InsertBefore */:
29464 renderer.insertBefore(parentNode, renderNode, nextSibling);
29465 break;
29466 case 3 /* RemoveChild */:
29467 renderer.removeChild(parentNode, renderNode);
29468 break;
29469 case 0 /* Collect */:
29470 target.push(renderNode);
29471 break;
29472 }
29473}
29474const NS_PREFIX_RE = /^:([^:]+):(.+)$/;
29475function splitNamespace(name) {
29476 if (name[0] === ':') {
29477 const match = name.match(NS_PREFIX_RE);
29478 return [match[1], match[2]];
29479 }
29480 return ['', name];
29481}
29482function calcBindingFlags(bindings) {
29483 let flags = 0;
29484 for (let i = 0; i < bindings.length; i++) {
29485 flags |= bindings[i].flags;
29486 }
29487 return flags;
29488}
29489function interpolate(valueCount, constAndInterp) {
29490 let result = '';
29491 for (let i = 0; i < valueCount * 2; i = i + 2) {
29492 result = result + constAndInterp[i] + _toStringWithNull(constAndInterp[i + 1]);
29493 }
29494 return result + constAndInterp[valueCount * 2];
29495}
29496function inlineInterpolate(valueCount, c0, a1, c1, a2, c2, a3, c3, a4, c4, a5, c5, a6, c6, a7, c7, a8, c8, a9, c9) {
29497 switch (valueCount) {
29498 case 1:
29499 return c0 + _toStringWithNull(a1) + c1;
29500 case 2:
29501 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2;
29502 case 3:
29503 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29504 c3;
29505 case 4:
29506 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29507 c3 + _toStringWithNull(a4) + c4;
29508 case 5:
29509 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29510 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5;
29511 case 6:
29512 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29513 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) + c6;
29514 case 7:
29515 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29516 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
29517 c6 + _toStringWithNull(a7) + c7;
29518 case 8:
29519 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29520 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
29521 c6 + _toStringWithNull(a7) + c7 + _toStringWithNull(a8) + c8;
29522 case 9:
29523 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29524 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
29525 c6 + _toStringWithNull(a7) + c7 + _toStringWithNull(a8) + c8 + _toStringWithNull(a9) + c9;
29526 default:
29527 throw new Error(`Does not support more than 9 expressions`);
29528 }
29529}
29530function _toStringWithNull(v) {
29531 return v != null ? v.toString() : '';
29532}
29533const EMPTY_MAP = {};
29534
29535/**
29536 * @license
29537 * Copyright Google LLC All Rights Reserved.
29538 *
29539 * Use of this source code is governed by an MIT-style license that can be
29540 * found in the LICENSE file at https://angular.io/license
29541 */
29542function anchorDef(flags, matchedQueriesDsl, ngContentIndex, childCount, handleEvent, templateFactory) {
29543 flags |= 1 /* TypeElement */;
29544 const { matchedQueries, references, matchedQueryIds } = splitMatchedQueriesDsl(matchedQueriesDsl);
29545 const template = templateFactory ? resolveDefinition(templateFactory) : null;
29546 return {
29547 // will bet set by the view definition
29548 nodeIndex: -1,
29549 parent: null,
29550 renderParent: null,
29551 bindingIndex: -1,
29552 outputIndex: -1,
29553 // regular values
29554 flags,
29555 checkIndex: -1,
29556 childFlags: 0,
29557 directChildFlags: 0,
29558 childMatchedQueries: 0,
29559 matchedQueries,
29560 matchedQueryIds,
29561 references,
29562 ngContentIndex,
29563 childCount,
29564 bindings: [],
29565 bindingFlags: 0,
29566 outputs: [],
29567 element: {
29568 ns: null,
29569 name: null,
29570 attrs: null,
29571 template,
29572 componentProvider: null,
29573 componentView: null,
29574 componentRendererType: null,
29575 publicProviders: null,
29576 allProviders: null,
29577 handleEvent: handleEvent || NOOP
29578 },
29579 provider: null,
29580 text: null,
29581 query: null,
29582 ngContent: null
29583 };
29584}
29585function elementDef(checkIndex, flags, matchedQueriesDsl, ngContentIndex, childCount, namespaceAndName, fixedAttrs = [], bindings, outputs, handleEvent, componentView, componentRendererType) {
29586 if (!handleEvent) {
29587 handleEvent = NOOP;
29588 }
29589 const { matchedQueries, references, matchedQueryIds } = splitMatchedQueriesDsl(matchedQueriesDsl);
29590 let ns = null;
29591 let name = null;
29592 if (namespaceAndName) {
29593 [ns, name] = splitNamespace(namespaceAndName);
29594 }
29595 bindings = bindings || [];
29596 const bindingDefs = [];
29597 for (let i = 0; i < bindings.length; i++) {
29598 const [bindingFlags, namespaceAndName, suffixOrSecurityContext] = bindings[i];
29599 const [ns, name] = splitNamespace(namespaceAndName);
29600 let securityContext = undefined;
29601 let suffix = undefined;
29602 switch (bindingFlags & 15 /* Types */) {
29603 case 4 /* TypeElementStyle */:
29604 suffix = suffixOrSecurityContext;
29605 break;
29606 case 1 /* TypeElementAttribute */:
29607 case 8 /* TypeProperty */:
29608 securityContext = suffixOrSecurityContext;
29609 break;
29610 }
29611 bindingDefs[i] =
29612 { flags: bindingFlags, ns, name, nonMinifiedName: name, securityContext, suffix };
29613 }
29614 outputs = outputs || [];
29615 const outputDefs = [];
29616 for (let i = 0; i < outputs.length; i++) {
29617 const [target, eventName] = outputs[i];
29618 outputDefs[i] =
29619 { type: 0 /* ElementOutput */, target: target, eventName, propName: null };
29620 }
29621 fixedAttrs = fixedAttrs || [];
29622 const attrs = fixedAttrs.map(([namespaceAndName, value]) => {
29623 const [ns, name] = splitNamespace(namespaceAndName);
29624 return [ns, name, value];
29625 });
29626 componentRendererType = resolveRendererType2(componentRendererType);
29627 if (componentView) {
29628 flags |= 33554432 /* ComponentView */;
29629 }
29630 flags |= 1 /* TypeElement */;
29631 return {
29632 // will bet set by the view definition
29633 nodeIndex: -1,
29634 parent: null,
29635 renderParent: null,
29636 bindingIndex: -1,
29637 outputIndex: -1,
29638 // regular values
29639 checkIndex,
29640 flags,
29641 childFlags: 0,
29642 directChildFlags: 0,
29643 childMatchedQueries: 0,
29644 matchedQueries,
29645 matchedQueryIds,
29646 references,
29647 ngContentIndex,
29648 childCount,
29649 bindings: bindingDefs,
29650 bindingFlags: calcBindingFlags(bindingDefs),
29651 outputs: outputDefs,
29652 element: {
29653 ns,
29654 name,
29655 attrs,
29656 template: null,
29657 // will bet set by the view definition
29658 componentProvider: null,
29659 componentView: componentView || null,
29660 componentRendererType: componentRendererType,
29661 publicProviders: null,
29662 allProviders: null,
29663 handleEvent: handleEvent || NOOP,
29664 },
29665 provider: null,
29666 text: null,
29667 query: null,
29668 ngContent: null
29669 };
29670}
29671function createElement(view, renderHost, def) {
29672 const elDef = def.element;
29673 const rootSelectorOrNode = view.root.selectorOrNode;
29674 const renderer = view.renderer;
29675 let el;
29676 if (view.parent || !rootSelectorOrNode) {
29677 if (elDef.name) {
29678 el = renderer.createElement(elDef.name, elDef.ns);
29679 }
29680 else {
29681 el = renderer.createComment('');
29682 }
29683 const parentEl = getParentRenderElement(view, renderHost, def);
29684 if (parentEl) {
29685 renderer.appendChild(parentEl, el);
29686 }
29687 }
29688 else {
29689 // when using native Shadow DOM, do not clear the root element contents to allow slot projection
29690 const preserveContent = (!!elDef.componentRendererType &&
29691 elDef.componentRendererType.encapsulation === ViewEncapsulation$1.ShadowDom);
29692 el = renderer.selectRootElement(rootSelectorOrNode, preserveContent);
29693 }
29694 if (elDef.attrs) {
29695 for (let i = 0; i < elDef.attrs.length; i++) {
29696 const [ns, name, value] = elDef.attrs[i];
29697 renderer.setAttribute(el, name, value, ns);
29698 }
29699 }
29700 return el;
29701}
29702function listenToElementOutputs(view, compView, def, el) {
29703 for (let i = 0; i < def.outputs.length; i++) {
29704 const output = def.outputs[i];
29705 const handleEventClosure = renderEventHandlerClosure(view, def.nodeIndex, elementEventFullName(output.target, output.eventName));
29706 let listenTarget = output.target;
29707 let listenerView = view;
29708 if (output.target === 'component') {
29709 listenTarget = null;
29710 listenerView = compView;
29711 }
29712 const disposable = listenerView.renderer.listen(listenTarget || el, output.eventName, handleEventClosure);
29713 view.disposables[def.outputIndex + i] = disposable;
29714 }
29715}
29716function renderEventHandlerClosure(view, index, eventName) {
29717 return (event) => dispatchEvent(view, index, eventName, event);
29718}
29719function checkAndUpdateElementInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
29720 const bindLen = def.bindings.length;
29721 let changed = false;
29722 if (bindLen > 0 && checkAndUpdateElementValue(view, def, 0, v0))
29723 changed = true;
29724 if (bindLen > 1 && checkAndUpdateElementValue(view, def, 1, v1))
29725 changed = true;
29726 if (bindLen > 2 && checkAndUpdateElementValue(view, def, 2, v2))
29727 changed = true;
29728 if (bindLen > 3 && checkAndUpdateElementValue(view, def, 3, v3))
29729 changed = true;
29730 if (bindLen > 4 && checkAndUpdateElementValue(view, def, 4, v4))
29731 changed = true;
29732 if (bindLen > 5 && checkAndUpdateElementValue(view, def, 5, v5))
29733 changed = true;
29734 if (bindLen > 6 && checkAndUpdateElementValue(view, def, 6, v6))
29735 changed = true;
29736 if (bindLen > 7 && checkAndUpdateElementValue(view, def, 7, v7))
29737 changed = true;
29738 if (bindLen > 8 && checkAndUpdateElementValue(view, def, 8, v8))
29739 changed = true;
29740 if (bindLen > 9 && checkAndUpdateElementValue(view, def, 9, v9))
29741 changed = true;
29742 return changed;
29743}
29744function checkAndUpdateElementDynamic(view, def, values) {
29745 let changed = false;
29746 for (let i = 0; i < values.length; i++) {
29747 if (checkAndUpdateElementValue(view, def, i, values[i]))
29748 changed = true;
29749 }
29750 return changed;
29751}
29752function checkAndUpdateElementValue(view, def, bindingIdx, value) {
29753 if (!checkAndUpdateBinding(view, def, bindingIdx, value)) {
29754 return false;
29755 }
29756 const binding = def.bindings[bindingIdx];
29757 const elData = asElementData(view, def.nodeIndex);
29758 const renderNode = elData.renderElement;
29759 const name = binding.name;
29760 switch (binding.flags & 15 /* Types */) {
29761 case 1 /* TypeElementAttribute */:
29762 setElementAttribute(view, binding, renderNode, binding.ns, name, value);
29763 break;
29764 case 2 /* TypeElementClass */:
29765 setElementClass(view, renderNode, name, value);
29766 break;
29767 case 4 /* TypeElementStyle */:
29768 setElementStyle(view, binding, renderNode, name, value);
29769 break;
29770 case 8 /* TypeProperty */:
29771 const bindView = (def.flags & 33554432 /* ComponentView */ &&
29772 binding.flags & 32 /* SyntheticHostProperty */) ?
29773 elData.componentView :
29774 view;
29775 setElementProperty(bindView, binding, renderNode, name, value);
29776 break;
29777 }
29778 return true;
29779}
29780function setElementAttribute(view, binding, renderNode, ns, name, value) {
29781 const securityContext = binding.securityContext;
29782 let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
29783 renderValue = renderValue != null ? renderValue.toString() : null;
29784 const renderer = view.renderer;
29785 if (value != null) {
29786 renderer.setAttribute(renderNode, name, renderValue, ns);
29787 }
29788 else {
29789 renderer.removeAttribute(renderNode, name, ns);
29790 }
29791}
29792function setElementClass(view, renderNode, name, value) {
29793 const renderer = view.renderer;
29794 if (value) {
29795 renderer.addClass(renderNode, name);
29796 }
29797 else {
29798 renderer.removeClass(renderNode, name);
29799 }
29800}
29801function setElementStyle(view, binding, renderNode, name, value) {
29802 let renderValue = view.root.sanitizer.sanitize(SecurityContext.STYLE, value);
29803 if (renderValue != null) {
29804 renderValue = renderValue.toString();
29805 const unit = binding.suffix;
29806 if (unit != null) {
29807 renderValue = renderValue + unit;
29808 }
29809 }
29810 else {
29811 renderValue = null;
29812 }
29813 const renderer = view.renderer;
29814 if (renderValue != null) {
29815 renderer.setStyle(renderNode, name, renderValue);
29816 }
29817 else {
29818 renderer.removeStyle(renderNode, name);
29819 }
29820}
29821function setElementProperty(view, binding, renderNode, name, value) {
29822 const securityContext = binding.securityContext;
29823 let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
29824 view.renderer.setProperty(renderNode, name, renderValue);
29825}
29826
29827/**
29828 * @license
29829 * Copyright Google LLC All Rights Reserved.
29830 *
29831 * Use of this source code is governed by an MIT-style license that can be
29832 * found in the LICENSE file at https://angular.io/license
29833 */
29834const UNDEFINED_VALUE = {};
29835const InjectorRefTokenKey$1 = tokenKey(Injector);
29836const INJECTORRefTokenKey$1 = tokenKey(INJECTOR);
29837const NgModuleRefTokenKey = tokenKey(NgModuleRef$1);
29838function moduleProvideDef(flags, token, value, deps) {
29839 // Need to resolve forwardRefs as e.g. for `useValue` we
29840 // lowered the expression and then stopped evaluating it,
29841 // i.e. also didn't unwrap it.
29842 value = resolveForwardRef(value);
29843 const depDefs = splitDepsDsl(deps, stringify(token));
29844 return {
29845 // will bet set by the module definition
29846 index: -1,
29847 deps: depDefs,
29848 flags,
29849 token,
29850 value
29851 };
29852}
29853function moduleDef(providers) {
29854 const providersByKey = {};
29855 const modules = [];
29856 let scope = null;
29857 for (let i = 0; i < providers.length; i++) {
29858 const provider = providers[i];
29859 if (provider.token === INJECTOR_SCOPE) {
29860 scope = provider.value;
29861 }
29862 if (provider.flags & 1073741824 /* TypeNgModule */) {
29863 modules.push(provider.token);
29864 }
29865 provider.index = i;
29866 providersByKey[tokenKey(provider.token)] = provider;
29867 }
29868 return {
29869 // Will be filled later...
29870 factory: null,
29871 providersByKey,
29872 providers,
29873 modules,
29874 scope: scope,
29875 };
29876}
29877function initNgModule(data) {
29878 const def = data._def;
29879 const providers = data._providers = newArray(def.providers.length);
29880 for (let i = 0; i < def.providers.length; i++) {
29881 const provDef = def.providers[i];
29882 if (!(provDef.flags & 4096 /* LazyProvider */)) {
29883 // Make sure the provider has not been already initialized outside this loop.
29884 if (providers[i] === undefined) {
29885 providers[i] = _createProviderInstance$1(data, provDef);
29886 }
29887 }
29888 }
29889}
29890function resolveNgModuleDep(data, depDef, notFoundValue = Injector.THROW_IF_NOT_FOUND) {
29891 const former = setCurrentInjector(data);
29892 try {
29893 if (depDef.flags & 8 /* Value */) {
29894 return depDef.token;
29895 }
29896 if (depDef.flags & 2 /* Optional */) {
29897 notFoundValue = null;
29898 }
29899 if (depDef.flags & 1 /* SkipSelf */) {
29900 return data._parent.get(depDef.token, notFoundValue);
29901 }
29902 const tokenKey = depDef.tokenKey;
29903 switch (tokenKey) {
29904 case InjectorRefTokenKey$1:
29905 case INJECTORRefTokenKey$1:
29906 case NgModuleRefTokenKey:
29907 return data;
29908 }
29909 const providerDef = data._def.providersByKey[tokenKey];
29910 let injectableDef;
29911 if (providerDef) {
29912 let providerInstance = data._providers[providerDef.index];
29913 if (providerInstance === undefined) {
29914 providerInstance = data._providers[providerDef.index] =
29915 _createProviderInstance$1(data, providerDef);
29916 }
29917 return providerInstance === UNDEFINED_VALUE ? undefined : providerInstance;
29918 }
29919 else if ((injectableDef = getInjectableDef(depDef.token)) && targetsModule(data, injectableDef)) {
29920 const index = data._providers.length;
29921 data._def.providers[index] = data._def.providersByKey[depDef.tokenKey] = {
29922 flags: 1024 /* TypeFactoryProvider */ | 4096 /* LazyProvider */,
29923 value: injectableDef.factory,
29924 deps: [],
29925 index,
29926 token: depDef.token,
29927 };
29928 data._providers[index] = UNDEFINED_VALUE;
29929 return (data._providers[index] =
29930 _createProviderInstance$1(data, data._def.providersByKey[depDef.tokenKey]));
29931 }
29932 else if (depDef.flags & 4 /* Self */) {
29933 return notFoundValue;
29934 }
29935 return data._parent.get(depDef.token, notFoundValue);
29936 }
29937 finally {
29938 setCurrentInjector(former);
29939 }
29940}
29941function moduleTransitivelyPresent(ngModule, scope) {
29942 return ngModule._def.modules.indexOf(scope) > -1;
29943}
29944function targetsModule(ngModule, def) {
29945 const providedIn = resolveForwardRef(def.providedIn);
29946 return providedIn != null &&
29947 (providedIn === 'any' || providedIn === ngModule._def.scope ||
29948 moduleTransitivelyPresent(ngModule, providedIn));
29949}
29950function _createProviderInstance$1(ngModule, providerDef) {
29951 let injectable;
29952 switch (providerDef.flags & 201347067 /* Types */) {
29953 case 512 /* TypeClassProvider */:
29954 injectable = _createClass(ngModule, providerDef.value, providerDef.deps);
29955 break;
29956 case 1024 /* TypeFactoryProvider */:
29957 injectable = _callFactory(ngModule, providerDef.value, providerDef.deps);
29958 break;
29959 case 2048 /* TypeUseExistingProvider */:
29960 injectable = resolveNgModuleDep(ngModule, providerDef.deps[0]);
29961 break;
29962 case 256 /* TypeValueProvider */:
29963 injectable = providerDef.value;
29964 break;
29965 }
29966 // The read of `ngOnDestroy` here is slightly expensive as it's megamorphic, so it should be
29967 // avoided if possible. The sequence of checks here determines whether ngOnDestroy needs to be
29968 // checked. It might not if the `injectable` isn't an object or if NodeFlags.OnDestroy is already
29969 // set (ngOnDestroy was detected statically).
29970 if (injectable !== UNDEFINED_VALUE && injectable !== null && typeof injectable === 'object' &&
29971 !(providerDef.flags & 131072 /* OnDestroy */) && typeof injectable.ngOnDestroy === 'function') {
29972 providerDef.flags |= 131072 /* OnDestroy */;
29973 }
29974 return injectable === undefined ? UNDEFINED_VALUE : injectable;
29975}
29976function _createClass(ngModule, ctor, deps) {
29977 const len = deps.length;
29978 switch (len) {
29979 case 0:
29980 return new ctor();
29981 case 1:
29982 return new ctor(resolveNgModuleDep(ngModule, deps[0]));
29983 case 2:
29984 return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
29985 case 3:
29986 return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2]));
29987 default:
29988 const depValues = [];
29989 for (let i = 0; i < len; i++) {
29990 depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
29991 }
29992 return new ctor(...depValues);
29993 }
29994}
29995function _callFactory(ngModule, factory, deps) {
29996 const len = deps.length;
29997 switch (len) {
29998 case 0:
29999 return factory();
30000 case 1:
30001 return factory(resolveNgModuleDep(ngModule, deps[0]));
30002 case 2:
30003 return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
30004 case 3:
30005 return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2]));
30006 default:
30007 const depValues = [];
30008 for (let i = 0; i < len; i++) {
30009 depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
30010 }
30011 return factory(...depValues);
30012 }
30013}
30014function callNgModuleLifecycle(ngModule, lifecycles) {
30015 const def = ngModule._def;
30016 const destroyed = new Set();
30017 for (let i = 0; i < def.providers.length; i++) {
30018 const provDef = def.providers[i];
30019 if (provDef.flags & 131072 /* OnDestroy */) {
30020 const instance = ngModule._providers[i];
30021 if (instance && instance !== UNDEFINED_VALUE) {
30022 const onDestroy = instance.ngOnDestroy;
30023 if (typeof onDestroy === 'function' && !destroyed.has(instance)) {
30024 onDestroy.apply(instance);
30025 destroyed.add(instance);
30026 }
30027 }
30028 }
30029 }
30030}
30031
30032/**
30033 * @license
30034 * Copyright Google LLC All Rights Reserved.
30035 *
30036 * Use of this source code is governed by an MIT-style license that can be
30037 * found in the LICENSE file at https://angular.io/license
30038 */
30039function attachEmbeddedView(parentView, elementData, viewIndex, view) {
30040 let embeddedViews = elementData.viewContainer._embeddedViews;
30041 if (viewIndex === null || viewIndex === undefined) {
30042 viewIndex = embeddedViews.length;
30043 }
30044 view.viewContainerParent = parentView;
30045 addToArray(embeddedViews, viewIndex, view);
30046 attachProjectedView(elementData, view);
30047 Services.dirtyParentQueries(view);
30048 const prevView = viewIndex > 0 ? embeddedViews[viewIndex - 1] : null;
30049 renderAttachEmbeddedView(elementData, prevView, view);
30050}
30051function attachProjectedView(vcElementData, view) {
30052 const dvcElementData = declaredViewContainer(view);
30053 if (!dvcElementData || dvcElementData === vcElementData ||
30054 view.state & 16 /* IsProjectedView */) {
30055 return;
30056 }
30057 // Note: For performance reasons, we
30058 // - add a view to template._projectedViews only 1x throughout its lifetime,
30059 // and remove it not until the view is destroyed.
30060 // (hard, as when a parent view is attached/detached we would need to attach/detach all
30061 // nested projected views as well, even across component boundaries).
30062 // - don't track the insertion order of views in the projected views array
30063 // (hard, as when the views of the same template are inserted different view containers)
30064 view.state |= 16 /* IsProjectedView */;
30065 let projectedViews = dvcElementData.template._projectedViews;
30066 if (!projectedViews) {
30067 projectedViews = dvcElementData.template._projectedViews = [];
30068 }
30069 projectedViews.push(view);
30070 // Note: we are changing the NodeDef here as we cannot calculate
30071 // the fact whether a template is used for projection during compilation.
30072 markNodeAsProjectedTemplate(view.parent.def, view.parentNodeDef);
30073}
30074function markNodeAsProjectedTemplate(viewDef, nodeDef) {
30075 if (nodeDef.flags & 4 /* ProjectedTemplate */) {
30076 return;
30077 }
30078 viewDef.nodeFlags |= 4 /* ProjectedTemplate */;
30079 nodeDef.flags |= 4 /* ProjectedTemplate */;
30080 let parentNodeDef = nodeDef.parent;
30081 while (parentNodeDef) {
30082 parentNodeDef.childFlags |= 4 /* ProjectedTemplate */;
30083 parentNodeDef = parentNodeDef.parent;
30084 }
30085}
30086function detachEmbeddedView(elementData, viewIndex) {
30087 const embeddedViews = elementData.viewContainer._embeddedViews;
30088 if (viewIndex == null || viewIndex >= embeddedViews.length) {
30089 viewIndex = embeddedViews.length - 1;
30090 }
30091 if (viewIndex < 0) {
30092 return null;
30093 }
30094 const view = embeddedViews[viewIndex];
30095 view.viewContainerParent = null;
30096 removeFromArray(embeddedViews, viewIndex);
30097 // See attachProjectedView for why we don't update projectedViews here.
30098 Services.dirtyParentQueries(view);
30099 renderDetachView(view);
30100 return view;
30101}
30102function detachProjectedView(view) {
30103 if (!(view.state & 16 /* IsProjectedView */)) {
30104 return;
30105 }
30106 const dvcElementData = declaredViewContainer(view);
30107 if (dvcElementData) {
30108 const projectedViews = dvcElementData.template._projectedViews;
30109 if (projectedViews) {
30110 removeFromArray(projectedViews, projectedViews.indexOf(view));
30111 Services.dirtyParentQueries(view);
30112 }
30113 }
30114}
30115function moveEmbeddedView(elementData, oldViewIndex, newViewIndex) {
30116 const embeddedViews = elementData.viewContainer._embeddedViews;
30117 const view = embeddedViews[oldViewIndex];
30118 removeFromArray(embeddedViews, oldViewIndex);
30119 if (newViewIndex == null) {
30120 newViewIndex = embeddedViews.length;
30121 }
30122 addToArray(embeddedViews, newViewIndex, view);
30123 // Note: Don't need to change projectedViews as the order in there
30124 // as always invalid...
30125 Services.dirtyParentQueries(view);
30126 renderDetachView(view);
30127 const prevView = newViewIndex > 0 ? embeddedViews[newViewIndex - 1] : null;
30128 renderAttachEmbeddedView(elementData, prevView, view);
30129 return view;
30130}
30131function renderAttachEmbeddedView(elementData, prevView, view) {
30132 const prevRenderNode = prevView ? renderNode(prevView, prevView.def.lastRenderRootNode) : elementData.renderElement;
30133 const parentNode = view.renderer.parentNode(prevRenderNode);
30134 const nextSibling = view.renderer.nextSibling(prevRenderNode);
30135 // Note: We can't check if `nextSibling` is present, as on WebWorkers it will always be!
30136 // However, browsers automatically do `appendChild` when there is no `nextSibling`.
30137 visitRootRenderNodes(view, 2 /* InsertBefore */, parentNode, nextSibling, undefined);
30138}
30139function renderDetachView(view) {
30140 visitRootRenderNodes(view, 3 /* RemoveChild */, null, null, undefined);
30141}
30142
30143/**
30144 * @license
30145 * Copyright Google LLC All Rights Reserved.
30146 *
30147 * Use of this source code is governed by an MIT-style license that can be
30148 * found in the LICENSE file at https://angular.io/license
30149 */
30150const EMPTY_CONTEXT = {};
30151// Attention: this function is called as top level function.
30152// Putting any logic in here will destroy closure tree shaking!
30153function createComponentFactory(selector, componentType, viewDefFactory, inputs, outputs, ngContentSelectors) {
30154 return new ComponentFactory_(selector, componentType, viewDefFactory, inputs, outputs, ngContentSelectors);
30155}
30156function getComponentViewDefinitionFactory(componentFactory) {
30157 return componentFactory.viewDefFactory;
30158}
30159class ComponentFactory_ extends ComponentFactory$1 {
30160 constructor(selector, componentType, viewDefFactory, _inputs, _outputs, ngContentSelectors) {
30161 // Attention: this ctor is called as top level function.
30162 // Putting any logic in here will destroy closure tree shaking!
30163 super();
30164 this.selector = selector;
30165 this.componentType = componentType;
30166 this._inputs = _inputs;
30167 this._outputs = _outputs;
30168 this.ngContentSelectors = ngContentSelectors;
30169 this.viewDefFactory = viewDefFactory;
30170 }
30171 get inputs() {
30172 const inputsArr = [];
30173 const inputs = this._inputs;
30174 for (let propName in inputs) {
30175 const templateName = inputs[propName];
30176 inputsArr.push({ propName, templateName });
30177 }
30178 return inputsArr;
30179 }
30180 get outputs() {
30181 const outputsArr = [];
30182 for (let propName in this._outputs) {
30183 const templateName = this._outputs[propName];
30184 outputsArr.push({ propName, templateName });
30185 }
30186 return outputsArr;
30187 }
30188 /**
30189 * Creates a new component.
30190 */
30191 create(injector, projectableNodes, rootSelectorOrNode, ngModule) {
30192 if (!ngModule) {
30193 throw new Error('ngModule should be provided');
30194 }
30195 const viewDef = resolveDefinition(this.viewDefFactory);
30196 const componentNodeIndex = viewDef.nodes[0].element.componentProvider.nodeIndex;
30197 const view = Services.createRootView(injector, projectableNodes || [], rootSelectorOrNode, viewDef, ngModule, EMPTY_CONTEXT);
30198 const component = asProviderData(view, componentNodeIndex).instance;
30199 if (rootSelectorOrNode) {
30200 view.renderer.setAttribute(asElementData(view, 0).renderElement, 'ng-version', VERSION.full);
30201 }
30202 return new ComponentRef_(view, new ViewRef_(view), component);
30203 }
30204}
30205class ComponentRef_ extends ComponentRef$1 {
30206 constructor(_view, _viewRef, _component) {
30207 super();
30208 this._view = _view;
30209 this._viewRef = _viewRef;
30210 this._component = _component;
30211 this._elDef = this._view.def.nodes[0];
30212 this.hostView = _viewRef;
30213 this.changeDetectorRef = _viewRef;
30214 this.instance = _component;
30215 }
30216 get location() {
30217 return new ElementRef(asElementData(this._view, this._elDef.nodeIndex).renderElement);
30218 }
30219 get injector() {
30220 return new Injector_(this._view, this._elDef);
30221 }
30222 get componentType() {
30223 return this._component.constructor;
30224 }
30225 destroy() {
30226 this._viewRef.destroy();
30227 }
30228 onDestroy(callback) {
30229 this._viewRef.onDestroy(callback);
30230 }
30231}
30232function createViewContainerData(view, elDef, elData) {
30233 return new ViewContainerRef_(view, elDef, elData);
30234}
30235class ViewContainerRef_ {
30236 constructor(_view, _elDef, _data) {
30237 this._view = _view;
30238 this._elDef = _elDef;
30239 this._data = _data;
30240 /**
30241 * @internal
30242 */
30243 this._embeddedViews = [];
30244 }
30245 get element() {
30246 return new ElementRef(this._data.renderElement);
30247 }
30248 get injector() {
30249 return new Injector_(this._view, this._elDef);
30250 }
30251 /** @deprecated No replacement */
30252 get parentInjector() {
30253 let view = this._view;
30254 let elDef = this._elDef.parent;
30255 while (!elDef && view) {
30256 elDef = viewParentEl(view);
30257 view = view.parent;
30258 }
30259 return view ? new Injector_(view, elDef) : new Injector_(this._view, null);
30260 }
30261 clear() {
30262 const len = this._embeddedViews.length;
30263 for (let i = len - 1; i >= 0; i--) {
30264 const view = detachEmbeddedView(this._data, i);
30265 Services.destroyView(view);
30266 }
30267 }
30268 get(index) {
30269 const view = this._embeddedViews[index];
30270 if (view) {
30271 const ref = new ViewRef_(view);
30272 ref.attachToViewContainerRef(this);
30273 return ref;
30274 }
30275 return null;
30276 }
30277 get length() {
30278 return this._embeddedViews.length;
30279 }
30280 createEmbeddedView(templateRef, context, index) {
30281 const viewRef = templateRef.createEmbeddedView(context || {});
30282 this.insert(viewRef, index);
30283 return viewRef;
30284 }
30285 createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, ngModuleRef) {
30286 if (typeof ngDevMode === 'undefined' || ngDevMode) {
30287 assertEqual(typeof componentFactoryOrType !== 'function', true, 'ViewEngine does not support Type as an argument for \'componentFactoryOrType\'');
30288 assertEqual(typeof indexOrOptions !== 'object', true, 'ViewEngine does not support options as an object provided via second argument');
30289 }
30290 const index = indexOrOptions;
30291 const contextInjector = injector || this.parentInjector;
30292 const componentFactory = componentFactoryOrType;
30293 if (!ngModuleRef && !(componentFactory instanceof ComponentFactoryBoundToModule)) {
30294 ngModuleRef = contextInjector.get(NgModuleRef$1);
30295 }
30296 const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
30297 this.insert(componentRef.hostView, index);
30298 return componentRef;
30299 }
30300 insert(viewRef, index) {
30301 if (viewRef.destroyed) {
30302 throw new Error('Cannot insert a destroyed View in a ViewContainer!');
30303 }
30304 const viewRef_ = viewRef;
30305 const viewData = viewRef_._view;
30306 attachEmbeddedView(this._view, this._data, index, viewData);
30307 viewRef_.attachToViewContainerRef(this);
30308 return viewRef;
30309 }
30310 move(viewRef, currentIndex) {
30311 if (viewRef.destroyed) {
30312 throw new Error('Cannot move a destroyed View in a ViewContainer!');
30313 }
30314 const previousIndex = this._embeddedViews.indexOf(viewRef._view);
30315 moveEmbeddedView(this._data, previousIndex, currentIndex);
30316 return viewRef;
30317 }
30318 indexOf(viewRef) {
30319 return this._embeddedViews.indexOf(viewRef._view);
30320 }
30321 remove(index) {
30322 const viewData = detachEmbeddedView(this._data, index);
30323 if (viewData) {
30324 Services.destroyView(viewData);
30325 }
30326 }
30327 detach(index) {
30328 const view = detachEmbeddedView(this._data, index);
30329 return view ? new ViewRef_(view) : null;
30330 }
30331}
30332function createChangeDetectorRef(view) {
30333 return new ViewRef_(view);
30334}
30335class ViewRef_ {
30336 constructor(_view) {
30337 this._view = _view;
30338 this._viewContainerRef = null;
30339 this._appRef = null;
30340 }
30341 get rootNodes() {
30342 return rootRenderNodes(this._view);
30343 }
30344 get context() {
30345 return this._view.context;
30346 }
30347 set context(value) {
30348 this._view.context = value;
30349 }
30350 get destroyed() {
30351 return (this._view.state & 128 /* Destroyed */) !== 0;
30352 }
30353 markForCheck() {
30354 markParentViewsForCheck(this._view);
30355 }
30356 detach() {
30357 this._view.state &= ~4 /* Attached */;
30358 }
30359 detectChanges() {
30360 const fs = this._view.root.rendererFactory;
30361 if (fs.begin) {
30362 fs.begin();
30363 }
30364 try {
30365 Services.checkAndUpdateView(this._view);
30366 }
30367 finally {
30368 if (fs.end) {
30369 fs.end();
30370 }
30371 }
30372 }
30373 checkNoChanges() {
30374 Services.checkNoChangesView(this._view);
30375 }
30376 reattach() {
30377 this._view.state |= 4 /* Attached */;
30378 }
30379 onDestroy(callback) {
30380 if (!this._view.disposables) {
30381 this._view.disposables = [];
30382 }
30383 this._view.disposables.push(callback);
30384 }
30385 destroy() {
30386 if (this._appRef) {
30387 this._appRef.detachView(this);
30388 }
30389 else if (this._viewContainerRef) {
30390 this._viewContainerRef.detach(this._viewContainerRef.indexOf(this));
30391 }
30392 Services.destroyView(this._view);
30393 }
30394 detachFromAppRef() {
30395 this._appRef = null;
30396 renderDetachView(this._view);
30397 Services.dirtyParentQueries(this._view);
30398 }
30399 attachToAppRef(appRef) {
30400 if (this._viewContainerRef) {
30401 throw new Error('This view is already attached to a ViewContainer!');
30402 }
30403 this._appRef = appRef;
30404 }
30405 attachToViewContainerRef(vcRef) {
30406 if (this._appRef) {
30407 throw new Error('This view is already attached directly to the ApplicationRef!');
30408 }
30409 this._viewContainerRef = vcRef;
30410 }
30411}
30412function createTemplateData(view, def) {
30413 return new TemplateRef_(view, def);
30414}
30415class TemplateRef_ extends TemplateRef {
30416 constructor(_parentView, _def) {
30417 super();
30418 this._parentView = _parentView;
30419 this._def = _def;
30420 }
30421 createEmbeddedView(context) {
30422 return new ViewRef_(Services.createEmbeddedView(this._parentView, this._def, this._def.element.template, context));
30423 }
30424 get elementRef() {
30425 return new ElementRef(asElementData(this._parentView, this._def.nodeIndex).renderElement);
30426 }
30427}
30428function createInjector(view, elDef) {
30429 return new Injector_(view, elDef);
30430}
30431class Injector_ {
30432 constructor(view, elDef) {
30433 this.view = view;
30434 this.elDef = elDef;
30435 }
30436 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND) {
30437 const allowPrivateServices = this.elDef ? (this.elDef.flags & 33554432 /* ComponentView */) !== 0 : false;
30438 return Services.resolveDep(this.view, this.elDef, allowPrivateServices, { flags: 0 /* None */, token, tokenKey: tokenKey(token) }, notFoundValue);
30439 }
30440}
30441function nodeValue(view, index) {
30442 const def = view.def.nodes[index];
30443 if (def.flags & 1 /* TypeElement */) {
30444 const elData = asElementData(view, def.nodeIndex);
30445 return def.element.template ? elData.template : elData.renderElement;
30446 }
30447 else if (def.flags & 2 /* TypeText */) {
30448 return asTextData(view, def.nodeIndex).renderText;
30449 }
30450 else if (def.flags & (20224 /* CatProvider */ | 16 /* TypePipe */)) {
30451 return asProviderData(view, def.nodeIndex).instance;
30452 }
30453 throw new Error(`Illegal state: read nodeValue for node index ${index}`);
30454}
30455function createNgModuleRef(moduleType, parent, bootstrapComponents, def) {
30456 return new NgModuleRef_(moduleType, parent, bootstrapComponents, def);
30457}
30458class NgModuleRef_ {
30459 constructor(_moduleType, _parent, _bootstrapComponents, _def) {
30460 this._moduleType = _moduleType;
30461 this._parent = _parent;
30462 this._bootstrapComponents = _bootstrapComponents;
30463 this._def = _def;
30464 this._destroyListeners = [];
30465 this._destroyed = false;
30466 this.injector = this;
30467 initNgModule(this);
30468 }
30469 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, injectFlags = InjectFlags.Default) {
30470 let flags = 0 /* None */;
30471 if (injectFlags & InjectFlags.SkipSelf) {
30472 flags |= 1 /* SkipSelf */;
30473 }
30474 else if (injectFlags & InjectFlags.Self) {
30475 flags |= 4 /* Self */;
30476 }
30477 return resolveNgModuleDep(this, { token: token, tokenKey: tokenKey(token), flags: flags }, notFoundValue);
30478 }
30479 get instance() {
30480 return this.get(this._moduleType);
30481 }
30482 get componentFactoryResolver() {
30483 return this.get(ComponentFactoryResolver$1);
30484 }
30485 destroy() {
30486 if (this._destroyed) {
30487 throw new Error(`The ng module ${stringify(this.instance.constructor)} has already been destroyed.`);
30488 }
30489 this._destroyed = true;
30490 callNgModuleLifecycle(this, 131072 /* OnDestroy */);
30491 this._destroyListeners.forEach((listener) => listener());
30492 }
30493 onDestroy(callback) {
30494 this._destroyListeners.push(callback);
30495 }
30496}
30497
30498/**
30499 * @license
30500 * Copyright Google LLC All Rights Reserved.
30501 *
30502 * Use of this source code is governed by an MIT-style license that can be
30503 * found in the LICENSE file at https://angular.io/license
30504 */
30505const Renderer2TokenKey = tokenKey(Renderer2);
30506const ElementRefTokenKey = tokenKey(ElementRef);
30507const ViewContainerRefTokenKey = tokenKey(ViewContainerRef);
30508const TemplateRefTokenKey = tokenKey(TemplateRef);
30509const ChangeDetectorRefTokenKey = tokenKey(ChangeDetectorRef);
30510const InjectorRefTokenKey = tokenKey(Injector);
30511const INJECTORRefTokenKey = tokenKey(INJECTOR);
30512function directiveDef(checkIndex, flags, matchedQueries, childCount, ctor, deps, props, outputs) {
30513 const bindings = [];
30514 if (props) {
30515 for (let prop in props) {
30516 const [bindingIndex, nonMinifiedName] = props[prop];
30517 bindings[bindingIndex] = {
30518 flags: 8 /* TypeProperty */,
30519 name: prop,
30520 nonMinifiedName,
30521 ns: null,
30522 securityContext: null,
30523 suffix: null
30524 };
30525 }
30526 }
30527 const outputDefs = [];
30528 if (outputs) {
30529 for (let propName in outputs) {
30530 outputDefs.push({ type: 1 /* DirectiveOutput */, propName, target: null, eventName: outputs[propName] });
30531 }
30532 }
30533 flags |= 16384 /* TypeDirective */;
30534 return _def(checkIndex, flags, matchedQueries, childCount, ctor, ctor, deps, bindings, outputDefs);
30535}
30536function pipeDef(flags, ctor, deps) {
30537 flags |= 16 /* TypePipe */;
30538 return _def(-1, flags, null, 0, ctor, ctor, deps);
30539}
30540function providerDef(flags, matchedQueries, token, value, deps) {
30541 return _def(-1, flags, matchedQueries, 0, token, value, deps);
30542}
30543function _def(checkIndex, flags, matchedQueriesDsl, childCount, token, value, deps, bindings, outputs) {
30544 const { matchedQueries, references, matchedQueryIds } = splitMatchedQueriesDsl(matchedQueriesDsl);
30545 if (!outputs) {
30546 outputs = [];
30547 }
30548 if (!bindings) {
30549 bindings = [];
30550 }
30551 // Need to resolve forwardRefs as e.g. for `useValue` we
30552 // lowered the expression and then stopped evaluating it,
30553 // i.e. also didn't unwrap it.
30554 value = resolveForwardRef(value);
30555 const depDefs = splitDepsDsl(deps, stringify(token));
30556 return {
30557 // will bet set by the view definition
30558 nodeIndex: -1,
30559 parent: null,
30560 renderParent: null,
30561 bindingIndex: -1,
30562 outputIndex: -1,
30563 // regular values
30564 checkIndex,
30565 flags,
30566 childFlags: 0,
30567 directChildFlags: 0,
30568 childMatchedQueries: 0,
30569 matchedQueries,
30570 matchedQueryIds,
30571 references,
30572 ngContentIndex: -1,
30573 childCount,
30574 bindings,
30575 bindingFlags: calcBindingFlags(bindings),
30576 outputs,
30577 element: null,
30578 provider: { token, value, deps: depDefs },
30579 text: null,
30580 query: null,
30581 ngContent: null
30582 };
30583}
30584function createProviderInstance(view, def) {
30585 return _createProviderInstance(view, def);
30586}
30587function createPipeInstance(view, def) {
30588 // deps are looked up from component.
30589 let compView = view;
30590 while (compView.parent && !isComponentView(compView)) {
30591 compView = compView.parent;
30592 }
30593 // pipes can see the private services of the component
30594 const allowPrivateServices = true;
30595 // pipes are always eager and classes!
30596 return createClass(compView.parent, viewParentEl(compView), allowPrivateServices, def.provider.value, def.provider.deps);
30597}
30598function createDirectiveInstance(view, def) {
30599 // components can see other private services, other directives can't.
30600 const allowPrivateServices = (def.flags & 32768 /* Component */) > 0;
30601 // directives are always eager and classes!
30602 const instance = createClass(view, def.parent, allowPrivateServices, def.provider.value, def.provider.deps);
30603 if (def.outputs.length) {
30604 for (let i = 0; i < def.outputs.length; i++) {
30605 const output = def.outputs[i];
30606 const outputObservable = instance[output.propName];
30607 if (isObservable(outputObservable)) {
30608 const subscription = outputObservable.subscribe(eventHandlerClosure(view, def.parent.nodeIndex, output.eventName));
30609 view.disposables[def.outputIndex + i] = subscription.unsubscribe.bind(subscription);
30610 }
30611 else {
30612 throw new Error(`@Output ${output.propName} not initialized in '${instance.constructor.name}'.`);
30613 }
30614 }
30615 }
30616 return instance;
30617}
30618function eventHandlerClosure(view, index, eventName) {
30619 return (event) => dispatchEvent(view, index, eventName, event);
30620}
30621function checkAndUpdateDirectiveInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
30622 const providerData = asProviderData(view, def.nodeIndex);
30623 const directive = providerData.instance;
30624 let changed = false;
30625 let changes = undefined;
30626 const bindLen = def.bindings.length;
30627 if (bindLen > 0 && checkBinding(view, def, 0, v0)) {
30628 changed = true;
30629 changes = updateProp(view, providerData, def, 0, v0, changes);
30630 }
30631 if (bindLen > 1 && checkBinding(view, def, 1, v1)) {
30632 changed = true;
30633 changes = updateProp(view, providerData, def, 1, v1, changes);
30634 }
30635 if (bindLen > 2 && checkBinding(view, def, 2, v2)) {
30636 changed = true;
30637 changes = updateProp(view, providerData, def, 2, v2, changes);
30638 }
30639 if (bindLen > 3 && checkBinding(view, def, 3, v3)) {
30640 changed = true;
30641 changes = updateProp(view, providerData, def, 3, v3, changes);
30642 }
30643 if (bindLen > 4 && checkBinding(view, def, 4, v4)) {
30644 changed = true;
30645 changes = updateProp(view, providerData, def, 4, v4, changes);
30646 }
30647 if (bindLen > 5 && checkBinding(view, def, 5, v5)) {
30648 changed = true;
30649 changes = updateProp(view, providerData, def, 5, v5, changes);
30650 }
30651 if (bindLen > 6 && checkBinding(view, def, 6, v6)) {
30652 changed = true;
30653 changes = updateProp(view, providerData, def, 6, v6, changes);
30654 }
30655 if (bindLen > 7 && checkBinding(view, def, 7, v7)) {
30656 changed = true;
30657 changes = updateProp(view, providerData, def, 7, v7, changes);
30658 }
30659 if (bindLen > 8 && checkBinding(view, def, 8, v8)) {
30660 changed = true;
30661 changes = updateProp(view, providerData, def, 8, v8, changes);
30662 }
30663 if (bindLen > 9 && checkBinding(view, def, 9, v9)) {
30664 changed = true;
30665 changes = updateProp(view, providerData, def, 9, v9, changes);
30666 }
30667 if (changes) {
30668 directive.ngOnChanges(changes);
30669 }
30670 if ((def.flags & 65536 /* OnInit */) &&
30671 shouldCallLifecycleInitHook(view, 256 /* InitState_CallingOnInit */, def.nodeIndex)) {
30672 directive.ngOnInit();
30673 }
30674 if (def.flags & 262144 /* DoCheck */) {
30675 directive.ngDoCheck();
30676 }
30677 return changed;
30678}
30679function checkAndUpdateDirectiveDynamic(view, def, values) {
30680 const providerData = asProviderData(view, def.nodeIndex);
30681 const directive = providerData.instance;
30682 let changed = false;
30683 let changes = undefined;
30684 for (let i = 0; i < values.length; i++) {
30685 if (checkBinding(view, def, i, values[i])) {
30686 changed = true;
30687 changes = updateProp(view, providerData, def, i, values[i], changes);
30688 }
30689 }
30690 if (changes) {
30691 directive.ngOnChanges(changes);
30692 }
30693 if ((def.flags & 65536 /* OnInit */) &&
30694 shouldCallLifecycleInitHook(view, 256 /* InitState_CallingOnInit */, def.nodeIndex)) {
30695 directive.ngOnInit();
30696 }
30697 if (def.flags & 262144 /* DoCheck */) {
30698 directive.ngDoCheck();
30699 }
30700 return changed;
30701}
30702function _createProviderInstance(view, def) {
30703 // private services can see other private services
30704 const allowPrivateServices = (def.flags & 8192 /* PrivateProvider */) > 0;
30705 const providerDef = def.provider;
30706 switch (def.flags & 201347067 /* Types */) {
30707 case 512 /* TypeClassProvider */:
30708 return createClass(view, def.parent, allowPrivateServices, providerDef.value, providerDef.deps);
30709 case 1024 /* TypeFactoryProvider */:
30710 return callFactory(view, def.parent, allowPrivateServices, providerDef.value, providerDef.deps);
30711 case 2048 /* TypeUseExistingProvider */:
30712 return resolveDep(view, def.parent, allowPrivateServices, providerDef.deps[0]);
30713 case 256 /* TypeValueProvider */:
30714 return providerDef.value;
30715 }
30716}
30717function createClass(view, elDef, allowPrivateServices, ctor, deps) {
30718 const len = deps.length;
30719 switch (len) {
30720 case 0:
30721 return new ctor();
30722 case 1:
30723 return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]));
30724 case 2:
30725 return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]));
30726 case 3:
30727 return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2]));
30728 default:
30729 const depValues = [];
30730 for (let i = 0; i < len; i++) {
30731 depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i]));
30732 }
30733 return new ctor(...depValues);
30734 }
30735}
30736function callFactory(view, elDef, allowPrivateServices, factory, deps) {
30737 const len = deps.length;
30738 switch (len) {
30739 case 0:
30740 return factory();
30741 case 1:
30742 return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]));
30743 case 2:
30744 return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]));
30745 case 3:
30746 return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2]));
30747 default:
30748 const depValues = [];
30749 for (let i = 0; i < len; i++) {
30750 depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i]));
30751 }
30752 return factory(...depValues);
30753 }
30754}
30755function resolveDep(view, elDef, allowPrivateServices, depDef, notFoundValue = Injector.THROW_IF_NOT_FOUND) {
30756 if (depDef.flags & 8 /* Value */) {
30757 return depDef.token;
30758 }
30759 const startView = view;
30760 if (depDef.flags & 2 /* Optional */) {
30761 notFoundValue = null;
30762 }
30763 const tokenKey = depDef.tokenKey;
30764 if (tokenKey === ChangeDetectorRefTokenKey) {
30765 // directives on the same element as a component should be able to control the change detector
30766 // of that component as well.
30767 allowPrivateServices = !!(elDef && elDef.element.componentView);
30768 }
30769 if (elDef && (depDef.flags & 1 /* SkipSelf */)) {
30770 allowPrivateServices = false;
30771 elDef = elDef.parent;
30772 }
30773 let searchView = view;
30774 while (searchView) {
30775 if (elDef) {
30776 switch (tokenKey) {
30777 case Renderer2TokenKey: {
30778 const compView = findCompView(searchView, elDef, allowPrivateServices);
30779 return compView.renderer;
30780 }
30781 case ElementRefTokenKey:
30782 return new ElementRef(asElementData(searchView, elDef.nodeIndex).renderElement);
30783 case ViewContainerRefTokenKey:
30784 return asElementData(searchView, elDef.nodeIndex).viewContainer;
30785 case TemplateRefTokenKey: {
30786 if (elDef.element.template) {
30787 return asElementData(searchView, elDef.nodeIndex).template;
30788 }
30789 break;
30790 }
30791 case ChangeDetectorRefTokenKey: {
30792 let cdView = findCompView(searchView, elDef, allowPrivateServices);
30793 return createChangeDetectorRef(cdView);
30794 }
30795 case InjectorRefTokenKey:
30796 case INJECTORRefTokenKey:
30797 return createInjector(searchView, elDef);
30798 default:
30799 const providerDef = (allowPrivateServices ? elDef.element.allProviders :
30800 elDef.element.publicProviders)[tokenKey];
30801 if (providerDef) {
30802 let providerData = asProviderData(searchView, providerDef.nodeIndex);
30803 if (!providerData) {
30804 providerData = { instance: _createProviderInstance(searchView, providerDef) };
30805 searchView.nodes[providerDef.nodeIndex] = providerData;
30806 }
30807 return providerData.instance;
30808 }
30809 }
30810 }
30811 allowPrivateServices = isComponentView(searchView);
30812 elDef = viewParentEl(searchView);
30813 searchView = searchView.parent;
30814 if (depDef.flags & 4 /* Self */) {
30815 searchView = null;
30816 }
30817 }
30818 const value = startView.root.injector.get(depDef.token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);
30819 if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
30820 notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
30821 // Return the value from the root element injector when
30822 // - it provides it
30823 // (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
30824 // - the module injector should not be checked
30825 // (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
30826 return value;
30827 }
30828 return startView.root.ngModule.injector.get(depDef.token, notFoundValue);
30829}
30830function findCompView(view, elDef, allowPrivateServices) {
30831 let compView;
30832 if (allowPrivateServices) {
30833 compView = asElementData(view, elDef.nodeIndex).componentView;
30834 }
30835 else {
30836 compView = view;
30837 while (compView.parent && !isComponentView(compView)) {
30838 compView = compView.parent;
30839 }
30840 }
30841 return compView;
30842}
30843function updateProp(view, providerData, def, bindingIdx, value, changes) {
30844 if (def.flags & 32768 /* Component */) {
30845 const compView = asElementData(view, def.parent.nodeIndex).componentView;
30846 if (compView.def.flags & 2 /* OnPush */) {
30847 compView.state |= 8 /* ChecksEnabled */;
30848 }
30849 }
30850 const binding = def.bindings[bindingIdx];
30851 const propName = binding.name;
30852 // Note: This is still safe with Closure Compiler as
30853 // the user passed in the property name as an object has to `providerDef`,
30854 // so Closure Compiler will have renamed the property correctly already.
30855 providerData.instance[propName] = value;
30856 if (def.flags & 524288 /* OnChanges */) {
30857 changes = changes || {};
30858 const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
30859 const binding = def.bindings[bindingIdx];
30860 changes[binding.nonMinifiedName] =
30861 new SimpleChange(oldValue, value, (view.state & 2 /* FirstCheck */) !== 0);
30862 }
30863 view.oldValues[def.bindingIndex + bindingIdx] = value;
30864 return changes;
30865}
30866// This function calls the ngAfterContentCheck, ngAfterContentInit,
30867// ngAfterViewCheck, and ngAfterViewInit lifecycle hooks (depending on the node
30868// flags in lifecycle). Unlike ngDoCheck, ngOnChanges and ngOnInit, which are
30869// called during a pre-order traversal of the view tree (that is calling the
30870// parent hooks before the child hooks) these events are sent in using a
30871// post-order traversal of the tree (children before parents). This changes the
30872// meaning of initIndex in the view state. For ngOnInit, initIndex tracks the
30873// expected nodeIndex which a ngOnInit should be called. When sending
30874// ngAfterContentInit and ngAfterViewInit it is the expected count of
30875// ngAfterContentInit or ngAfterViewInit methods that have been called. This
30876// ensure that despite being called recursively or after picking up after an
30877// exception, the ngAfterContentInit or ngAfterViewInit will be called on the
30878// correct nodes. Consider for example, the following (where E is an element
30879// and D is a directive)
30880// Tree: pre-order index post-order index
30881// E1 0 6
30882// E2 1 1
30883// D3 2 0
30884// E4 3 5
30885// E5 4 4
30886// E6 5 2
30887// E7 6 3
30888// As can be seen, the post-order index has an unclear relationship to the
30889// pre-order index (postOrderIndex === preOrderIndex - parentCount +
30890// childCount). Since number of calls to ngAfterContentInit and ngAfterViewInit
30891// are stable (will be the same for the same view regardless of exceptions or
30892// recursion) we just need to count them which will roughly correspond to the
30893// post-order index (it skips elements and directives that do not have
30894// lifecycle hooks).
30895//
30896// For example, if an exception is raised in the E6.onAfterViewInit() the
30897// initIndex is left at 3 (by shouldCallLifecycleInitHook() which set it to
30898// initIndex + 1). When checkAndUpdateView() is called again D3, E2 and E6 will
30899// not have their ngAfterViewInit() called but, starting with E7, the rest of
30900// the view will begin getting ngAfterViewInit() called until a check and
30901// pass is complete.
30902//
30903// This algorthim also handles recursion. Consider if E4's ngAfterViewInit()
30904// indirectly calls E1's ChangeDetectorRef.detectChanges(). The expected
30905// initIndex is set to 6, the recusive checkAndUpdateView() starts walk again.
30906// D3, E2, E6, E7, E5 and E4 are skipped, ngAfterViewInit() is called on E1.
30907// When the recursion returns the initIndex will be 7 so E1 is skipped as it
30908// has already been called in the recursively called checkAnUpdateView().
30909function callLifecycleHooksChildrenFirst(view, lifecycles) {
30910 if (!(view.def.nodeFlags & lifecycles)) {
30911 return;
30912 }
30913 const nodes = view.def.nodes;
30914 let initIndex = 0;
30915 for (let i = 0; i < nodes.length; i++) {
30916 const nodeDef = nodes[i];
30917 let parent = nodeDef.parent;
30918 if (!parent && nodeDef.flags & lifecycles) {
30919 // matching root node (e.g. a pipe)
30920 callProviderLifecycles(view, i, nodeDef.flags & lifecycles, initIndex++);
30921 }
30922 if ((nodeDef.childFlags & lifecycles) === 0) {
30923 // no child matches one of the lifecycles
30924 i += nodeDef.childCount;
30925 }
30926 while (parent && (parent.flags & 1 /* TypeElement */) &&
30927 i === parent.nodeIndex + parent.childCount) {
30928 // last child of an element
30929 if (parent.directChildFlags & lifecycles) {
30930 initIndex = callElementProvidersLifecycles(view, parent, lifecycles, initIndex);
30931 }
30932 parent = parent.parent;
30933 }
30934 }
30935}
30936function callElementProvidersLifecycles(view, elDef, lifecycles, initIndex) {
30937 for (let i = elDef.nodeIndex + 1; i <= elDef.nodeIndex + elDef.childCount; i++) {
30938 const nodeDef = view.def.nodes[i];
30939 if (nodeDef.flags & lifecycles) {
30940 callProviderLifecycles(view, i, nodeDef.flags & lifecycles, initIndex++);
30941 }
30942 // only visit direct children
30943 i += nodeDef.childCount;
30944 }
30945 return initIndex;
30946}
30947function callProviderLifecycles(view, index, lifecycles, initIndex) {
30948 const providerData = asProviderData(view, index);
30949 if (!providerData) {
30950 return;
30951 }
30952 const provider = providerData.instance;
30953 if (!provider) {
30954 return;
30955 }
30956 Services.setCurrentNode(view, index);
30957 if (lifecycles & 1048576 /* AfterContentInit */ &&
30958 shouldCallLifecycleInitHook(view, 512 /* InitState_CallingAfterContentInit */, initIndex)) {
30959 provider.ngAfterContentInit();
30960 }
30961 if (lifecycles & 2097152 /* AfterContentChecked */) {
30962 provider.ngAfterContentChecked();
30963 }
30964 if (lifecycles & 4194304 /* AfterViewInit */ &&
30965 shouldCallLifecycleInitHook(view, 768 /* InitState_CallingAfterViewInit */, initIndex)) {
30966 provider.ngAfterViewInit();
30967 }
30968 if (lifecycles & 8388608 /* AfterViewChecked */) {
30969 provider.ngAfterViewChecked();
30970 }
30971 if (lifecycles & 131072 /* OnDestroy */) {
30972 provider.ngOnDestroy();
30973 }
30974}
30975
30976/**
30977 * @license
30978 * Copyright Google LLC All Rights Reserved.
30979 *
30980 * Use of this source code is governed by an MIT-style license that can be
30981 * found in the LICENSE file at https://angular.io/license
30982 */
30983function queryDef(flags, id, bindings) {
30984 let bindingDefs = [];
30985 for (let propName in bindings) {
30986 const bindingType = bindings[propName];
30987 bindingDefs.push({ propName, bindingType });
30988 }
30989 return {
30990 // will bet set by the view definition
30991 nodeIndex: -1,
30992 parent: null,
30993 renderParent: null,
30994 bindingIndex: -1,
30995 outputIndex: -1,
30996 // regular values
30997 // TODO(vicb): check
30998 checkIndex: -1,
30999 flags,
31000 childFlags: 0,
31001 directChildFlags: 0,
31002 childMatchedQueries: 0,
31003 ngContentIndex: -1,
31004 matchedQueries: {},
31005 matchedQueryIds: 0,
31006 references: {},
31007 childCount: 0,
31008 bindings: [],
31009 bindingFlags: 0,
31010 outputs: [],
31011 element: null,
31012 provider: null,
31013 text: null,
31014 query: { id, filterId: filterQueryId(id), bindings: bindingDefs },
31015 ngContent: null
31016 };
31017}
31018function createQuery(emitDistinctChangesOnly) {
31019 return new QueryList(emitDistinctChangesOnly);
31020}
31021function dirtyParentQueries(view) {
31022 const queryIds = view.def.nodeMatchedQueries;
31023 while (view.parent && isEmbeddedView(view)) {
31024 let tplDef = view.parentNodeDef;
31025 view = view.parent;
31026 // content queries
31027 const end = tplDef.nodeIndex + tplDef.childCount;
31028 for (let i = 0; i <= end; i++) {
31029 const nodeDef = view.def.nodes[i];
31030 if ((nodeDef.flags & 67108864 /* TypeContentQuery */) &&
31031 (nodeDef.flags & 536870912 /* DynamicQuery */) &&
31032 (nodeDef.query.filterId & queryIds) === nodeDef.query.filterId) {
31033 asQueryList(view, i).setDirty();
31034 }
31035 if ((nodeDef.flags & 1 /* TypeElement */ && i + nodeDef.childCount < tplDef.nodeIndex) ||
31036 !(nodeDef.childFlags & 67108864 /* TypeContentQuery */) ||
31037 !(nodeDef.childFlags & 536870912 /* DynamicQuery */)) {
31038 // skip elements that don't contain the template element or no query.
31039 i += nodeDef.childCount;
31040 }
31041 }
31042 }
31043 // view queries
31044 if (view.def.nodeFlags & 134217728 /* TypeViewQuery */) {
31045 for (let i = 0; i < view.def.nodes.length; i++) {
31046 const nodeDef = view.def.nodes[i];
31047 if ((nodeDef.flags & 134217728 /* TypeViewQuery */) && (nodeDef.flags & 536870912 /* DynamicQuery */)) {
31048 asQueryList(view, i).setDirty();
31049 }
31050 // only visit the root nodes
31051 i += nodeDef.childCount;
31052 }
31053 }
31054}
31055function checkAndUpdateQuery(view, nodeDef) {
31056 const queryList = asQueryList(view, nodeDef.nodeIndex);
31057 if (!queryList.dirty) {
31058 return;
31059 }
31060 let directiveInstance;
31061 let newValues = undefined;
31062 if (nodeDef.flags & 67108864 /* TypeContentQuery */) {
31063 const elementDef = nodeDef.parent.parent;
31064 newValues = calcQueryValues(view, elementDef.nodeIndex, elementDef.nodeIndex + elementDef.childCount, nodeDef.query, []);
31065 directiveInstance = asProviderData(view, nodeDef.parent.nodeIndex).instance;
31066 }
31067 else if (nodeDef.flags & 134217728 /* TypeViewQuery */) {
31068 newValues = calcQueryValues(view, 0, view.def.nodes.length - 1, nodeDef.query, []);
31069 directiveInstance = view.component;
31070 }
31071 queryList.reset(newValues, unwrapElementRef);
31072 const bindings = nodeDef.query.bindings;
31073 let notify = false;
31074 for (let i = 0; i < bindings.length; i++) {
31075 const binding = bindings[i];
31076 let boundValue;
31077 switch (binding.bindingType) {
31078 case 0 /* First */:
31079 boundValue = queryList.first;
31080 break;
31081 case 1 /* All */:
31082 boundValue = queryList;
31083 notify = true;
31084 break;
31085 }
31086 directiveInstance[binding.propName] = boundValue;
31087 }
31088 if (notify) {
31089 queryList.notifyOnChanges();
31090 }
31091}
31092function calcQueryValues(view, startIndex, endIndex, queryDef, values) {
31093 for (let i = startIndex; i <= endIndex; i++) {
31094 const nodeDef = view.def.nodes[i];
31095 const valueType = nodeDef.matchedQueries[queryDef.id];
31096 if (valueType != null) {
31097 values.push(getQueryValue(view, nodeDef, valueType));
31098 }
31099 if (nodeDef.flags & 1 /* TypeElement */ && nodeDef.element.template &&
31100 (nodeDef.element.template.nodeMatchedQueries & queryDef.filterId) ===
31101 queryDef.filterId) {
31102 const elementData = asElementData(view, i);
31103 // check embedded views that were attached at the place of their template,
31104 // but process child nodes first if some match the query (see issue #16568)
31105 if ((nodeDef.childMatchedQueries & queryDef.filterId) === queryDef.filterId) {
31106 calcQueryValues(view, i + 1, i + nodeDef.childCount, queryDef, values);
31107 i += nodeDef.childCount;
31108 }
31109 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
31110 const embeddedViews = elementData.viewContainer._embeddedViews;
31111 for (let k = 0; k < embeddedViews.length; k++) {
31112 const embeddedView = embeddedViews[k];
31113 const dvc = declaredViewContainer(embeddedView);
31114 if (dvc && dvc === elementData) {
31115 calcQueryValues(embeddedView, 0, embeddedView.def.nodes.length - 1, queryDef, values);
31116 }
31117 }
31118 }
31119 const projectedViews = elementData.template._projectedViews;
31120 if (projectedViews) {
31121 for (let k = 0; k < projectedViews.length; k++) {
31122 const projectedView = projectedViews[k];
31123 calcQueryValues(projectedView, 0, projectedView.def.nodes.length - 1, queryDef, values);
31124 }
31125 }
31126 }
31127 if ((nodeDef.childMatchedQueries & queryDef.filterId) !== queryDef.filterId) {
31128 // if no child matches the query, skip the children.
31129 i += nodeDef.childCount;
31130 }
31131 }
31132 return values;
31133}
31134function getQueryValue(view, nodeDef, queryValueType) {
31135 if (queryValueType != null) {
31136 // a match
31137 switch (queryValueType) {
31138 case 1 /* RenderElement */:
31139 return asElementData(view, nodeDef.nodeIndex).renderElement;
31140 case 0 /* ElementRef */:
31141 return new ElementRef(asElementData(view, nodeDef.nodeIndex).renderElement);
31142 case 2 /* TemplateRef */:
31143 return asElementData(view, nodeDef.nodeIndex).template;
31144 case 3 /* ViewContainerRef */:
31145 return asElementData(view, nodeDef.nodeIndex).viewContainer;
31146 case 4 /* Provider */:
31147 return asProviderData(view, nodeDef.nodeIndex).instance;
31148 }
31149 }
31150}
31151
31152/**
31153 * @license
31154 * Copyright Google LLC All Rights Reserved.
31155 *
31156 * Use of this source code is governed by an MIT-style license that can be
31157 * found in the LICENSE file at https://angular.io/license
31158 */
31159function ngContentDef(ngContentIndex, index) {
31160 return {
31161 // will bet set by the view definition
31162 nodeIndex: -1,
31163 parent: null,
31164 renderParent: null,
31165 bindingIndex: -1,
31166 outputIndex: -1,
31167 // regular values
31168 checkIndex: -1,
31169 flags: 8 /* TypeNgContent */,
31170 childFlags: 0,
31171 directChildFlags: 0,
31172 childMatchedQueries: 0,
31173 matchedQueries: {},
31174 matchedQueryIds: 0,
31175 references: {},
31176 ngContentIndex,
31177 childCount: 0,
31178 bindings: [],
31179 bindingFlags: 0,
31180 outputs: [],
31181 element: null,
31182 provider: null,
31183 text: null,
31184 query: null,
31185 ngContent: { index }
31186 };
31187}
31188function appendNgContent(view, renderHost, def) {
31189 const parentEl = getParentRenderElement(view, renderHost, def);
31190 if (!parentEl) {
31191 // Nothing to do if there is no parent element.
31192 return;
31193 }
31194 const ngContentIndex = def.ngContent.index;
31195 visitProjectedRenderNodes(view, ngContentIndex, 1 /* AppendChild */, parentEl, null, undefined);
31196}
31197
31198/**
31199 * @license
31200 * Copyright Google LLC All Rights Reserved.
31201 *
31202 * Use of this source code is governed by an MIT-style license that can be
31203 * found in the LICENSE file at https://angular.io/license
31204 */
31205function purePipeDef(checkIndex, argCount) {
31206 // argCount + 1 to include the pipe as first arg
31207 return _pureExpressionDef(128 /* TypePurePipe */, checkIndex, newArray(argCount + 1));
31208}
31209function pureArrayDef(checkIndex, argCount) {
31210 return _pureExpressionDef(32 /* TypePureArray */, checkIndex, newArray(argCount));
31211}
31212function pureObjectDef(checkIndex, propToIndex) {
31213 const keys = Object.keys(propToIndex);
31214 const nbKeys = keys.length;
31215 const propertyNames = [];
31216 for (let i = 0; i < nbKeys; i++) {
31217 const key = keys[i];
31218 const index = propToIndex[key];
31219 propertyNames.push(key);
31220 }
31221 return _pureExpressionDef(64 /* TypePureObject */, checkIndex, propertyNames);
31222}
31223function _pureExpressionDef(flags, checkIndex, propertyNames) {
31224 const bindings = [];
31225 for (let i = 0; i < propertyNames.length; i++) {
31226 const prop = propertyNames[i];
31227 bindings.push({
31228 flags: 8 /* TypeProperty */,
31229 name: prop,
31230 ns: null,
31231 nonMinifiedName: prop,
31232 securityContext: null,
31233 suffix: null
31234 });
31235 }
31236 return {
31237 // will bet set by the view definition
31238 nodeIndex: -1,
31239 parent: null,
31240 renderParent: null,
31241 bindingIndex: -1,
31242 outputIndex: -1,
31243 // regular values
31244 checkIndex,
31245 flags,
31246 childFlags: 0,
31247 directChildFlags: 0,
31248 childMatchedQueries: 0,
31249 matchedQueries: {},
31250 matchedQueryIds: 0,
31251 references: {},
31252 ngContentIndex: -1,
31253 childCount: 0,
31254 bindings,
31255 bindingFlags: calcBindingFlags(bindings),
31256 outputs: [],
31257 element: null,
31258 provider: null,
31259 text: null,
31260 query: null,
31261 ngContent: null
31262 };
31263}
31264function createPureExpression(view, def) {
31265 return { value: undefined };
31266}
31267function checkAndUpdatePureExpressionInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31268 const bindings = def.bindings;
31269 let changed = false;
31270 const bindLen = bindings.length;
31271 if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0))
31272 changed = true;
31273 if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1))
31274 changed = true;
31275 if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2))
31276 changed = true;
31277 if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3))
31278 changed = true;
31279 if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4))
31280 changed = true;
31281 if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5))
31282 changed = true;
31283 if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6))
31284 changed = true;
31285 if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7))
31286 changed = true;
31287 if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8))
31288 changed = true;
31289 if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9))
31290 changed = true;
31291 if (changed) {
31292 const data = asPureExpressionData(view, def.nodeIndex);
31293 let value;
31294 switch (def.flags & 201347067 /* Types */) {
31295 case 32 /* TypePureArray */:
31296 value = [];
31297 if (bindLen > 0)
31298 value.push(v0);
31299 if (bindLen > 1)
31300 value.push(v1);
31301 if (bindLen > 2)
31302 value.push(v2);
31303 if (bindLen > 3)
31304 value.push(v3);
31305 if (bindLen > 4)
31306 value.push(v4);
31307 if (bindLen > 5)
31308 value.push(v5);
31309 if (bindLen > 6)
31310 value.push(v6);
31311 if (bindLen > 7)
31312 value.push(v7);
31313 if (bindLen > 8)
31314 value.push(v8);
31315 if (bindLen > 9)
31316 value.push(v9);
31317 break;
31318 case 64 /* TypePureObject */:
31319 value = {};
31320 if (bindLen > 0)
31321 value[bindings[0].name] = v0;
31322 if (bindLen > 1)
31323 value[bindings[1].name] = v1;
31324 if (bindLen > 2)
31325 value[bindings[2].name] = v2;
31326 if (bindLen > 3)
31327 value[bindings[3].name] = v3;
31328 if (bindLen > 4)
31329 value[bindings[4].name] = v4;
31330 if (bindLen > 5)
31331 value[bindings[5].name] = v5;
31332 if (bindLen > 6)
31333 value[bindings[6].name] = v6;
31334 if (bindLen > 7)
31335 value[bindings[7].name] = v7;
31336 if (bindLen > 8)
31337 value[bindings[8].name] = v8;
31338 if (bindLen > 9)
31339 value[bindings[9].name] = v9;
31340 break;
31341 case 128 /* TypePurePipe */:
31342 const pipe = v0;
31343 switch (bindLen) {
31344 case 1:
31345 value = pipe.transform(v0);
31346 break;
31347 case 2:
31348 value = pipe.transform(v1);
31349 break;
31350 case 3:
31351 value = pipe.transform(v1, v2);
31352 break;
31353 case 4:
31354 value = pipe.transform(v1, v2, v3);
31355 break;
31356 case 5:
31357 value = pipe.transform(v1, v2, v3, v4);
31358 break;
31359 case 6:
31360 value = pipe.transform(v1, v2, v3, v4, v5);
31361 break;
31362 case 7:
31363 value = pipe.transform(v1, v2, v3, v4, v5, v6);
31364 break;
31365 case 8:
31366 value = pipe.transform(v1, v2, v3, v4, v5, v6, v7);
31367 break;
31368 case 9:
31369 value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8);
31370 break;
31371 case 10:
31372 value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8, v9);
31373 break;
31374 }
31375 break;
31376 }
31377 data.value = value;
31378 }
31379 return changed;
31380}
31381function checkAndUpdatePureExpressionDynamic(view, def, values) {
31382 const bindings = def.bindings;
31383 let changed = false;
31384 for (let i = 0; i < values.length; i++) {
31385 // Note: We need to loop over all values, so that
31386 // the old values are updates as well!
31387 if (checkAndUpdateBinding(view, def, i, values[i])) {
31388 changed = true;
31389 }
31390 }
31391 if (changed) {
31392 const data = asPureExpressionData(view, def.nodeIndex);
31393 let value;
31394 switch (def.flags & 201347067 /* Types */) {
31395 case 32 /* TypePureArray */:
31396 value = values;
31397 break;
31398 case 64 /* TypePureObject */:
31399 value = {};
31400 for (let i = 0; i < values.length; i++) {
31401 value[bindings[i].name] = values[i];
31402 }
31403 break;
31404 case 128 /* TypePurePipe */:
31405 const pipe = values[0];
31406 const params = values.slice(1);
31407 value = pipe.transform(...params);
31408 break;
31409 }
31410 data.value = value;
31411 }
31412 return changed;
31413}
31414
31415/**
31416 * @license
31417 * Copyright Google LLC All Rights Reserved.
31418 *
31419 * Use of this source code is governed by an MIT-style license that can be
31420 * found in the LICENSE file at https://angular.io/license
31421 */
31422function textDef(checkIndex, ngContentIndex, staticText) {
31423 const bindings = [];
31424 for (let i = 1; i < staticText.length; i++) {
31425 bindings[i - 1] = {
31426 flags: 8 /* TypeProperty */,
31427 name: null,
31428 ns: null,
31429 nonMinifiedName: null,
31430 securityContext: null,
31431 suffix: staticText[i],
31432 };
31433 }
31434 return {
31435 // will bet set by the view definition
31436 nodeIndex: -1,
31437 parent: null,
31438 renderParent: null,
31439 bindingIndex: -1,
31440 outputIndex: -1,
31441 // regular values
31442 checkIndex,
31443 flags: 2 /* TypeText */,
31444 childFlags: 0,
31445 directChildFlags: 0,
31446 childMatchedQueries: 0,
31447 matchedQueries: {},
31448 matchedQueryIds: 0,
31449 references: {},
31450 ngContentIndex,
31451 childCount: 0,
31452 bindings,
31453 bindingFlags: 8 /* TypeProperty */,
31454 outputs: [],
31455 element: null,
31456 provider: null,
31457 text: { prefix: staticText[0] },
31458 query: null,
31459 ngContent: null,
31460 };
31461}
31462function createText(view, renderHost, def) {
31463 let renderNode;
31464 const renderer = view.renderer;
31465 renderNode = renderer.createText(def.text.prefix);
31466 const parentEl = getParentRenderElement(view, renderHost, def);
31467 if (parentEl) {
31468 renderer.appendChild(parentEl, renderNode);
31469 }
31470 return { renderText: renderNode };
31471}
31472function checkAndUpdateTextInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31473 let changed = false;
31474 const bindings = def.bindings;
31475 const bindLen = bindings.length;
31476 if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0))
31477 changed = true;
31478 if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1))
31479 changed = true;
31480 if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2))
31481 changed = true;
31482 if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3))
31483 changed = true;
31484 if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4))
31485 changed = true;
31486 if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5))
31487 changed = true;
31488 if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6))
31489 changed = true;
31490 if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7))
31491 changed = true;
31492 if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8))
31493 changed = true;
31494 if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9))
31495 changed = true;
31496 if (changed) {
31497 let value = def.text.prefix;
31498 if (bindLen > 0)
31499 value += _addInterpolationPart(v0, bindings[0]);
31500 if (bindLen > 1)
31501 value += _addInterpolationPart(v1, bindings[1]);
31502 if (bindLen > 2)
31503 value += _addInterpolationPart(v2, bindings[2]);
31504 if (bindLen > 3)
31505 value += _addInterpolationPart(v3, bindings[3]);
31506 if (bindLen > 4)
31507 value += _addInterpolationPart(v4, bindings[4]);
31508 if (bindLen > 5)
31509 value += _addInterpolationPart(v5, bindings[5]);
31510 if (bindLen > 6)
31511 value += _addInterpolationPart(v6, bindings[6]);
31512 if (bindLen > 7)
31513 value += _addInterpolationPart(v7, bindings[7]);
31514 if (bindLen > 8)
31515 value += _addInterpolationPart(v8, bindings[8]);
31516 if (bindLen > 9)
31517 value += _addInterpolationPart(v9, bindings[9]);
31518 const renderNode = asTextData(view, def.nodeIndex).renderText;
31519 view.renderer.setValue(renderNode, value);
31520 }
31521 return changed;
31522}
31523function checkAndUpdateTextDynamic(view, def, values) {
31524 const bindings = def.bindings;
31525 let changed = false;
31526 for (let i = 0; i < values.length; i++) {
31527 // Note: We need to loop over all values, so that
31528 // the old values are updates as well!
31529 if (checkAndUpdateBinding(view, def, i, values[i])) {
31530 changed = true;
31531 }
31532 }
31533 if (changed) {
31534 let value = '';
31535 for (let i = 0; i < values.length; i++) {
31536 value = value + _addInterpolationPart(values[i], bindings[i]);
31537 }
31538 value = def.text.prefix + value;
31539 const renderNode = asTextData(view, def.nodeIndex).renderText;
31540 view.renderer.setValue(renderNode, value);
31541 }
31542 return changed;
31543}
31544function _addInterpolationPart(value, binding) {
31545 const valueStr = value != null ? value.toString() : '';
31546 return valueStr + binding.suffix;
31547}
31548
31549/**
31550 * @license
31551 * Copyright Google LLC All Rights Reserved.
31552 *
31553 * Use of this source code is governed by an MIT-style license that can be
31554 * found in the LICENSE file at https://angular.io/license
31555 */
31556function viewDef(flags, nodes, updateDirectives, updateRenderer) {
31557 // clone nodes and set auto calculated values
31558 let viewBindingCount = 0;
31559 let viewDisposableCount = 0;
31560 let viewNodeFlags = 0;
31561 let viewRootNodeFlags = 0;
31562 let viewMatchedQueries = 0;
31563 let currentParent = null;
31564 let currentRenderParent = null;
31565 let currentElementHasPublicProviders = false;
31566 let currentElementHasPrivateProviders = false;
31567 let lastRenderRootNode = null;
31568 for (let i = 0; i < nodes.length; i++) {
31569 const node = nodes[i];
31570 node.nodeIndex = i;
31571 node.parent = currentParent;
31572 node.bindingIndex = viewBindingCount;
31573 node.outputIndex = viewDisposableCount;
31574 node.renderParent = currentRenderParent;
31575 viewNodeFlags |= node.flags;
31576 viewMatchedQueries |= node.matchedQueryIds;
31577 if (node.element) {
31578 const elDef = node.element;
31579 elDef.publicProviders =
31580 currentParent ? currentParent.element.publicProviders : Object.create(null);
31581 elDef.allProviders = elDef.publicProviders;
31582 // Note: We assume that all providers of an element are before any child element!
31583 currentElementHasPublicProviders = false;
31584 currentElementHasPrivateProviders = false;
31585 if (node.element.template) {
31586 viewMatchedQueries |= node.element.template.nodeMatchedQueries;
31587 }
31588 }
31589 validateNode(currentParent, node, nodes.length);
31590 viewBindingCount += node.bindings.length;
31591 viewDisposableCount += node.outputs.length;
31592 if (!currentRenderParent && (node.flags & 3 /* CatRenderNode */)) {
31593 lastRenderRootNode = node;
31594 }
31595 if (node.flags & 20224 /* CatProvider */) {
31596 if (!currentElementHasPublicProviders) {
31597 currentElementHasPublicProviders = true;
31598 // Use prototypical inheritance to not get O(n^2) complexity...
31599 currentParent.element.publicProviders =
31600 Object.create(currentParent.element.publicProviders);
31601 currentParent.element.allProviders = currentParent.element.publicProviders;
31602 }
31603 const isPrivateService = (node.flags & 8192 /* PrivateProvider */) !== 0;
31604 const isComponent = (node.flags & 32768 /* Component */) !== 0;
31605 if (!isPrivateService || isComponent) {
31606 currentParent.element.publicProviders[tokenKey(node.provider.token)] = node;
31607 }
31608 else {
31609 if (!currentElementHasPrivateProviders) {
31610 currentElementHasPrivateProviders = true;
31611 // Use prototypical inheritance to not get O(n^2) complexity...
31612 currentParent.element.allProviders =
31613 Object.create(currentParent.element.publicProviders);
31614 }
31615 currentParent.element.allProviders[tokenKey(node.provider.token)] = node;
31616 }
31617 if (isComponent) {
31618 currentParent.element.componentProvider = node;
31619 }
31620 }
31621 if (currentParent) {
31622 currentParent.childFlags |= node.flags;
31623 currentParent.directChildFlags |= node.flags;
31624 currentParent.childMatchedQueries |= node.matchedQueryIds;
31625 if (node.element && node.element.template) {
31626 currentParent.childMatchedQueries |= node.element.template.nodeMatchedQueries;
31627 }
31628 }
31629 else {
31630 viewRootNodeFlags |= node.flags;
31631 }
31632 if (node.childCount > 0) {
31633 currentParent = node;
31634 if (!isNgContainer(node)) {
31635 currentRenderParent = node;
31636 }
31637 }
31638 else {
31639 // When the current node has no children, check if it is the last children of its parent.
31640 // When it is, propagate the flags up.
31641 // The loop is required because an element could be the last transitive children of several
31642 // elements. We loop to either the root or the highest opened element (= with remaining
31643 // children)
31644 while (currentParent && i === currentParent.nodeIndex + currentParent.childCount) {
31645 const newParent = currentParent.parent;
31646 if (newParent) {
31647 newParent.childFlags |= currentParent.childFlags;
31648 newParent.childMatchedQueries |= currentParent.childMatchedQueries;
31649 }
31650 currentParent = newParent;
31651 // We also need to update the render parent & account for ng-container
31652 if (currentParent && isNgContainer(currentParent)) {
31653 currentRenderParent = currentParent.renderParent;
31654 }
31655 else {
31656 currentRenderParent = currentParent;
31657 }
31658 }
31659 }
31660 }
31661 const handleEvent = (view, nodeIndex, eventName, event) => nodes[nodeIndex].element.handleEvent(view, eventName, event);
31662 return {
31663 // Will be filled later...
31664 factory: null,
31665 nodeFlags: viewNodeFlags,
31666 rootNodeFlags: viewRootNodeFlags,
31667 nodeMatchedQueries: viewMatchedQueries,
31668 flags,
31669 nodes: nodes,
31670 updateDirectives: updateDirectives || NOOP,
31671 updateRenderer: updateRenderer || NOOP,
31672 handleEvent,
31673 bindingCount: viewBindingCount,
31674 outputCount: viewDisposableCount,
31675 lastRenderRootNode
31676 };
31677}
31678function isNgContainer(node) {
31679 return (node.flags & 1 /* TypeElement */) !== 0 && node.element.name === null;
31680}
31681function validateNode(parent, node, nodeCount) {
31682 const template = node.element && node.element.template;
31683 if (template) {
31684 if (!template.lastRenderRootNode) {
31685 throw new Error(`Illegal State: Embedded templates without nodes are not allowed!`);
31686 }
31687 if (template.lastRenderRootNode &&
31688 template.lastRenderRootNode.flags & 16777216 /* EmbeddedViews */) {
31689 throw new Error(`Illegal State: Last root node of a template can't have embedded views, at index ${node.nodeIndex}!`);
31690 }
31691 }
31692 if (node.flags & 20224 /* CatProvider */) {
31693 const parentFlags = parent ? parent.flags : 0;
31694 if ((parentFlags & 1 /* TypeElement */) === 0) {
31695 throw new Error(`Illegal State: StaticProvider/Directive nodes need to be children of elements or anchors, at index ${node.nodeIndex}!`);
31696 }
31697 }
31698 if (node.query) {
31699 if (node.flags & 67108864 /* TypeContentQuery */ &&
31700 (!parent || (parent.flags & 16384 /* TypeDirective */) === 0)) {
31701 throw new Error(`Illegal State: Content Query nodes need to be children of directives, at index ${node.nodeIndex}!`);
31702 }
31703 if (node.flags & 134217728 /* TypeViewQuery */ && parent) {
31704 throw new Error(`Illegal State: View Query nodes have to be top level nodes, at index ${node.nodeIndex}!`);
31705 }
31706 }
31707 if (node.childCount) {
31708 const parentEnd = parent ? parent.nodeIndex + parent.childCount : nodeCount - 1;
31709 if (node.nodeIndex <= parentEnd && node.nodeIndex + node.childCount > parentEnd) {
31710 throw new Error(`Illegal State: childCount of node leads outside of parent, at index ${node.nodeIndex}!`);
31711 }
31712 }
31713}
31714function createEmbeddedView(parent, anchorDef, viewDef, context) {
31715 // embedded views are seen as siblings to the anchor, so we need
31716 // to get the parent of the anchor and use it as parentIndex.
31717 const view = createView(parent.root, parent.renderer, parent, anchorDef, viewDef);
31718 initView(view, parent.component, context);
31719 createViewNodes(view);
31720 return view;
31721}
31722function createRootView(root, def, context) {
31723 const view = createView(root, root.renderer, null, null, def);
31724 initView(view, context, context);
31725 createViewNodes(view);
31726 return view;
31727}
31728function createComponentView(parentView, nodeDef, viewDef, hostElement) {
31729 const rendererType = nodeDef.element.componentRendererType;
31730 let compRenderer;
31731 if (!rendererType) {
31732 compRenderer = parentView.root.renderer;
31733 }
31734 else {
31735 compRenderer = parentView.root.rendererFactory.createRenderer(hostElement, rendererType);
31736 }
31737 return createView(parentView.root, compRenderer, parentView, nodeDef.element.componentProvider, viewDef);
31738}
31739function createView(root, renderer, parent, parentNodeDef, def) {
31740 const nodes = new Array(def.nodes.length);
31741 const disposables = def.outputCount ? new Array(def.outputCount) : null;
31742 const view = {
31743 def,
31744 parent,
31745 viewContainerParent: null,
31746 parentNodeDef,
31747 context: null,
31748 component: null,
31749 nodes,
31750 state: 13 /* CatInit */,
31751 root,
31752 renderer,
31753 oldValues: new Array(def.bindingCount),
31754 disposables,
31755 initIndex: -1
31756 };
31757 return view;
31758}
31759function initView(view, component, context) {
31760 view.component = component;
31761 view.context = context;
31762}
31763function createViewNodes(view) {
31764 let renderHost;
31765 if (isComponentView(view)) {
31766 const hostDef = view.parentNodeDef;
31767 renderHost = asElementData(view.parent, hostDef.parent.nodeIndex).renderElement;
31768 }
31769 const def = view.def;
31770 const nodes = view.nodes;
31771 for (let i = 0; i < def.nodes.length; i++) {
31772 const nodeDef = def.nodes[i];
31773 Services.setCurrentNode(view, i);
31774 let nodeData;
31775 switch (nodeDef.flags & 201347067 /* Types */) {
31776 case 1 /* TypeElement */:
31777 const el = createElement(view, renderHost, nodeDef);
31778 let componentView = undefined;
31779 if (nodeDef.flags & 33554432 /* ComponentView */) {
31780 const compViewDef = resolveDefinition(nodeDef.element.componentView);
31781 componentView = Services.createComponentView(view, nodeDef, compViewDef, el);
31782 }
31783 listenToElementOutputs(view, componentView, nodeDef, el);
31784 nodeData = {
31785 renderElement: el,
31786 componentView,
31787 viewContainer: null,
31788 template: nodeDef.element.template ? createTemplateData(view, nodeDef) : undefined
31789 };
31790 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
31791 nodeData.viewContainer = createViewContainerData(view, nodeDef, nodeData);
31792 }
31793 break;
31794 case 2 /* TypeText */:
31795 nodeData = createText(view, renderHost, nodeDef);
31796 break;
31797 case 512 /* TypeClassProvider */:
31798 case 1024 /* TypeFactoryProvider */:
31799 case 2048 /* TypeUseExistingProvider */:
31800 case 256 /* TypeValueProvider */: {
31801 nodeData = nodes[i];
31802 if (!nodeData && !(nodeDef.flags & 4096 /* LazyProvider */)) {
31803 const instance = createProviderInstance(view, nodeDef);
31804 nodeData = { instance };
31805 }
31806 break;
31807 }
31808 case 16 /* TypePipe */: {
31809 const instance = createPipeInstance(view, nodeDef);
31810 nodeData = { instance };
31811 break;
31812 }
31813 case 16384 /* TypeDirective */: {
31814 nodeData = nodes[i];
31815 if (!nodeData) {
31816 const instance = createDirectiveInstance(view, nodeDef);
31817 nodeData = { instance };
31818 }
31819 if (nodeDef.flags & 32768 /* Component */) {
31820 const compView = asElementData(view, nodeDef.parent.nodeIndex).componentView;
31821 initView(compView, nodeData.instance, nodeData.instance);
31822 }
31823 break;
31824 }
31825 case 32 /* TypePureArray */:
31826 case 64 /* TypePureObject */:
31827 case 128 /* TypePurePipe */:
31828 nodeData = createPureExpression(view, nodeDef);
31829 break;
31830 case 67108864 /* TypeContentQuery */:
31831 case 134217728 /* TypeViewQuery */:
31832 nodeData = createQuery((nodeDef.flags & -2147483648 /* EmitDistinctChangesOnly */) ===
31833 -2147483648 /* EmitDistinctChangesOnly */);
31834 break;
31835 case 8 /* TypeNgContent */:
31836 appendNgContent(view, renderHost, nodeDef);
31837 // no runtime data needed for NgContent...
31838 nodeData = undefined;
31839 break;
31840 }
31841 nodes[i] = nodeData;
31842 }
31843 // Create the ViewData.nodes of component views after we created everything else,
31844 // so that e.g. ng-content works
31845 execComponentViewsAction(view, ViewAction.CreateViewNodes);
31846 // fill static content and view queries
31847 execQueriesAction(view, 67108864 /* TypeContentQuery */ | 134217728 /* TypeViewQuery */, 268435456 /* StaticQuery */, 0 /* CheckAndUpdate */);
31848}
31849function checkNoChangesView(view) {
31850 markProjectedViewsForCheck(view);
31851 Services.updateDirectives(view, 1 /* CheckNoChanges */);
31852 execEmbeddedViewsAction(view, ViewAction.CheckNoChanges);
31853 Services.updateRenderer(view, 1 /* CheckNoChanges */);
31854 execComponentViewsAction(view, ViewAction.CheckNoChanges);
31855 // Note: We don't check queries for changes as we didn't do this in v2.x.
31856 // TODO(tbosch): investigate if we can enable the check again in v5.x with a nicer error message.
31857 view.state &= ~(64 /* CheckProjectedViews */ | 32 /* CheckProjectedView */);
31858}
31859function checkAndUpdateView(view) {
31860 if (view.state & 1 /* BeforeFirstCheck */) {
31861 view.state &= ~1 /* BeforeFirstCheck */;
31862 view.state |= 2 /* FirstCheck */;
31863 }
31864 else {
31865 view.state &= ~2 /* FirstCheck */;
31866 }
31867 shiftInitState(view, 0 /* InitState_BeforeInit */, 256 /* InitState_CallingOnInit */);
31868 markProjectedViewsForCheck(view);
31869 Services.updateDirectives(view, 0 /* CheckAndUpdate */);
31870 execEmbeddedViewsAction(view, ViewAction.CheckAndUpdate);
31871 execQueriesAction(view, 67108864 /* TypeContentQuery */, 536870912 /* DynamicQuery */, 0 /* CheckAndUpdate */);
31872 let callInit = shiftInitState(view, 256 /* InitState_CallingOnInit */, 512 /* InitState_CallingAfterContentInit */);
31873 callLifecycleHooksChildrenFirst(view, 2097152 /* AfterContentChecked */ | (callInit ? 1048576 /* AfterContentInit */ : 0));
31874 Services.updateRenderer(view, 0 /* CheckAndUpdate */);
31875 execComponentViewsAction(view, ViewAction.CheckAndUpdate);
31876 execQueriesAction(view, 134217728 /* TypeViewQuery */, 536870912 /* DynamicQuery */, 0 /* CheckAndUpdate */);
31877 callInit = shiftInitState(view, 512 /* InitState_CallingAfterContentInit */, 768 /* InitState_CallingAfterViewInit */);
31878 callLifecycleHooksChildrenFirst(view, 8388608 /* AfterViewChecked */ | (callInit ? 4194304 /* AfterViewInit */ : 0));
31879 if (view.def.flags & 2 /* OnPush */) {
31880 view.state &= ~8 /* ChecksEnabled */;
31881 }
31882 view.state &= ~(64 /* CheckProjectedViews */ | 32 /* CheckProjectedView */);
31883 shiftInitState(view, 768 /* InitState_CallingAfterViewInit */, 1024 /* InitState_AfterInit */);
31884}
31885function checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31886 if (argStyle === 0 /* Inline */) {
31887 return checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31888 }
31889 else {
31890 return checkAndUpdateNodeDynamic(view, nodeDef, v0);
31891 }
31892}
31893function markProjectedViewsForCheck(view) {
31894 const def = view.def;
31895 if (!(def.nodeFlags & 4 /* ProjectedTemplate */)) {
31896 return;
31897 }
31898 for (let i = 0; i < def.nodes.length; i++) {
31899 const nodeDef = def.nodes[i];
31900 if (nodeDef.flags & 4 /* ProjectedTemplate */) {
31901 const projectedViews = asElementData(view, i).template._projectedViews;
31902 if (projectedViews) {
31903 for (let i = 0; i < projectedViews.length; i++) {
31904 const projectedView = projectedViews[i];
31905 projectedView.state |= 32 /* CheckProjectedView */;
31906 markParentViewsForCheckProjectedViews(projectedView, view);
31907 }
31908 }
31909 }
31910 else if ((nodeDef.childFlags & 4 /* ProjectedTemplate */) === 0) {
31911 // a parent with leafs
31912 // no child is a component,
31913 // then skip the children
31914 i += nodeDef.childCount;
31915 }
31916 }
31917}
31918function checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31919 switch (nodeDef.flags & 201347067 /* Types */) {
31920 case 1 /* TypeElement */:
31921 return checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31922 case 2 /* TypeText */:
31923 return checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31924 case 16384 /* TypeDirective */:
31925 return checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31926 case 32 /* TypePureArray */:
31927 case 64 /* TypePureObject */:
31928 case 128 /* TypePurePipe */:
31929 return checkAndUpdatePureExpressionInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31930 default:
31931 throw 'unreachable';
31932 }
31933}
31934function checkAndUpdateNodeDynamic(view, nodeDef, values) {
31935 switch (nodeDef.flags & 201347067 /* Types */) {
31936 case 1 /* TypeElement */:
31937 return checkAndUpdateElementDynamic(view, nodeDef, values);
31938 case 2 /* TypeText */:
31939 return checkAndUpdateTextDynamic(view, nodeDef, values);
31940 case 16384 /* TypeDirective */:
31941 return checkAndUpdateDirectiveDynamic(view, nodeDef, values);
31942 case 32 /* TypePureArray */:
31943 case 64 /* TypePureObject */:
31944 case 128 /* TypePurePipe */:
31945 return checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
31946 default:
31947 throw 'unreachable';
31948 }
31949}
31950function checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31951 if (argStyle === 0 /* Inline */) {
31952 checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31953 }
31954 else {
31955 checkNoChangesNodeDynamic(view, nodeDef, v0);
31956 }
31957 // Returning false is ok here as we would have thrown in case of a change.
31958 return false;
31959}
31960function checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31961 const bindLen = nodeDef.bindings.length;
31962 if (bindLen > 0)
31963 checkBindingNoChanges(view, nodeDef, 0, v0);
31964 if (bindLen > 1)
31965 checkBindingNoChanges(view, nodeDef, 1, v1);
31966 if (bindLen > 2)
31967 checkBindingNoChanges(view, nodeDef, 2, v2);
31968 if (bindLen > 3)
31969 checkBindingNoChanges(view, nodeDef, 3, v3);
31970 if (bindLen > 4)
31971 checkBindingNoChanges(view, nodeDef, 4, v4);
31972 if (bindLen > 5)
31973 checkBindingNoChanges(view, nodeDef, 5, v5);
31974 if (bindLen > 6)
31975 checkBindingNoChanges(view, nodeDef, 6, v6);
31976 if (bindLen > 7)
31977 checkBindingNoChanges(view, nodeDef, 7, v7);
31978 if (bindLen > 8)
31979 checkBindingNoChanges(view, nodeDef, 8, v8);
31980 if (bindLen > 9)
31981 checkBindingNoChanges(view, nodeDef, 9, v9);
31982}
31983function checkNoChangesNodeDynamic(view, nodeDef, values) {
31984 for (let i = 0; i < values.length; i++) {
31985 checkBindingNoChanges(view, nodeDef, i, values[i]);
31986 }
31987}
31988/**
31989 * Workaround https://github.com/angular/tsickle/issues/497
31990 * @suppress {misplacedTypeAnnotation}
31991 */
31992function checkNoChangesQuery(view, nodeDef) {
31993 const queryList = asQueryList(view, nodeDef.nodeIndex);
31994 if (queryList.dirty) {
31995 throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, nodeDef.nodeIndex), `Query ${nodeDef.query.id} not dirty`, `Query ${nodeDef.query.id} dirty`, (view.state & 1 /* BeforeFirstCheck */) !== 0);
31996 }
31997}
31998function destroyView(view) {
31999 if (view.state & 128 /* Destroyed */) {
32000 return;
32001 }
32002 execEmbeddedViewsAction(view, ViewAction.Destroy);
32003 execComponentViewsAction(view, ViewAction.Destroy);
32004 callLifecycleHooksChildrenFirst(view, 131072 /* OnDestroy */);
32005 if (view.disposables) {
32006 for (let i = 0; i < view.disposables.length; i++) {
32007 view.disposables[i]();
32008 }
32009 }
32010 detachProjectedView(view);
32011 if (view.renderer.destroyNode) {
32012 destroyViewNodes(view);
32013 }
32014 if (isComponentView(view)) {
32015 view.renderer.destroy();
32016 }
32017 view.state |= 128 /* Destroyed */;
32018}
32019function destroyViewNodes(view) {
32020 const len = view.def.nodes.length;
32021 for (let i = 0; i < len; i++) {
32022 const def = view.def.nodes[i];
32023 if (def.flags & 1 /* TypeElement */) {
32024 view.renderer.destroyNode(asElementData(view, i).renderElement);
32025 }
32026 else if (def.flags & 2 /* TypeText */) {
32027 view.renderer.destroyNode(asTextData(view, i).renderText);
32028 }
32029 else if (def.flags & 67108864 /* TypeContentQuery */ || def.flags & 134217728 /* TypeViewQuery */) {
32030 asQueryList(view, i).destroy();
32031 }
32032 }
32033}
32034var ViewAction;
32035(function (ViewAction) {
32036 ViewAction[ViewAction["CreateViewNodes"] = 0] = "CreateViewNodes";
32037 ViewAction[ViewAction["CheckNoChanges"] = 1] = "CheckNoChanges";
32038 ViewAction[ViewAction["CheckNoChangesProjectedViews"] = 2] = "CheckNoChangesProjectedViews";
32039 ViewAction[ViewAction["CheckAndUpdate"] = 3] = "CheckAndUpdate";
32040 ViewAction[ViewAction["CheckAndUpdateProjectedViews"] = 4] = "CheckAndUpdateProjectedViews";
32041 ViewAction[ViewAction["Destroy"] = 5] = "Destroy";
32042})(ViewAction || (ViewAction = {}));
32043function execComponentViewsAction(view, action) {
32044 const def = view.def;
32045 if (!(def.nodeFlags & 33554432 /* ComponentView */)) {
32046 return;
32047 }
32048 for (let i = 0; i < def.nodes.length; i++) {
32049 const nodeDef = def.nodes[i];
32050 if (nodeDef.flags & 33554432 /* ComponentView */) {
32051 // a leaf
32052 callViewAction(asElementData(view, i).componentView, action);
32053 }
32054 else if ((nodeDef.childFlags & 33554432 /* ComponentView */) === 0) {
32055 // a parent with leafs
32056 // no child is a component,
32057 // then skip the children
32058 i += nodeDef.childCount;
32059 }
32060 }
32061}
32062function execEmbeddedViewsAction(view, action) {
32063 const def = view.def;
32064 if (!(def.nodeFlags & 16777216 /* EmbeddedViews */)) {
32065 return;
32066 }
32067 for (let i = 0; i < def.nodes.length; i++) {
32068 const nodeDef = def.nodes[i];
32069 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
32070 // a leaf
32071 const embeddedViews = asElementData(view, i).viewContainer._embeddedViews;
32072 for (let k = 0; k < embeddedViews.length; k++) {
32073 callViewAction(embeddedViews[k], action);
32074 }
32075 }
32076 else if ((nodeDef.childFlags & 16777216 /* EmbeddedViews */) === 0) {
32077 // a parent with leafs
32078 // no child is a component,
32079 // then skip the children
32080 i += nodeDef.childCount;
32081 }
32082 }
32083}
32084function callViewAction(view, action) {
32085 const viewState = view.state;
32086 switch (action) {
32087 case ViewAction.CheckNoChanges:
32088 if ((viewState & 128 /* Destroyed */) === 0) {
32089 if ((viewState & 12 /* CatDetectChanges */) === 12 /* CatDetectChanges */) {
32090 checkNoChangesView(view);
32091 }
32092 else if (viewState & 64 /* CheckProjectedViews */) {
32093 execProjectedViewsAction(view, ViewAction.CheckNoChangesProjectedViews);
32094 }
32095 }
32096 break;
32097 case ViewAction.CheckNoChangesProjectedViews:
32098 if ((viewState & 128 /* Destroyed */) === 0) {
32099 if (viewState & 32 /* CheckProjectedView */) {
32100 checkNoChangesView(view);
32101 }
32102 else if (viewState & 64 /* CheckProjectedViews */) {
32103 execProjectedViewsAction(view, action);
32104 }
32105 }
32106 break;
32107 case ViewAction.CheckAndUpdate:
32108 if ((viewState & 128 /* Destroyed */) === 0) {
32109 if ((viewState & 12 /* CatDetectChanges */) === 12 /* CatDetectChanges */) {
32110 checkAndUpdateView(view);
32111 }
32112 else if (viewState & 64 /* CheckProjectedViews */) {
32113 execProjectedViewsAction(view, ViewAction.CheckAndUpdateProjectedViews);
32114 }
32115 }
32116 break;
32117 case ViewAction.CheckAndUpdateProjectedViews:
32118 if ((viewState & 128 /* Destroyed */) === 0) {
32119 if (viewState & 32 /* CheckProjectedView */) {
32120 checkAndUpdateView(view);
32121 }
32122 else if (viewState & 64 /* CheckProjectedViews */) {
32123 execProjectedViewsAction(view, action);
32124 }
32125 }
32126 break;
32127 case ViewAction.Destroy:
32128 // Note: destroyView recurses over all views,
32129 // so we don't need to special case projected views here.
32130 destroyView(view);
32131 break;
32132 case ViewAction.CreateViewNodes:
32133 createViewNodes(view);
32134 break;
32135 }
32136}
32137function execProjectedViewsAction(view, action) {
32138 execEmbeddedViewsAction(view, action);
32139 execComponentViewsAction(view, action);
32140}
32141function execQueriesAction(view, queryFlags, staticDynamicQueryFlag, checkType) {
32142 if (!(view.def.nodeFlags & queryFlags) || !(view.def.nodeFlags & staticDynamicQueryFlag)) {
32143 return;
32144 }
32145 const nodeCount = view.def.nodes.length;
32146 for (let i = 0; i < nodeCount; i++) {
32147 const nodeDef = view.def.nodes[i];
32148 if ((nodeDef.flags & queryFlags) && (nodeDef.flags & staticDynamicQueryFlag)) {
32149 Services.setCurrentNode(view, nodeDef.nodeIndex);
32150 switch (checkType) {
32151 case 0 /* CheckAndUpdate */:
32152 checkAndUpdateQuery(view, nodeDef);
32153 break;
32154 case 1 /* CheckNoChanges */:
32155 checkNoChangesQuery(view, nodeDef);
32156 break;
32157 }
32158 }
32159 if (!(nodeDef.childFlags & queryFlags) || !(nodeDef.childFlags & staticDynamicQueryFlag)) {
32160 // no child has a matching query
32161 // then skip the children
32162 i += nodeDef.childCount;
32163 }
32164 }
32165}
32166
32167/**
32168 * @license
32169 * Copyright Google LLC All Rights Reserved.
32170 *
32171 * Use of this source code is governed by an MIT-style license that can be
32172 * found in the LICENSE file at https://angular.io/license
32173 */
32174let initialized = false;
32175function initServicesIfNeeded() {
32176 if (initialized) {
32177 return;
32178 }
32179 initialized = true;
32180 const services = isDevMode() ? createDebugServices() : createProdServices();
32181 Services.setCurrentNode = services.setCurrentNode;
32182 Services.createRootView = services.createRootView;
32183 Services.createEmbeddedView = services.createEmbeddedView;
32184 Services.createComponentView = services.createComponentView;
32185 Services.createNgModuleRef = services.createNgModuleRef;
32186 Services.overrideProvider = services.overrideProvider;
32187 Services.overrideComponentView = services.overrideComponentView;
32188 Services.clearOverrides = services.clearOverrides;
32189 Services.checkAndUpdateView = services.checkAndUpdateView;
32190 Services.checkNoChangesView = services.checkNoChangesView;
32191 Services.destroyView = services.destroyView;
32192 Services.resolveDep = resolveDep;
32193 Services.createDebugContext = services.createDebugContext;
32194 Services.handleEvent = services.handleEvent;
32195 Services.updateDirectives = services.updateDirectives;
32196 Services.updateRenderer = services.updateRenderer;
32197 Services.dirtyParentQueries = dirtyParentQueries;
32198}
32199function createProdServices() {
32200 return {
32201 setCurrentNode: () => { },
32202 createRootView: createProdRootView,
32203 createEmbeddedView: createEmbeddedView,
32204 createComponentView: createComponentView,
32205 createNgModuleRef: createNgModuleRef,
32206 overrideProvider: NOOP,
32207 overrideComponentView: NOOP,
32208 clearOverrides: NOOP,
32209 checkAndUpdateView: checkAndUpdateView,
32210 checkNoChangesView: checkNoChangesView,
32211 destroyView: destroyView,
32212 createDebugContext: (view, nodeIndex) => new DebugContext_(view, nodeIndex),
32213 handleEvent: (view, nodeIndex, eventName, event) => view.def.handleEvent(view, nodeIndex, eventName, event),
32214 updateDirectives: (view, checkType) => view.def.updateDirectives(checkType === 0 /* CheckAndUpdate */ ? prodCheckAndUpdateNode : prodCheckNoChangesNode, view),
32215 updateRenderer: (view, checkType) => view.def.updateRenderer(checkType === 0 /* CheckAndUpdate */ ? prodCheckAndUpdateNode : prodCheckNoChangesNode, view),
32216 };
32217}
32218function createDebugServices() {
32219 return {
32220 setCurrentNode: debugSetCurrentNode,
32221 createRootView: debugCreateRootView,
32222 createEmbeddedView: debugCreateEmbeddedView,
32223 createComponentView: debugCreateComponentView,
32224 createNgModuleRef: debugCreateNgModuleRef,
32225 overrideProvider: debugOverrideProvider,
32226 overrideComponentView: debugOverrideComponentView,
32227 clearOverrides: debugClearOverrides,
32228 checkAndUpdateView: debugCheckAndUpdateView,
32229 checkNoChangesView: debugCheckNoChangesView,
32230 destroyView: debugDestroyView,
32231 createDebugContext: (view, nodeIndex) => new DebugContext_(view, nodeIndex),
32232 handleEvent: debugHandleEvent,
32233 updateDirectives: debugUpdateDirectives,
32234 updateRenderer: debugUpdateRenderer,
32235 };
32236}
32237function createProdRootView(elInjector, projectableNodes, rootSelectorOrNode, def, ngModule, context) {
32238 const rendererFactory = ngModule.injector.get(RendererFactory2);
32239 return createRootView(createRootData(elInjector, ngModule, rendererFactory, projectableNodes, rootSelectorOrNode), def, context);
32240}
32241function debugCreateRootView(elInjector, projectableNodes, rootSelectorOrNode, def, ngModule, context) {
32242 const rendererFactory = ngModule.injector.get(RendererFactory2);
32243 const root = createRootData(elInjector, ngModule, new DebugRendererFactory2(rendererFactory), projectableNodes, rootSelectorOrNode);
32244 const defWithOverride = applyProviderOverridesToView(def);
32245 return callWithDebugContext(DebugAction.create, createRootView, null, [root, defWithOverride, context]);
32246}
32247function createRootData(elInjector, ngModule, rendererFactory, projectableNodes, rootSelectorOrNode) {
32248 const sanitizer = ngModule.injector.get(Sanitizer);
32249 const errorHandler = ngModule.injector.get(ErrorHandler);
32250 const renderer = rendererFactory.createRenderer(null, null);
32251 return {
32252 ngModule,
32253 injector: elInjector,
32254 projectableNodes,
32255 selectorOrNode: rootSelectorOrNode,
32256 sanitizer,
32257 rendererFactory,
32258 renderer,
32259 errorHandler
32260 };
32261}
32262function debugCreateEmbeddedView(parentView, anchorDef, viewDef, context) {
32263 const defWithOverride = applyProviderOverridesToView(viewDef);
32264 return callWithDebugContext(DebugAction.create, createEmbeddedView, null, [parentView, anchorDef, defWithOverride, context]);
32265}
32266function debugCreateComponentView(parentView, nodeDef, viewDef, hostElement) {
32267 const overrideComponentView = viewDefOverrides.get(nodeDef.element.componentProvider.provider.token);
32268 if (overrideComponentView) {
32269 viewDef = overrideComponentView;
32270 }
32271 else {
32272 viewDef = applyProviderOverridesToView(viewDef);
32273 }
32274 return callWithDebugContext(DebugAction.create, createComponentView, null, [parentView, nodeDef, viewDef, hostElement]);
32275}
32276function debugCreateNgModuleRef(moduleType, parentInjector, bootstrapComponents, def) {
32277 const defWithOverride = applyProviderOverridesToNgModule(def);
32278 return createNgModuleRef(moduleType, parentInjector, bootstrapComponents, defWithOverride);
32279}
32280const providerOverrides = new Map();
32281const providerOverridesWithScope = new Map();
32282const viewDefOverrides = new Map();
32283function debugOverrideProvider(override) {
32284 providerOverrides.set(override.token, override);
32285 let injectableDef;
32286 if (typeof override.token === 'function' && (injectableDef = getInjectableDef(override.token)) &&
32287 typeof injectableDef.providedIn === 'function') {
32288 providerOverridesWithScope.set(override.token, override);
32289 }
32290}
32291function debugOverrideComponentView(comp, compFactory) {
32292 const hostViewDef = resolveDefinition(getComponentViewDefinitionFactory(compFactory));
32293 const compViewDef = resolveDefinition(hostViewDef.nodes[0].element.componentView);
32294 viewDefOverrides.set(comp, compViewDef);
32295}
32296function debugClearOverrides() {
32297 providerOverrides.clear();
32298 providerOverridesWithScope.clear();
32299 viewDefOverrides.clear();
32300}
32301// Notes about the algorithm:
32302// 1) Locate the providers of an element and check if one of them was overwritten
32303// 2) Change the providers of that element
32304//
32305// We only create new data structures if we need to, to keep perf impact
32306// reasonable.
32307function applyProviderOverridesToView(def) {
32308 if (providerOverrides.size === 0) {
32309 return def;
32310 }
32311 const elementIndicesWithOverwrittenProviders = findElementIndicesWithOverwrittenProviders(def);
32312 if (elementIndicesWithOverwrittenProviders.length === 0) {
32313 return def;
32314 }
32315 // clone the whole view definition,
32316 // as it maintains references between the nodes that are hard to update.
32317 def = def.factory(() => NOOP);
32318 for (let i = 0; i < elementIndicesWithOverwrittenProviders.length; i++) {
32319 applyProviderOverridesToElement(def, elementIndicesWithOverwrittenProviders[i]);
32320 }
32321 return def;
32322 function findElementIndicesWithOverwrittenProviders(def) {
32323 const elIndicesWithOverwrittenProviders = [];
32324 let lastElementDef = null;
32325 for (let i = 0; i < def.nodes.length; i++) {
32326 const nodeDef = def.nodes[i];
32327 if (nodeDef.flags & 1 /* TypeElement */) {
32328 lastElementDef = nodeDef;
32329 }
32330 if (lastElementDef && nodeDef.flags & 3840 /* CatProviderNoDirective */ &&
32331 providerOverrides.has(nodeDef.provider.token)) {
32332 elIndicesWithOverwrittenProviders.push(lastElementDef.nodeIndex);
32333 lastElementDef = null;
32334 }
32335 }
32336 return elIndicesWithOverwrittenProviders;
32337 }
32338 function applyProviderOverridesToElement(viewDef, elIndex) {
32339 for (let i = elIndex + 1; i < viewDef.nodes.length; i++) {
32340 const nodeDef = viewDef.nodes[i];
32341 if (nodeDef.flags & 1 /* TypeElement */) {
32342 // stop at the next element
32343 return;
32344 }
32345 if (nodeDef.flags & 3840 /* CatProviderNoDirective */) {
32346 const provider = nodeDef.provider;
32347 const override = providerOverrides.get(provider.token);
32348 if (override) {
32349 nodeDef.flags = (nodeDef.flags & ~3840 /* CatProviderNoDirective */) | override.flags;
32350 provider.deps = splitDepsDsl(override.deps);
32351 provider.value = override.value;
32352 }
32353 }
32354 }
32355 }
32356}
32357// Notes about the algorithm:
32358// We only create new data structures if we need to, to keep perf impact
32359// reasonable.
32360function applyProviderOverridesToNgModule(def) {
32361 const { hasOverrides, hasDeprecatedOverrides } = calcHasOverrides(def);
32362 if (!hasOverrides) {
32363 return def;
32364 }
32365 // clone the whole view definition,
32366 // as it maintains references between the nodes that are hard to update.
32367 def = def.factory(() => NOOP);
32368 applyProviderOverrides(def);
32369 return def;
32370 function calcHasOverrides(def) {
32371 let hasOverrides = false;
32372 let hasDeprecatedOverrides = false;
32373 if (providerOverrides.size === 0) {
32374 return { hasOverrides, hasDeprecatedOverrides };
32375 }
32376 def.providers.forEach(node => {
32377 const override = providerOverrides.get(node.token);
32378 if ((node.flags & 3840 /* CatProviderNoDirective */) && override) {
32379 hasOverrides = true;
32380 hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
32381 }
32382 });
32383 def.modules.forEach(module => {
32384 providerOverridesWithScope.forEach((override, token) => {
32385 if (resolveForwardRef(getInjectableDef(token).providedIn) === module) {
32386 hasOverrides = true;
32387 hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
32388 }
32389 });
32390 });
32391 return { hasOverrides, hasDeprecatedOverrides };
32392 }
32393 function applyProviderOverrides(def) {
32394 for (let i = 0; i < def.providers.length; i++) {
32395 const provider = def.providers[i];
32396 if (hasDeprecatedOverrides) {
32397 // We had a bug where me made
32398 // all providers lazy. Keep this logic behind a flag
32399 // for migrating existing users.
32400 provider.flags |= 4096 /* LazyProvider */;
32401 }
32402 const override = providerOverrides.get(provider.token);
32403 if (override) {
32404 provider.flags = (provider.flags & ~3840 /* CatProviderNoDirective */) | override.flags;
32405 provider.deps = splitDepsDsl(override.deps);
32406 provider.value = override.value;
32407 }
32408 }
32409 if (providerOverridesWithScope.size > 0) {
32410 let moduleSet = new Set(def.modules);
32411 providerOverridesWithScope.forEach((override, token) => {
32412 if (moduleSet.has(resolveForwardRef(getInjectableDef(token).providedIn))) {
32413 let provider = {
32414 token: token,
32415 flags: override.flags | (hasDeprecatedOverrides ? 4096 /* LazyProvider */ : 0 /* None */),
32416 deps: splitDepsDsl(override.deps),
32417 value: override.value,
32418 index: def.providers.length,
32419 };
32420 def.providers.push(provider);
32421 def.providersByKey[tokenKey(token)] = provider;
32422 }
32423 });
32424 }
32425 }
32426}
32427function prodCheckAndUpdateNode(view, checkIndex, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
32428 const nodeDef = view.def.nodes[checkIndex];
32429 checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
32430 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32431 asPureExpressionData(view, checkIndex).value :
32432 undefined;
32433}
32434function prodCheckNoChangesNode(view, checkIndex, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
32435 const nodeDef = view.def.nodes[checkIndex];
32436 checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
32437 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32438 asPureExpressionData(view, checkIndex).value :
32439 undefined;
32440}
32441function debugCheckAndUpdateView(view) {
32442 return callWithDebugContext(DebugAction.detectChanges, checkAndUpdateView, null, [view]);
32443}
32444function debugCheckNoChangesView(view) {
32445 return callWithDebugContext(DebugAction.checkNoChanges, checkNoChangesView, null, [view]);
32446}
32447function debugDestroyView(view) {
32448 return callWithDebugContext(DebugAction.destroy, destroyView, null, [view]);
32449}
32450var DebugAction;
32451(function (DebugAction) {
32452 DebugAction[DebugAction["create"] = 0] = "create";
32453 DebugAction[DebugAction["detectChanges"] = 1] = "detectChanges";
32454 DebugAction[DebugAction["checkNoChanges"] = 2] = "checkNoChanges";
32455 DebugAction[DebugAction["destroy"] = 3] = "destroy";
32456 DebugAction[DebugAction["handleEvent"] = 4] = "handleEvent";
32457})(DebugAction || (DebugAction = {}));
32458let _currentAction;
32459let _currentView;
32460let _currentNodeIndex;
32461function debugSetCurrentNode(view, nodeIndex) {
32462 _currentView = view;
32463 _currentNodeIndex = nodeIndex;
32464}
32465function debugHandleEvent(view, nodeIndex, eventName, event) {
32466 debugSetCurrentNode(view, nodeIndex);
32467 return callWithDebugContext(DebugAction.handleEvent, view.def.handleEvent, null, [view, nodeIndex, eventName, event]);
32468}
32469function debugUpdateDirectives(view, checkType) {
32470 if (view.state & 128 /* Destroyed */) {
32471 throw viewDestroyedError(DebugAction[_currentAction]);
32472 }
32473 debugSetCurrentNode(view, nextDirectiveWithBinding(view, 0));
32474 return view.def.updateDirectives(debugCheckDirectivesFn, view);
32475 function debugCheckDirectivesFn(view, nodeIndex, argStyle, ...values) {
32476 const nodeDef = view.def.nodes[nodeIndex];
32477 if (checkType === 0 /* CheckAndUpdate */) {
32478 debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
32479 }
32480 else {
32481 debugCheckNoChangesNode(view, nodeDef, argStyle, values);
32482 }
32483 if (nodeDef.flags & 16384 /* TypeDirective */) {
32484 debugSetCurrentNode(view, nextDirectiveWithBinding(view, nodeIndex));
32485 }
32486 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32487 asPureExpressionData(view, nodeDef.nodeIndex).value :
32488 undefined;
32489 }
32490}
32491function debugUpdateRenderer(view, checkType) {
32492 if (view.state & 128 /* Destroyed */) {
32493 throw viewDestroyedError(DebugAction[_currentAction]);
32494 }
32495 debugSetCurrentNode(view, nextRenderNodeWithBinding(view, 0));
32496 return view.def.updateRenderer(debugCheckRenderNodeFn, view);
32497 function debugCheckRenderNodeFn(view, nodeIndex, argStyle, ...values) {
32498 const nodeDef = view.def.nodes[nodeIndex];
32499 if (checkType === 0 /* CheckAndUpdate */) {
32500 debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
32501 }
32502 else {
32503 debugCheckNoChangesNode(view, nodeDef, argStyle, values);
32504 }
32505 if (nodeDef.flags & 3 /* CatRenderNode */) {
32506 debugSetCurrentNode(view, nextRenderNodeWithBinding(view, nodeIndex));
32507 }
32508 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32509 asPureExpressionData(view, nodeDef.nodeIndex).value :
32510 undefined;
32511 }
32512}
32513function debugCheckAndUpdateNode(view, nodeDef, argStyle, givenValues) {
32514 const changed = checkAndUpdateNode(view, nodeDef, argStyle, ...givenValues);
32515 if (changed) {
32516 const values = argStyle === 1 /* Dynamic */ ? givenValues[0] : givenValues;
32517 if (nodeDef.flags & 16384 /* TypeDirective */) {
32518 const bindingValues = {};
32519 for (let i = 0; i < nodeDef.bindings.length; i++) {
32520 const binding = nodeDef.bindings[i];
32521 const value = values[i];
32522 if (binding.flags & 8 /* TypeProperty */) {
32523 bindingValues[normalizeDebugBindingName(binding.nonMinifiedName)] =
32524 normalizeDebugBindingValue(value);
32525 }
32526 }
32527 const elDef = nodeDef.parent;
32528 const el = asElementData(view, elDef.nodeIndex).renderElement;
32529 if (!elDef.element.name) {
32530 // a comment.
32531 view.renderer.setValue(el, escapeCommentText(`bindings=${JSON.stringify(bindingValues, null, 2)}`));
32532 }
32533 else {
32534 // a regular element.
32535 for (let attr in bindingValues) {
32536 const value = bindingValues[attr];
32537 if (value != null) {
32538 view.renderer.setAttribute(el, attr, value);
32539 }
32540 else {
32541 view.renderer.removeAttribute(el, attr);
32542 }
32543 }
32544 }
32545 }
32546 }
32547}
32548function debugCheckNoChangesNode(view, nodeDef, argStyle, values) {
32549 checkNoChangesNode(view, nodeDef, argStyle, ...values);
32550}
32551function nextDirectiveWithBinding(view, nodeIndex) {
32552 for (let i = nodeIndex; i < view.def.nodes.length; i++) {
32553 const nodeDef = view.def.nodes[i];
32554 if (nodeDef.flags & 16384 /* TypeDirective */ && nodeDef.bindings && nodeDef.bindings.length) {
32555 return i;
32556 }
32557 }
32558 return null;
32559}
32560function nextRenderNodeWithBinding(view, nodeIndex) {
32561 for (let i = nodeIndex; i < view.def.nodes.length; i++) {
32562 const nodeDef = view.def.nodes[i];
32563 if ((nodeDef.flags & 3 /* CatRenderNode */) && nodeDef.bindings && nodeDef.bindings.length) {
32564 return i;
32565 }
32566 }
32567 return null;
32568}
32569class DebugContext_ {
32570 constructor(view, nodeIndex) {
32571 this.view = view;
32572 this.nodeIndex = nodeIndex;
32573 if (nodeIndex == null) {
32574 this.nodeIndex = nodeIndex = 0;
32575 }
32576 this.nodeDef = view.def.nodes[nodeIndex];
32577 let elDef = this.nodeDef;
32578 let elView = view;
32579 while (elDef && (elDef.flags & 1 /* TypeElement */) === 0) {
32580 elDef = elDef.parent;
32581 }
32582 if (!elDef) {
32583 while (!elDef && elView) {
32584 elDef = viewParentEl(elView);
32585 elView = elView.parent;
32586 }
32587 }
32588 this.elDef = elDef;
32589 this.elView = elView;
32590 }
32591 get elOrCompView() {
32592 // Has to be done lazily as we use the DebugContext also during creation of elements...
32593 return asElementData(this.elView, this.elDef.nodeIndex).componentView || this.view;
32594 }
32595 get injector() {
32596 return createInjector(this.elView, this.elDef);
32597 }
32598 get component() {
32599 return this.elOrCompView.component;
32600 }
32601 get context() {
32602 return this.elOrCompView.context;
32603 }
32604 get providerTokens() {
32605 const tokens = [];
32606 if (this.elDef) {
32607 for (let i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount; i++) {
32608 const childDef = this.elView.def.nodes[i];
32609 if (childDef.flags & 20224 /* CatProvider */) {
32610 tokens.push(childDef.provider.token);
32611 }
32612 i += childDef.childCount;
32613 }
32614 }
32615 return tokens;
32616 }
32617 get references() {
32618 const references = {};
32619 if (this.elDef) {
32620 collectReferences(this.elView, this.elDef, references);
32621 for (let i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount; i++) {
32622 const childDef = this.elView.def.nodes[i];
32623 if (childDef.flags & 20224 /* CatProvider */) {
32624 collectReferences(this.elView, childDef, references);
32625 }
32626 i += childDef.childCount;
32627 }
32628 }
32629 return references;
32630 }
32631 get componentRenderElement() {
32632 const elData = findHostElement(this.elOrCompView);
32633 return elData ? elData.renderElement : undefined;
32634 }
32635 get renderNode() {
32636 return this.nodeDef.flags & 2 /* TypeText */ ? renderNode(this.view, this.nodeDef) :
32637 renderNode(this.elView, this.elDef);
32638 }
32639 logError(console, ...values) {
32640 let logViewDef;
32641 let logNodeIndex;
32642 if (this.nodeDef.flags & 2 /* TypeText */) {
32643 logViewDef = this.view.def;
32644 logNodeIndex = this.nodeDef.nodeIndex;
32645 }
32646 else {
32647 logViewDef = this.elView.def;
32648 logNodeIndex = this.elDef.nodeIndex;
32649 }
32650 // Note: we only generate a log function for text and element nodes
32651 // to make the generated code as small as possible.
32652 const renderNodeIndex = getRenderNodeIndex(logViewDef, logNodeIndex);
32653 let currRenderNodeIndex = -1;
32654 let nodeLogger = () => {
32655 currRenderNodeIndex++;
32656 if (currRenderNodeIndex === renderNodeIndex) {
32657 return console.error.bind(console, ...values);
32658 }
32659 else {
32660 return NOOP;
32661 }
32662 };
32663 logViewDef.factory(nodeLogger);
32664 if (currRenderNodeIndex < renderNodeIndex) {
32665 console.error('Illegal state: the ViewDefinitionFactory did not call the logger!');
32666 console.error(...values);
32667 }
32668 }
32669}
32670function getRenderNodeIndex(viewDef, nodeIndex) {
32671 let renderNodeIndex = -1;
32672 for (let i = 0; i <= nodeIndex; i++) {
32673 const nodeDef = viewDef.nodes[i];
32674 if (nodeDef.flags & 3 /* CatRenderNode */) {
32675 renderNodeIndex++;
32676 }
32677 }
32678 return renderNodeIndex;
32679}
32680function findHostElement(view) {
32681 while (view && !isComponentView(view)) {
32682 view = view.parent;
32683 }
32684 if (view.parent) {
32685 return asElementData(view.parent, viewParentEl(view).nodeIndex);
32686 }
32687 return null;
32688}
32689function collectReferences(view, nodeDef, references) {
32690 for (let refName in nodeDef.references) {
32691 references[refName] = getQueryValue(view, nodeDef, nodeDef.references[refName]);
32692 }
32693}
32694function callWithDebugContext(action, fn, self, args) {
32695 const oldAction = _currentAction;
32696 const oldView = _currentView;
32697 const oldNodeIndex = _currentNodeIndex;
32698 try {
32699 _currentAction = action;
32700 const result = fn.apply(self, args);
32701 _currentView = oldView;
32702 _currentNodeIndex = oldNodeIndex;
32703 _currentAction = oldAction;
32704 return result;
32705 }
32706 catch (e) {
32707 if (isViewDebugError(e) || !_currentView) {
32708 throw e;
32709 }
32710 throw viewWrappedDebugError(e, getCurrentDebugContext());
32711 }
32712}
32713function getCurrentDebugContext() {
32714 return _currentView ? new DebugContext_(_currentView, _currentNodeIndex) : null;
32715}
32716class DebugRendererFactory2 {
32717 constructor(delegate) {
32718 this.delegate = delegate;
32719 }
32720 createRenderer(element, renderData) {
32721 return new DebugRenderer2(this.delegate.createRenderer(element, renderData));
32722 }
32723 begin() {
32724 if (this.delegate.begin) {
32725 this.delegate.begin();
32726 }
32727 }
32728 end() {
32729 if (this.delegate.end) {
32730 this.delegate.end();
32731 }
32732 }
32733 whenRenderingDone() {
32734 if (this.delegate.whenRenderingDone) {
32735 return this.delegate.whenRenderingDone();
32736 }
32737 return Promise.resolve(null);
32738 }
32739}
32740class DebugRenderer2 {
32741 constructor(delegate) {
32742 this.delegate = delegate;
32743 /**
32744 * Factory function used to create a `DebugContext` when a node is created.
32745 *
32746 * The `DebugContext` allows to retrieve information about the nodes that are useful in tests.
32747 *
32748 * The factory is configurable so that the `DebugRenderer2` could instantiate either a View Engine
32749 * or a Render context.
32750 */
32751 this.debugContextFactory = getCurrentDebugContext;
32752 this.data = this.delegate.data;
32753 }
32754 createDebugContext(nativeElement) {
32755 return this.debugContextFactory(nativeElement);
32756 }
32757 destroyNode(node) {
32758 const debugNode = getDebugNode(node);
32759 if (debugNode) {
32760 removeDebugNodeFromIndex(debugNode);
32761 if (debugNode instanceof DebugNode__PRE_R3__) {
32762 debugNode.listeners.length = 0;
32763 }
32764 }
32765 if (this.delegate.destroyNode) {
32766 this.delegate.destroyNode(node);
32767 }
32768 }
32769 destroy() {
32770 this.delegate.destroy();
32771 }
32772 createElement(name, namespace) {
32773 const el = this.delegate.createElement(name, namespace);
32774 const debugCtx = this.createDebugContext(el);
32775 if (debugCtx) {
32776 const debugEl = new DebugElement__PRE_R3__(el, null, debugCtx);
32777 debugEl.name = name;
32778 indexDebugNode(debugEl);
32779 }
32780 return el;
32781 }
32782 createComment(value) {
32783 const comment = this.delegate.createComment(escapeCommentText(value));
32784 const debugCtx = this.createDebugContext(comment);
32785 if (debugCtx) {
32786 indexDebugNode(new DebugNode__PRE_R3__(comment, null, debugCtx));
32787 }
32788 return comment;
32789 }
32790 createText(value) {
32791 const text = this.delegate.createText(value);
32792 const debugCtx = this.createDebugContext(text);
32793 if (debugCtx) {
32794 indexDebugNode(new DebugNode__PRE_R3__(text, null, debugCtx));
32795 }
32796 return text;
32797 }
32798 appendChild(parent, newChild) {
32799 const debugEl = getDebugNode(parent);
32800 const debugChildEl = getDebugNode(newChild);
32801 if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
32802 debugEl.addChild(debugChildEl);
32803 }
32804 this.delegate.appendChild(parent, newChild);
32805 }
32806 insertBefore(parent, newChild, refChild, isMove) {
32807 const debugEl = getDebugNode(parent);
32808 const debugChildEl = getDebugNode(newChild);
32809 const debugRefEl = getDebugNode(refChild);
32810 if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
32811 debugEl.insertBefore(debugRefEl, debugChildEl);
32812 }
32813 this.delegate.insertBefore(parent, newChild, refChild, isMove);
32814 }
32815 removeChild(parent, oldChild) {
32816 const debugEl = getDebugNode(parent);
32817 const debugChildEl = getDebugNode(oldChild);
32818 if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
32819 debugEl.removeChild(debugChildEl);
32820 }
32821 this.delegate.removeChild(parent, oldChild);
32822 }
32823 selectRootElement(selectorOrNode, preserveContent) {
32824 const el = this.delegate.selectRootElement(selectorOrNode, preserveContent);
32825 const debugCtx = getCurrentDebugContext();
32826 if (debugCtx) {
32827 indexDebugNode(new DebugElement__PRE_R3__(el, null, debugCtx));
32828 }
32829 return el;
32830 }
32831 setAttribute(el, name, value, namespace) {
32832 const debugEl = getDebugNode(el);
32833 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32834 const fullName = namespace ? namespace + ':' + name : name;
32835 debugEl.attributes[fullName] = value;
32836 }
32837 this.delegate.setAttribute(el, name, value, namespace);
32838 }
32839 removeAttribute(el, name, namespace) {
32840 const debugEl = getDebugNode(el);
32841 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32842 const fullName = namespace ? namespace + ':' + name : name;
32843 debugEl.attributes[fullName] = null;
32844 }
32845 this.delegate.removeAttribute(el, name, namespace);
32846 }
32847 addClass(el, name) {
32848 const debugEl = getDebugNode(el);
32849 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32850 debugEl.classes[name] = true;
32851 }
32852 this.delegate.addClass(el, name);
32853 }
32854 removeClass(el, name) {
32855 const debugEl = getDebugNode(el);
32856 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32857 debugEl.classes[name] = false;
32858 }
32859 this.delegate.removeClass(el, name);
32860 }
32861 setStyle(el, style, value, flags) {
32862 const debugEl = getDebugNode(el);
32863 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32864 debugEl.styles[style] = value;
32865 }
32866 this.delegate.setStyle(el, style, value, flags);
32867 }
32868 removeStyle(el, style, flags) {
32869 const debugEl = getDebugNode(el);
32870 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32871 debugEl.styles[style] = null;
32872 }
32873 this.delegate.removeStyle(el, style, flags);
32874 }
32875 setProperty(el, name, value) {
32876 const debugEl = getDebugNode(el);
32877 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32878 debugEl.properties[name] = value;
32879 }
32880 this.delegate.setProperty(el, name, value);
32881 }
32882 listen(target, eventName, callback) {
32883 if (typeof target !== 'string') {
32884 const debugEl = getDebugNode(target);
32885 if (debugEl) {
32886 debugEl.listeners.push(new DebugEventListener(eventName, callback));
32887 }
32888 }
32889 return this.delegate.listen(target, eventName, callback);
32890 }
32891 parentNode(node) {
32892 return this.delegate.parentNode(node);
32893 }
32894 nextSibling(node) {
32895 return this.delegate.nextSibling(node);
32896 }
32897 setValue(node, value) {
32898 return this.delegate.setValue(node, value);
32899 }
32900}
32901
32902/**
32903 * @license
32904 * Copyright Google LLC All Rights Reserved.
32905 *
32906 * Use of this source code is governed by an MIT-style license that can be
32907 * found in the LICENSE file at https://angular.io/license
32908 */
32909function overrideProvider(override) {
32910 initServicesIfNeeded();
32911 return Services.overrideProvider(override);
32912}
32913function overrideComponentView(comp, componentFactory) {
32914 initServicesIfNeeded();
32915 return Services.overrideComponentView(comp, componentFactory);
32916}
32917function clearOverrides() {
32918 initServicesIfNeeded();
32919 return Services.clearOverrides();
32920}
32921// Attention: this function is called as top level function.
32922// Putting any logic in here will destroy closure tree shaking!
32923function createNgModuleFactory(ngModuleType, bootstrapComponents, defFactory) {
32924 return new NgModuleFactory_(ngModuleType, bootstrapComponents, defFactory);
32925}
32926function cloneNgModuleDefinition(def) {
32927 const providers = Array.from(def.providers);
32928 const modules = Array.from(def.modules);
32929 const providersByKey = {};
32930 for (const key in def.providersByKey) {
32931 providersByKey[key] = def.providersByKey[key];
32932 }
32933 return {
32934 factory: def.factory,
32935 scope: def.scope,
32936 providers,
32937 modules,
32938 providersByKey,
32939 };
32940}
32941class NgModuleFactory_ extends NgModuleFactory$1 {
32942 constructor(moduleType, _bootstrapComponents, _ngModuleDefFactory) {
32943 // Attention: this ctor is called as top level function.
32944 // Putting any logic in here will destroy closure tree shaking!
32945 super();
32946 this.moduleType = moduleType;
32947 this._bootstrapComponents = _bootstrapComponents;
32948 this._ngModuleDefFactory = _ngModuleDefFactory;
32949 }
32950 create(parentInjector) {
32951 initServicesIfNeeded();
32952 // Clone the NgModuleDefinition so that any tree shakeable provider definition
32953 // added to this instance of the NgModuleRef doesn't affect the cached copy.
32954 // See https://github.com/angular/angular/issues/25018.
32955 const def = cloneNgModuleDefinition(resolveDefinition(this._ngModuleDefFactory));
32956 return Services.createNgModuleRef(this.moduleType, parentInjector || Injector.NULL, this._bootstrapComponents, def);
32957 }
32958}
32959
32960/**
32961 * @license
32962 * Copyright Google LLC All Rights Reserved.
32963 *
32964 * Use of this source code is governed by an MIT-style license that can be
32965 * found in the LICENSE file at https://angular.io/license
32966 */
32967
32968/**
32969 * @license
32970 * Copyright Google LLC All Rights Reserved.
32971 *
32972 * Use of this source code is governed by an MIT-style license that can be
32973 * found in the LICENSE file at https://angular.io/license
32974 */
32975
32976/**
32977 * @license
32978 * Copyright Google LLC All Rights Reserved.
32979 *
32980 * Use of this source code is governed by an MIT-style license that can be
32981 * found in the LICENSE file at https://angular.io/license
32982 */
32983/**
32984 * Compiles a partial directive declaration object into a full directive definition object.
32985 *
32986 * @codeGenApi
32987 */
32988function ɵɵngDeclareDirective(decl) {
32989 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'directive', type: decl.type });
32990 return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
32991}
32992/**
32993 * Evaluates the class metadata declaration.
32994 *
32995 * @codeGenApi
32996 */
32997function ɵɵngDeclareClassMetadata(decl) {
32998 setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null);
32999}
33000/**
33001 * Compiles a partial component declaration object into a full component definition object.
33002 *
33003 * @codeGenApi
33004 */
33005function ɵɵngDeclareComponent(decl) {
33006 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'component', type: decl.type });
33007 return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
33008}
33009/**
33010 * Compiles a partial pipe declaration object into a full pipe definition object.
33011 *
33012 * @codeGenApi
33013 */
33014function ɵɵngDeclareFactory(decl) {
33015 const compiler = getCompilerFacade({
33016 usage: 1 /* PartialDeclaration */,
33017 kind: getFactoryKind(decl.target),
33018 type: decl.type
33019 });
33020 return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
33021}
33022function getFactoryKind(target) {
33023 switch (target) {
33024 case FactoryTarget.Directive:
33025 return 'directive';
33026 case FactoryTarget.Component:
33027 return 'component';
33028 case FactoryTarget.Injectable:
33029 return 'injectable';
33030 case FactoryTarget.Pipe:
33031 return 'pipe';
33032 case FactoryTarget.NgModule:
33033 return 'NgModule';
33034 }
33035}
33036/**
33037 * Compiles a partial injectable declaration object into a full injectable definition object.
33038 *
33039 * @codeGenApi
33040 */
33041function ɵɵngDeclareInjectable(decl) {
33042 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'injectable', type: decl.type });
33043 return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
33044}
33045/**
33046 * Compiles a partial injector declaration object into a full injector definition object.
33047 *
33048 * @codeGenApi
33049 */
33050function ɵɵngDeclareInjector(decl) {
33051 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'NgModule', type: decl.type });
33052 return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
33053}
33054/**
33055 * Compiles a partial NgModule declaration object into a full NgModule definition object.
33056 *
33057 * @codeGenApi
33058 */
33059function ɵɵngDeclareNgModule(decl) {
33060 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'NgModule', type: decl.type });
33061 return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
33062}
33063/**
33064 * Compiles a partial pipe declaration object into a full pipe definition object.
33065 *
33066 * @codeGenApi
33067 */
33068function ɵɵngDeclarePipe(decl) {
33069 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'pipe', type: decl.type });
33070 return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
33071}
33072
33073/**
33074 * @license
33075 * Copyright Google LLC All Rights Reserved.
33076 *
33077 * Use of this source code is governed by an MIT-style license that can be
33078 * found in the LICENSE file at https://angular.io/license
33079 */
33080// clang-format on
33081
33082/**
33083 * @license
33084 * Copyright Google LLC All Rights Reserved.
33085 *
33086 * Use of this source code is governed by an MIT-style license that can be
33087 * found in the LICENSE file at https://angular.io/license
33088 */
33089
33090/**
33091 * @license
33092 * Copyright Google LLC All Rights Reserved.
33093 *
33094 * Use of this source code is governed by an MIT-style license that can be
33095 * found in the LICENSE file at https://angular.io/license
33096 */
33097if (typeof ngDevMode !== 'undefined' && ngDevMode) {
33098 // This helper is to give a reasonable error message to people upgrading to v9 that have not yet
33099 // installed `@angular/localize` in their app.
33100 // tslint:disable-next-line: no-toplevel-property-access
33101 _global.$localize = _global.$localize || function () {
33102 throw new Error('It looks like your application or one of its dependencies is using i18n.\n' +
33103 'Angular 9 introduced a global `$localize()` function that needs to be loaded.\n' +
33104 'Please run `ng add @angular/localize` from the Angular CLI.\n' +
33105 '(For non-CLI projects, add `import \'@angular/localize/init\';` to your `polyfills.ts` file.\n' +
33106 'For server-side rendering applications add the import to your `main.server.ts` file.)');
33107 };
33108}
33109
33110/**
33111 * @license
33112 * Copyright Google LLC All Rights Reserved.
33113 *
33114 * Use of this source code is governed by an MIT-style license that can be
33115 * found in the LICENSE file at https://angular.io/license
33116 */
33117// This file only reexports content of the `src` folder. Keep it that way.
33118
33119/**
33120 * @license
33121 * Copyright Google LLC All Rights Reserved.
33122 *
33123 * Use of this source code is governed by an MIT-style license that can be
33124 * found in the LICENSE file at https://angular.io/license
33125 */
33126
33127/**
33128 * Generated bundle index. Do not edit.
33129 */
33130
33131export { ANALYZE_FOR_ENTRY_COMPONENTS, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, Directive, ElementRef, EmbeddedViewRef, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, createNgModuleRef$1 as createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, inject, isDevMode, platformCore, resolveForwardRef, setTestabilityGetter, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, APP_ID_RANDOM_PROVIDER as ɵAPP_ID_RANDOM_PROVIDER, CREATE_ATTRIBUTE_DECORATOR__POST_R3__ as ɵCREATE_ATTRIBUTE_DECORATOR__POST_R3__, ChangeDetectorStatus as ɵChangeDetectorStatus, CodegenComponentFactoryResolver as ɵCodegenComponentFactoryResolver, Compiler_compileModuleAndAllComponentsAsync__POST_R3__ as ɵCompiler_compileModuleAndAllComponentsAsync__POST_R3__, Compiler_compileModuleAndAllComponentsSync__POST_R3__ as ɵCompiler_compileModuleAndAllComponentsSync__POST_R3__, Compiler_compileModuleAsync__POST_R3__ as ɵCompiler_compileModuleAsync__POST_R3__, Compiler_compileModuleSync__POST_R3__ as ɵCompiler_compileModuleSync__POST_R3__, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, EMPTY_ARRAY as ɵEMPTY_ARRAY, EMPTY_MAP as ɵEMPTY_MAP, INJECTOR_IMPL__POST_R3__ as ɵINJECTOR_IMPL__POST_R3__, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ as ɵSWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__, SWITCH_COMPILE_COMPONENT__POST_R3__ as ɵSWITCH_COMPILE_COMPONENT__POST_R3__, SWITCH_COMPILE_DIRECTIVE__POST_R3__ as ɵSWITCH_COMPILE_DIRECTIVE__POST_R3__, SWITCH_COMPILE_INJECTABLE__POST_R3__ as ɵSWITCH_COMPILE_INJECTABLE__POST_R3__, SWITCH_COMPILE_NGMODULE__POST_R3__ as ɵSWITCH_COMPILE_NGMODULE__POST_R3__, SWITCH_COMPILE_PIPE__POST_R3__ as ɵSWITCH_COMPILE_PIPE__POST_R3__, SWITCH_ELEMENT_REF_FACTORY__POST_R3__ as ɵSWITCH_ELEMENT_REF_FACTORY__POST_R3__, SWITCH_IVY_ENABLED__POST_R3__ as ɵSWITCH_IVY_ENABLED__POST_R3__, SWITCH_RENDERER2_FACTORY__POST_R3__ as ɵSWITCH_RENDERER2_FACTORY__POST_R3__, SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ as ɵSWITCH_TEMPLATE_REF_FACTORY__POST_R3__, SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__ as ɵSWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__, ViewRef$1 as ɵViewRef, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, anchorDef as ɵand, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, createComponentFactory as ɵccf, clearOverrides as ɵclearOverrides, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, createNgModuleFactory as ɵcmf, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory__POST_R3__ as ɵcompileNgModuleFactory__POST_R3__, compilePipe as ɵcompilePipe, createInjector$1 as ɵcreateInjector, createRendererType2 as ɵcrt, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, directiveDef as ɵdid, elementDef as ɵeld, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, getComponentViewDefinitionFactory as ɵgetComponentViewDefinitionFactory, getDebugNodeR2 as ɵgetDebugNodeR2, getDebugNode__POST_R3__ as ɵgetDebugNode__POST_R3__, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getModuleFactory__POST_R3__ as ɵgetModuleFactory__POST_R3__, getNgModuleById__POST_R3__ as ɵgetNgModuleById__POST_R3__, getSanitizationBypassType as ɵgetSanitizationBypassType, _global as ɵglobal, initServicesIfNeeded as ɵinitServicesIfNeeded, inlineInterpolate as ɵinlineInterpolate, interpolate as ɵinterpolate, isBoundToModule__POST_R3__ as ɵisBoundToModule__POST_R3__, isDefaultChangeDetectionStrategy as ɵisDefaultChangeDetectionStrategy, isListLikeIterable as ɵisListLikeIterable, isObservable as ɵisObservable, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, ivyEnabled as ɵivyEnabled, makeDecorator as ɵmakeDecorator, markDirty as ɵmarkDirty, moduleDef as ɵmod, moduleProvideDef as ɵmpd, ngContentDef as ɵncd, noSideEffects as ɵnoSideEffects, nodeValue as ɵnov, overrideComponentView as ɵoverrideComponentView, overrideProvider as ɵoverrideProvider, pureArrayDef as ɵpad, patchComponentDefWithScope as ɵpatchComponentDefWithScope, pipeDef as ɵpid, pureObjectDef as ɵpod, purePipeDef as ɵppd, providerDef as ɵprd, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, queryDef as ɵqud, registerLocaleData as ɵregisterLocaleData, registerModuleFactory as ɵregisterModuleFactory, registerNgModuleType as ɵregisterNgModuleType, renderComponent as ɵrenderComponent, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, setClassMetadata as ɵsetClassMetadata, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setLocaleId as ɵsetLocaleId, store as ɵstore, stringify as ɵstringify, textDef as ɵted, transitiveScopesFor as ɵtransitiveScopesFor, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, viewDef as ɵvid, whenRendered as ɵwhenRendered, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵviewQuery };
33132//# sourceMappingURL=core.mjs.map