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 * Special location which allows easy identification of type. If we have an array which was
1137 * retrieved from the `LView` and that array has `true` at `TYPE` location, we know it is
1138 * `LContainer`.
1139 */
1140const TYPE = 1;
1141/**
1142 * Below are constants for LContainer indices to help us look up LContainer members
1143 * without having to remember the specific indices.
1144 * Uglify will inline these when minifying so there shouldn't be a cost.
1145 */
1146/**
1147 * Flag to signify that this `LContainer` may have transplanted views which need to be change
1148 * detected. (see: `LView[DECLARATION_COMPONENT_VIEW])`.
1149 *
1150 * This flag, once set, is never unset for the `LContainer`. This means that when unset we can skip
1151 * a lot of work in `refreshEmbeddedViews`. But when set we still need to verify
1152 * that the `MOVED_VIEWS` are transplanted and on-push.
1153 */
1154const HAS_TRANSPLANTED_VIEWS = 2;
1155// PARENT, NEXT, TRANSPLANTED_VIEWS_TO_REFRESH are indices 3, 4, and 5
1156// As we already have these constants in LView, we don't need to re-create them.
1157// T_HOST is index 6
1158// We already have this constants in LView, we don't need to re-create it.
1159const NATIVE = 7;
1160const VIEW_REFS = 8;
1161const MOVED_VIEWS = 9;
1162/**
1163 * Size of LContainer's header. Represents the index after which all views in the
1164 * container will be inserted. We need to keep a record of current views so we know
1165 * which views are already in the DOM (and don't need to be re-added) and so we can
1166 * remove views from the DOM when they are no longer required.
1167 */
1168const CONTAINER_HEADER_OFFSET = 10;
1169// Note: This hack is necessary so we don't erroneously get a circular dependency
1170// failure based on types.
1171const unusedValueExportToPlacateAjd$8 = 1;
1172
1173/**
1174 * @license
1175 * Copyright Google LLC All Rights Reserved.
1176 *
1177 * Use of this source code is governed by an MIT-style license that can be
1178 * found in the LICENSE file at https://angular.io/license
1179 */
1180// Below are constants for LView indices to help us look up LView members
1181// without having to remember the specific indices.
1182// Uglify will inline these when minifying so there shouldn't be a cost.
1183const HOST = 0;
1184const TVIEW = 1;
1185const FLAGS = 2;
1186const PARENT = 3;
1187const NEXT = 4;
1188const TRANSPLANTED_VIEWS_TO_REFRESH = 5;
1189const T_HOST = 6;
1190const CLEANUP = 7;
1191const CONTEXT = 8;
1192const INJECTOR$1 = 9;
1193const RENDERER_FACTORY = 10;
1194const RENDERER = 11;
1195const SANITIZER = 12;
1196const CHILD_HEAD = 13;
1197const CHILD_TAIL = 14;
1198// FIXME(misko): Investigate if the three declarations aren't all same thing.
1199const DECLARATION_VIEW = 15;
1200const DECLARATION_COMPONENT_VIEW = 16;
1201const DECLARATION_LCONTAINER = 17;
1202const PREORDER_HOOK_FLAGS = 18;
1203const QUERIES = 19;
1204/**
1205 * Size of LView's header. Necessary to adjust for it when setting slots.
1206 *
1207 * IMPORTANT: `HEADER_OFFSET` should only be referred to the in the `ɵɵ*` instructions to translate
1208 * instruction index into `LView` index. All other indexes should be in the `LView` index space and
1209 * there should be no need to refer to `HEADER_OFFSET` anywhere else.
1210 */
1211const HEADER_OFFSET = 20;
1212/**
1213 * Converts `TViewType` into human readable text.
1214 * Make sure this matches with `TViewType`
1215 */
1216const TViewTypeAsString = [
1217 'Root',
1218 'Component',
1219 'Embedded', // 2
1220];
1221// Note: This hack is necessary so we don't erroneously get a circular dependency
1222// failure based on types.
1223const unusedValueExportToPlacateAjd$7 = 1;
1224
1225/**
1226 * @license
1227 * Copyright Google LLC All Rights Reserved.
1228 *
1229 * Use of this source code is governed by an MIT-style license that can be
1230 * found in the LICENSE file at https://angular.io/license
1231 */
1232/**
1233 * True if `value` is `LView`.
1234 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1235 */
1236function isLView(value) {
1237 return Array.isArray(value) && typeof value[TYPE] === 'object';
1238}
1239/**
1240 * True if `value` is `LContainer`.
1241 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1242 */
1243function isLContainer(value) {
1244 return Array.isArray(value) && value[TYPE] === true;
1245}
1246function isContentQueryHost(tNode) {
1247 return (tNode.flags & 8 /* hasContentQuery */) !== 0;
1248}
1249function isComponentHost(tNode) {
1250 return (tNode.flags & 2 /* isComponentHost */) === 2 /* isComponentHost */;
1251}
1252function isDirectiveHost(tNode) {
1253 return (tNode.flags & 1 /* isDirectiveHost */) === 1 /* isDirectiveHost */;
1254}
1255function isComponentDef(def) {
1256 return def.template !== null;
1257}
1258function isRootView(target) {
1259 return (target[FLAGS] & 512 /* IsRoot */) !== 0;
1260}
1261
1262/**
1263 * @license
1264 * Copyright Google LLC All Rights Reserved.
1265 *
1266 * Use of this source code is governed by an MIT-style license that can be
1267 * found in the LICENSE file at https://angular.io/license
1268 */
1269// [Assert functions do not constraint type when they are guarded by a truthy
1270// expression.](https://github.com/microsoft/TypeScript/issues/37295)
1271function assertTNodeForLView(tNode, lView) {
1272 assertTNodeForTView(tNode, lView[TVIEW]);
1273}
1274function assertTNodeForTView(tNode, tView) {
1275 assertTNode(tNode);
1276 tNode.hasOwnProperty('tView_') &&
1277 assertEqual(tNode.tView_, tView, 'This TNode does not belong to this TView.');
1278}
1279function assertTNode(tNode) {
1280 assertDefined(tNode, 'TNode must be defined');
1281 if (!(tNode && typeof tNode === 'object' && tNode.hasOwnProperty('directiveStylingLast'))) {
1282 throwError('Not of type TNode, got: ' + tNode);
1283 }
1284}
1285function assertTIcu(tIcu) {
1286 assertDefined(tIcu, 'Expected TIcu to be defined');
1287 if (!(typeof tIcu.currentCaseLViewIndex === 'number')) {
1288 throwError('Object is not of TIcu type.');
1289 }
1290}
1291function assertComponentType(actual, msg = 'Type passed in is not ComponentType, it does not have \'ɵcmp\' property.') {
1292 if (!getComponentDef(actual)) {
1293 throwError(msg);
1294 }
1295}
1296function assertNgModuleType(actual, msg = 'Type passed in is not NgModuleType, it does not have \'ɵmod\' property.') {
1297 if (!getNgModuleDef(actual)) {
1298 throwError(msg);
1299 }
1300}
1301function assertCurrentTNodeIsParent(isParent) {
1302 assertEqual(isParent, true, 'currentTNode should be a parent');
1303}
1304function assertHasParent(tNode) {
1305 assertDefined(tNode, 'currentTNode should exist!');
1306 assertDefined(tNode.parent, 'currentTNode should have a parent');
1307}
1308function assertDataNext(lView, index, arr) {
1309 if (arr == null)
1310 arr = lView;
1311 assertEqual(arr.length, index, `index ${index} expected to be at the end of arr (length ${arr.length})`);
1312}
1313function assertLContainer(value) {
1314 assertDefined(value, 'LContainer must be defined');
1315 assertEqual(isLContainer(value), true, 'Expecting LContainer');
1316}
1317function assertLViewOrUndefined(value) {
1318 value && assertEqual(isLView(value), true, 'Expecting LView or undefined or null');
1319}
1320function assertLView(value) {
1321 assertDefined(value, 'LView must be defined');
1322 assertEqual(isLView(value), true, 'Expecting LView');
1323}
1324function assertFirstCreatePass(tView, errMessage) {
1325 assertEqual(tView.firstCreatePass, true, errMessage || 'Should only be called in first create pass.');
1326}
1327function assertFirstUpdatePass(tView, errMessage) {
1328 assertEqual(tView.firstUpdatePass, true, errMessage || 'Should only be called in first update pass.');
1329}
1330/**
1331 * This is a basic sanity check that an object is probably a directive def. DirectiveDef is
1332 * an interface, so we can't do a direct instanceof check.
1333 */
1334function assertDirectiveDef(obj) {
1335 if (obj.type === undefined || obj.selectors == undefined || obj.inputs === undefined) {
1336 throwError(`Expected a DirectiveDef/ComponentDef and this object does not seem to have the expected shape.`);
1337 }
1338}
1339function assertIndexInDeclRange(lView, index) {
1340 const tView = lView[1];
1341 assertBetween(HEADER_OFFSET, tView.bindingStartIndex, index);
1342}
1343function assertIndexInVarsRange(lView, index) {
1344 const tView = lView[1];
1345 assertBetween(tView.bindingStartIndex, tView.expandoStartIndex, index);
1346}
1347function assertIndexInExpandoRange(lView, index) {
1348 const tView = lView[1];
1349 assertBetween(tView.expandoStartIndex, lView.length, index);
1350}
1351function assertBetween(lower, upper, index) {
1352 if (!(lower <= index && index < upper)) {
1353 throwError(`Index out of range (expecting ${lower} <= ${index} < ${upper})`);
1354 }
1355}
1356function assertProjectionSlots(lView, errMessage) {
1357 assertDefined(lView[DECLARATION_COMPONENT_VIEW], 'Component views should exist.');
1358 assertDefined(lView[DECLARATION_COMPONENT_VIEW][T_HOST].projection, errMessage ||
1359 'Components with projection nodes (<ng-content>) must have projection slots defined.');
1360}
1361function assertParentView(lView, errMessage) {
1362 assertDefined(lView, errMessage || 'Component views should always have a parent view (component\'s host view)');
1363}
1364/**
1365 * This is a basic sanity check that the `injectorIndex` seems to point to what looks like a
1366 * NodeInjector data structure.
1367 *
1368 * @param lView `LView` which should be checked.
1369 * @param injectorIndex index into the `LView` where the `NodeInjector` is expected.
1370 */
1371function assertNodeInjector(lView, injectorIndex) {
1372 assertIndexInExpandoRange(lView, injectorIndex);
1373 assertIndexInExpandoRange(lView, injectorIndex + 8 /* PARENT */);
1374 assertNumber(lView[injectorIndex + 0], 'injectorIndex should point to a bloom filter');
1375 assertNumber(lView[injectorIndex + 1], 'injectorIndex should point to a bloom filter');
1376 assertNumber(lView[injectorIndex + 2], 'injectorIndex should point to a bloom filter');
1377 assertNumber(lView[injectorIndex + 3], 'injectorIndex should point to a bloom filter');
1378 assertNumber(lView[injectorIndex + 4], 'injectorIndex should point to a bloom filter');
1379 assertNumber(lView[injectorIndex + 5], 'injectorIndex should point to a bloom filter');
1380 assertNumber(lView[injectorIndex + 6], 'injectorIndex should point to a bloom filter');
1381 assertNumber(lView[injectorIndex + 7], 'injectorIndex should point to a bloom filter');
1382 assertNumber(lView[injectorIndex + 8 /* PARENT */], 'injectorIndex should point to parent injector');
1383}
1384
1385/**
1386 * @license
1387 * Copyright Google LLC All Rights Reserved.
1388 *
1389 * Use of this source code is governed by an MIT-style license that can be
1390 * found in the LICENSE file at https://angular.io/license
1391 */
1392function getFactoryDef(type, throwNotFound) {
1393 const hasFactoryDef = type.hasOwnProperty(NG_FACTORY_DEF);
1394 if (!hasFactoryDef && throwNotFound === true && ngDevMode) {
1395 throw new Error(`Type ${stringify(type)} does not have 'ɵfac' property.`);
1396 }
1397 return hasFactoryDef ? type[NG_FACTORY_DEF] : null;
1398}
1399
1400/**
1401 * @license
1402 * Copyright Google LLC All Rights Reserved.
1403 *
1404 * Use of this source code is governed by an MIT-style license that can be
1405 * found in the LICENSE file at https://angular.io/license
1406 */
1407/**
1408 * Represents a basic change from a previous to a new value for a single
1409 * property on a directive instance. Passed as a value in a
1410 * {@link SimpleChanges} object to the `ngOnChanges` hook.
1411 *
1412 * @see `OnChanges`
1413 *
1414 * @publicApi
1415 */
1416class SimpleChange {
1417 constructor(previousValue, currentValue, firstChange) {
1418 this.previousValue = previousValue;
1419 this.currentValue = currentValue;
1420 this.firstChange = firstChange;
1421 }
1422 /**
1423 * Check whether the new value is the first value assigned.
1424 */
1425 isFirstChange() {
1426 return this.firstChange;
1427 }
1428}
1429
1430/**
1431 * @license
1432 * Copyright Google LLC All Rights Reserved.
1433 *
1434 * Use of this source code is governed by an MIT-style license that can be
1435 * found in the LICENSE file at https://angular.io/license
1436 */
1437/**
1438 * The NgOnChangesFeature decorates a component with support for the ngOnChanges
1439 * lifecycle hook, so it should be included in any component that implements
1440 * that hook.
1441 *
1442 * If the component or directive uses inheritance, the NgOnChangesFeature MUST
1443 * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
1444 * inherited properties will not be propagated to the ngOnChanges lifecycle
1445 * hook.
1446 *
1447 * Example usage:
1448 *
1449 * ```
1450 * static ɵcmp = defineComponent({
1451 * ...
1452 * inputs: {name: 'publicName'},
1453 * features: [NgOnChangesFeature]
1454 * });
1455 * ```
1456 *
1457 * @codeGenApi
1458 */
1459function ɵɵNgOnChangesFeature() {
1460 return NgOnChangesFeatureImpl;
1461}
1462function NgOnChangesFeatureImpl(definition) {
1463 if (definition.type.prototype.ngOnChanges) {
1464 definition.setInput = ngOnChangesSetInput;
1465 }
1466 return rememberChangeHistoryAndInvokeOnChangesHook;
1467}
1468// This option ensures that the ngOnChanges lifecycle hook will be inherited
1469// from superclasses (in InheritDefinitionFeature).
1470/** @nocollapse */
1471// tslint:disable-next-line:no-toplevel-property-access
1472ɵɵNgOnChangesFeature.ngInherit = true;
1473/**
1474 * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
1475 * `ngOnChanges`.
1476 *
1477 * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
1478 * found it invokes `ngOnChanges` on the component instance.
1479 *
1480 * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
1481 * it is guaranteed to be called with component instance.
1482 */
1483function rememberChangeHistoryAndInvokeOnChangesHook() {
1484 const simpleChangesStore = getSimpleChangesStore(this);
1485 const current = simpleChangesStore === null || simpleChangesStore === void 0 ? void 0 : simpleChangesStore.current;
1486 if (current) {
1487 const previous = simpleChangesStore.previous;
1488 if (previous === EMPTY_OBJ) {
1489 simpleChangesStore.previous = current;
1490 }
1491 else {
1492 // New changes are copied to the previous store, so that we don't lose history for inputs
1493 // which were not changed this time
1494 for (let key in current) {
1495 previous[key] = current[key];
1496 }
1497 }
1498 simpleChangesStore.current = null;
1499 this.ngOnChanges(current);
1500 }
1501}
1502function ngOnChangesSetInput(instance, value, publicName, privateName) {
1503 const simpleChangesStore = getSimpleChangesStore(instance) ||
1504 setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
1505 const current = simpleChangesStore.current || (simpleChangesStore.current = {});
1506 const previous = simpleChangesStore.previous;
1507 const declaredName = this.declaredInputs[publicName];
1508 const previousChange = previous[declaredName];
1509 current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
1510 instance[privateName] = value;
1511}
1512const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';
1513function getSimpleChangesStore(instance) {
1514 return instance[SIMPLE_CHANGES_STORE] || null;
1515}
1516function setSimpleChangesStore(instance, store) {
1517 return instance[SIMPLE_CHANGES_STORE] = store;
1518}
1519
1520/**
1521 * @license
1522 * Copyright Google LLC All Rights Reserved.
1523 *
1524 * Use of this source code is governed by an MIT-style license that can be
1525 * found in the LICENSE file at https://angular.io/license
1526 */
1527let profilerCallback = null;
1528/**
1529 * Sets the callback function which will be invoked before and after performing certain actions at
1530 * runtime (for example, before and after running change detection).
1531 *
1532 * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
1533 * The contract of the function might be changed in any release and/or the function can be removed
1534 * completely.
1535 *
1536 * @param profiler function provided by the caller or null value to disable profiling.
1537 */
1538const setProfiler = (profiler) => {
1539 profilerCallback = profiler;
1540};
1541/**
1542 * Profiler function which wraps user code executed by the runtime.
1543 *
1544 * @param event ProfilerEvent corresponding to the execution context
1545 * @param instance component instance
1546 * @param hookOrListener lifecycle hook function or output listener. The value depends on the
1547 * execution context
1548 * @returns
1549 */
1550const profiler = function (event, instance, hookOrListener) {
1551 if (profilerCallback != null /* both `null` and `undefined` */) {
1552 profilerCallback(event, instance, hookOrListener);
1553 }
1554};
1555
1556/**
1557 * @license
1558 * Copyright Google LLC All Rights Reserved.
1559 *
1560 * Use of this source code is governed by an MIT-style license that can be
1561 * found in the LICENSE file at https://angular.io/license
1562 */
1563const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
1564const MATH_ML_NAMESPACE = 'http://www.w3.org/1998/MathML/';
1565
1566/**
1567 * @license
1568 * Copyright Google LLC All Rights Reserved.
1569 *
1570 * Use of this source code is governed by an MIT-style license that can be
1571 * found in the LICENSE file at https://angular.io/license
1572 */
1573/**
1574 * Most of the use of `document` in Angular is from within the DI system so it is possible to simply
1575 * inject the `DOCUMENT` token and are done.
1576 *
1577 * Ivy is special because it does not rely upon the DI and must get hold of the document some other
1578 * way.
1579 *
1580 * The solution is to define `getDocument()` and `setDocument()` top-level functions for ivy.
1581 * Wherever ivy needs the global document, it calls `getDocument()` instead.
1582 *
1583 * When running ivy outside of a browser environment, it is necessary to call `setDocument()` to
1584 * tell ivy what the global `document` is.
1585 *
1586 * Angular does this for us in each of the standard platforms (`Browser`, `Server`, and `WebWorker`)
1587 * by calling `setDocument()` when providing the `DOCUMENT` token.
1588 */
1589let DOCUMENT = undefined;
1590/**
1591 * Tell ivy what the `document` is for this platform.
1592 *
1593 * It is only necessary to call this if the current platform is not a browser.
1594 *
1595 * @param document The object representing the global `document` in this environment.
1596 */
1597function setDocument(document) {
1598 DOCUMENT = document;
1599}
1600/**
1601 * Access the object that represents the `document` for this platform.
1602 *
1603 * Ivy calls this whenever it needs to access the `document` object.
1604 * For example to create the renderer or to do sanitization.
1605 */
1606function getDocument() {
1607 if (DOCUMENT !== undefined) {
1608 return DOCUMENT;
1609 }
1610 else if (typeof document !== 'undefined') {
1611 return document;
1612 }
1613 // No "document" can be found. This should only happen if we are running ivy outside Angular and
1614 // the current platform is not a browser. Since this is not a supported scenario at the moment
1615 // this should not happen in Angular apps.
1616 // Once we support running ivy outside of Angular we will need to publish `setDocument()` as a
1617 // public API. Meanwhile we just return `undefined` and let the application fail.
1618 return undefined;
1619}
1620
1621/**
1622 * @license
1623 * Copyright Google LLC All Rights Reserved.
1624 *
1625 * Use of this source code is governed by an MIT-style license that can be
1626 * found in the LICENSE file at https://angular.io/license
1627 */
1628// TODO: cleanup once the code is merged in angular/angular
1629var RendererStyleFlags3;
1630(function (RendererStyleFlags3) {
1631 RendererStyleFlags3[RendererStyleFlags3["Important"] = 1] = "Important";
1632 RendererStyleFlags3[RendererStyleFlags3["DashCase"] = 2] = "DashCase";
1633})(RendererStyleFlags3 || (RendererStyleFlags3 = {}));
1634/** Returns whether the `renderer` is a `ProceduralRenderer3` */
1635function isProceduralRenderer(renderer) {
1636 return !!(renderer.listen);
1637}
1638const domRendererFactory3 = {
1639 createRenderer: (hostElement, rendererType) => {
1640 return getDocument();
1641 }
1642};
1643// Note: This hack is necessary so we don't erroneously get a circular dependency
1644// failure based on types.
1645const unusedValueExportToPlacateAjd$6 = 1;
1646
1647/**
1648 * @license
1649 * Copyright Google LLC All Rights Reserved.
1650 *
1651 * Use of this source code is governed by an MIT-style license that can be
1652 * found in the LICENSE file at https://angular.io/license
1653 */
1654/**
1655 * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
1656 * in same location in `LView`. This is because we don't want to pre-allocate space for it
1657 * because the storage is sparse. This file contains utilities for dealing with such data types.
1658 *
1659 * How do we know what is stored at a given location in `LView`.
1660 * - `Array.isArray(value) === false` => `RNode` (The normal storage value)
1661 * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
1662 * - `typeof value[TYPE] === 'object'` => `LView`
1663 * - This happens when we have a component at a given location
1664 * - `typeof value[TYPE] === true` => `LContainer`
1665 * - This happens when we have `LContainer` binding at a given location.
1666 *
1667 *
1668 * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
1669 */
1670/**
1671 * Returns `RNode`.
1672 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1673 */
1674function unwrapRNode(value) {
1675 while (Array.isArray(value)) {
1676 value = value[HOST];
1677 }
1678 return value;
1679}
1680/**
1681 * Returns `LView` or `null` if not found.
1682 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1683 */
1684function unwrapLView(value) {
1685 while (Array.isArray(value)) {
1686 // This check is same as `isLView()` but we don't call at as we don't want to call
1687 // `Array.isArray()` twice and give JITer more work for inlining.
1688 if (typeof value[TYPE] === 'object')
1689 return value;
1690 value = value[HOST];
1691 }
1692 return null;
1693}
1694/**
1695 * Returns `LContainer` or `null` if not found.
1696 * @param value wrapped value of `RNode`, `LView`, `LContainer`
1697 */
1698function unwrapLContainer(value) {
1699 while (Array.isArray(value)) {
1700 // This check is same as `isLContainer()` but we don't call at as we don't want to call
1701 // `Array.isArray()` twice and give JITer more work for inlining.
1702 if (value[TYPE] === true)
1703 return value;
1704 value = value[HOST];
1705 }
1706 return null;
1707}
1708/**
1709 * Retrieves an element value from the provided `viewData`, by unwrapping
1710 * from any containers, component views, or style contexts.
1711 */
1712function getNativeByIndex(index, lView) {
1713 ngDevMode && assertIndexInRange(lView, index);
1714 ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
1715 return unwrapRNode(lView[index]);
1716}
1717/**
1718 * Retrieve an `RNode` for a given `TNode` and `LView`.
1719 *
1720 * This function guarantees in dev mode to retrieve a non-null `RNode`.
1721 *
1722 * @param tNode
1723 * @param lView
1724 */
1725function getNativeByTNode(tNode, lView) {
1726 ngDevMode && assertTNodeForLView(tNode, lView);
1727 ngDevMode && assertIndexInRange(lView, tNode.index);
1728 const node = unwrapRNode(lView[tNode.index]);
1729 ngDevMode && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
1730 return node;
1731}
1732/**
1733 * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
1734 *
1735 * Some `TNode`s don't have associated `RNode`s. For example `Projection`
1736 *
1737 * @param tNode
1738 * @param lView
1739 */
1740function getNativeByTNodeOrNull(tNode, lView) {
1741 const index = tNode === null ? -1 : tNode.index;
1742 if (index !== -1) {
1743 ngDevMode && assertTNodeForLView(tNode, lView);
1744 const node = unwrapRNode(lView[index]);
1745 ngDevMode && node !== null && !isProceduralRenderer(lView[RENDERER]) && assertDomNode(node);
1746 return node;
1747 }
1748 return null;
1749}
1750// fixme(misko): The return Type should be `TNode|null`
1751function getTNode(tView, index) {
1752 ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
1753 ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
1754 const tNode = tView.data[index];
1755 ngDevMode && tNode !== null && assertTNode(tNode);
1756 return tNode;
1757}
1758/** Retrieves a value from any `LView` or `TData`. */
1759function load(view, index) {
1760 ngDevMode && assertIndexInRange(view, index);
1761 return view[index];
1762}
1763function getComponentLViewByIndex(nodeIndex, hostView) {
1764 // Could be an LView or an LContainer. If LContainer, unwrap to find LView.
1765 ngDevMode && assertIndexInRange(hostView, nodeIndex);
1766 const slotValue = hostView[nodeIndex];
1767 const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
1768 return lView;
1769}
1770/** Checks whether a given view is in creation mode */
1771function isCreationMode(view) {
1772 return (view[FLAGS] & 4 /* CreationMode */) === 4 /* CreationMode */;
1773}
1774/**
1775 * Returns a boolean for whether the view is attached to the change detection tree.
1776 *
1777 * Note: This determines whether a view should be checked, not whether it's inserted
1778 * into a container. For that, you'll want `viewAttachedToContainer` below.
1779 */
1780function viewAttachedToChangeDetector(view) {
1781 return (view[FLAGS] & 128 /* Attached */) === 128 /* Attached */;
1782}
1783/** Returns a boolean for whether the view is attached to a container. */
1784function viewAttachedToContainer(view) {
1785 return isLContainer(view[PARENT]);
1786}
1787function getConstant(consts, index) {
1788 if (index === null || index === undefined)
1789 return null;
1790 ngDevMode && assertIndexInRange(consts, index);
1791 return consts[index];
1792}
1793/**
1794 * Resets the pre-order hook flags of the view.
1795 * @param lView the LView on which the flags are reset
1796 */
1797function resetPreOrderHookFlags(lView) {
1798 lView[PREORDER_HOOK_FLAGS] = 0;
1799}
1800/**
1801 * Updates the `TRANSPLANTED_VIEWS_TO_REFRESH` counter on the `LContainer` as well as the parents
1802 * whose
1803 * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
1804 * or
1805 * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
1806 */
1807function updateTransplantedViewCount(lContainer, amount) {
1808 lContainer[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;
1809 let viewOrContainer = lContainer;
1810 let parent = lContainer[PARENT];
1811 while (parent !== null &&
1812 ((amount === 1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 1) ||
1813 (amount === -1 && viewOrContainer[TRANSPLANTED_VIEWS_TO_REFRESH] === 0))) {
1814 parent[TRANSPLANTED_VIEWS_TO_REFRESH] += amount;
1815 viewOrContainer = parent;
1816 parent = parent[PARENT];
1817 }
1818}
1819
1820/**
1821 * @license
1822 * Copyright Google LLC All Rights Reserved.
1823 *
1824 * Use of this source code is governed by an MIT-style license that can be
1825 * found in the LICENSE file at https://angular.io/license
1826 */
1827const instructionState = {
1828 lFrame: createLFrame(null),
1829 bindingsEnabled: true,
1830 isInCheckNoChangesMode: false,
1831};
1832/**
1833 * Returns true if the instruction state stack is empty.
1834 *
1835 * Intended to be called from tests only (tree shaken otherwise).
1836 */
1837function specOnlyIsInstructionStateEmpty() {
1838 return instructionState.lFrame.parent === null;
1839}
1840function getElementDepthCount() {
1841 return instructionState.lFrame.elementDepthCount;
1842}
1843function increaseElementDepthCount() {
1844 instructionState.lFrame.elementDepthCount++;
1845}
1846function decreaseElementDepthCount() {
1847 instructionState.lFrame.elementDepthCount--;
1848}
1849function getBindingsEnabled() {
1850 return instructionState.bindingsEnabled;
1851}
1852/**
1853 * Enables directive matching on elements.
1854 *
1855 * * Example:
1856 * ```
1857 * <my-comp my-directive>
1858 * Should match component / directive.
1859 * </my-comp>
1860 * <div ngNonBindable>
1861 * <!-- ɵɵdisableBindings() -->
1862 * <my-comp my-directive>
1863 * Should not match component / directive because we are in ngNonBindable.
1864 * </my-comp>
1865 * <!-- ɵɵenableBindings() -->
1866 * </div>
1867 * ```
1868 *
1869 * @codeGenApi
1870 */
1871function ɵɵenableBindings() {
1872 instructionState.bindingsEnabled = true;
1873}
1874/**
1875 * Disables directive matching on element.
1876 *
1877 * * Example:
1878 * ```
1879 * <my-comp my-directive>
1880 * Should match component / directive.
1881 * </my-comp>
1882 * <div ngNonBindable>
1883 * <!-- ɵɵdisableBindings() -->
1884 * <my-comp my-directive>
1885 * Should not match component / directive because we are in ngNonBindable.
1886 * </my-comp>
1887 * <!-- ɵɵenableBindings() -->
1888 * </div>
1889 * ```
1890 *
1891 * @codeGenApi
1892 */
1893function ɵɵdisableBindings() {
1894 instructionState.bindingsEnabled = false;
1895}
1896/**
1897 * Return the current `LView`.
1898 */
1899function getLView() {
1900 return instructionState.lFrame.lView;
1901}
1902/**
1903 * Return the current `TView`.
1904 */
1905function getTView() {
1906 return instructionState.lFrame.tView;
1907}
1908/**
1909 * Restores `contextViewData` to the given OpaqueViewState instance.
1910 *
1911 * Used in conjunction with the getCurrentView() instruction to save a snapshot
1912 * of the current view and restore it when listeners are invoked. This allows
1913 * walking the declaration view tree in listeners to get vars from parent views.
1914 *
1915 * @param viewToRestore The OpaqueViewState instance to restore.
1916 * @returns Context of the restored OpaqueViewState instance.
1917 *
1918 * @codeGenApi
1919 */
1920function ɵɵrestoreView(viewToRestore) {
1921 instructionState.lFrame.contextLView = viewToRestore;
1922 return viewToRestore[CONTEXT];
1923}
1924function getCurrentTNode() {
1925 let currentTNode = getCurrentTNodePlaceholderOk();
1926 while (currentTNode !== null && currentTNode.type === 64 /* Placeholder */) {
1927 currentTNode = currentTNode.parent;
1928 }
1929 return currentTNode;
1930}
1931function getCurrentTNodePlaceholderOk() {
1932 return instructionState.lFrame.currentTNode;
1933}
1934function getCurrentParentTNode() {
1935 const lFrame = instructionState.lFrame;
1936 const currentTNode = lFrame.currentTNode;
1937 return lFrame.isParent ? currentTNode : currentTNode.parent;
1938}
1939function setCurrentTNode(tNode, isParent) {
1940 ngDevMode && tNode && assertTNodeForTView(tNode, instructionState.lFrame.tView);
1941 const lFrame = instructionState.lFrame;
1942 lFrame.currentTNode = tNode;
1943 lFrame.isParent = isParent;
1944}
1945function isCurrentTNodeParent() {
1946 return instructionState.lFrame.isParent;
1947}
1948function setCurrentTNodeAsNotParent() {
1949 instructionState.lFrame.isParent = false;
1950}
1951function setCurrentTNodeAsParent() {
1952 instructionState.lFrame.isParent = true;
1953}
1954function getContextLView() {
1955 return instructionState.lFrame.contextLView;
1956}
1957function isInCheckNoChangesMode() {
1958 // TODO(misko): remove this from the LView since it is ngDevMode=true mode only.
1959 return instructionState.isInCheckNoChangesMode;
1960}
1961function setIsInCheckNoChangesMode(mode) {
1962 instructionState.isInCheckNoChangesMode = mode;
1963}
1964// top level variables should not be exported for performance reasons (PERF_NOTES.md)
1965function getBindingRoot() {
1966 const lFrame = instructionState.lFrame;
1967 let index = lFrame.bindingRootIndex;
1968 if (index === -1) {
1969 index = lFrame.bindingRootIndex = lFrame.tView.bindingStartIndex;
1970 }
1971 return index;
1972}
1973function getBindingIndex() {
1974 return instructionState.lFrame.bindingIndex;
1975}
1976function setBindingIndex(value) {
1977 return instructionState.lFrame.bindingIndex = value;
1978}
1979function nextBindingIndex() {
1980 return instructionState.lFrame.bindingIndex++;
1981}
1982function incrementBindingIndex(count) {
1983 const lFrame = instructionState.lFrame;
1984 const index = lFrame.bindingIndex;
1985 lFrame.bindingIndex = lFrame.bindingIndex + count;
1986 return index;
1987}
1988function isInI18nBlock() {
1989 return instructionState.lFrame.inI18n;
1990}
1991function setInI18nBlock(isInI18nBlock) {
1992 instructionState.lFrame.inI18n = isInI18nBlock;
1993}
1994/**
1995 * Set a new binding root index so that host template functions can execute.
1996 *
1997 * Bindings inside the host template are 0 index. But because we don't know ahead of time
1998 * how many host bindings we have we can't pre-compute them. For this reason they are all
1999 * 0 index and we just shift the root so that they match next available location in the LView.
2000 *
2001 * @param bindingRootIndex Root index for `hostBindings`
2002 * @param currentDirectiveIndex `TData[currentDirectiveIndex]` will point to the current directive
2003 * whose `hostBindings` are being processed.
2004 */
2005function setBindingRootForHostBindings(bindingRootIndex, currentDirectiveIndex) {
2006 const lFrame = instructionState.lFrame;
2007 lFrame.bindingIndex = lFrame.bindingRootIndex = bindingRootIndex;
2008 setCurrentDirectiveIndex(currentDirectiveIndex);
2009}
2010/**
2011 * When host binding is executing this points to the directive index.
2012 * `TView.data[getCurrentDirectiveIndex()]` is `DirectiveDef`
2013 * `LView[getCurrentDirectiveIndex()]` is directive instance.
2014 */
2015function getCurrentDirectiveIndex() {
2016 return instructionState.lFrame.currentDirectiveIndex;
2017}
2018/**
2019 * Sets an index of a directive whose `hostBindings` are being processed.
2020 *
2021 * @param currentDirectiveIndex `TData` index where current directive instance can be found.
2022 */
2023function setCurrentDirectiveIndex(currentDirectiveIndex) {
2024 instructionState.lFrame.currentDirectiveIndex = currentDirectiveIndex;
2025}
2026/**
2027 * Retrieve the current `DirectiveDef` which is active when `hostBindings` instruction is being
2028 * executed.
2029 *
2030 * @param tData Current `TData` where the `DirectiveDef` will be looked up at.
2031 */
2032function getCurrentDirectiveDef(tData) {
2033 const currentDirectiveIndex = instructionState.lFrame.currentDirectiveIndex;
2034 return currentDirectiveIndex === -1 ? null : tData[currentDirectiveIndex];
2035}
2036function getCurrentQueryIndex() {
2037 return instructionState.lFrame.currentQueryIndex;
2038}
2039function setCurrentQueryIndex(value) {
2040 instructionState.lFrame.currentQueryIndex = value;
2041}
2042/**
2043 * Returns a `TNode` of the location where the current `LView` is declared at.
2044 *
2045 * @param lView an `LView` that we want to find parent `TNode` for.
2046 */
2047function getDeclarationTNode(lView) {
2048 const tView = lView[TVIEW];
2049 // Return the declaration parent for embedded views
2050 if (tView.type === 2 /* Embedded */) {
2051 ngDevMode && assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');
2052 return tView.declTNode;
2053 }
2054 // Components don't have `TView.declTNode` because each instance of component could be
2055 // inserted in different location, hence `TView.declTNode` is meaningless.
2056 // Falling back to `T_HOST` in case we cross component boundary.
2057 if (tView.type === 1 /* Component */) {
2058 return lView[T_HOST];
2059 }
2060 // Remaining TNode type is `TViewType.Root` which doesn't have a parent TNode.
2061 return null;
2062}
2063/**
2064 * This is a light weight version of the `enterView` which is needed by the DI system.
2065 *
2066 * @param lView `LView` location of the DI context.
2067 * @param tNode `TNode` for DI context
2068 * @param flags DI context flags. if `SkipSelf` flag is set than we walk up the declaration
2069 * tree from `tNode` until we find parent declared `TElementNode`.
2070 * @returns `true` if we have successfully entered DI associated with `tNode` (or with declared
2071 * `TNode` if `flags` has `SkipSelf`). Failing to enter DI implies that no associated
2072 * `NodeInjector` can be found and we should instead use `ModuleInjector`.
2073 * - If `true` than this call must be fallowed by `leaveDI`
2074 * - If `false` than this call failed and we should NOT call `leaveDI`
2075 */
2076function enterDI(lView, tNode, flags) {
2077 ngDevMode && assertLViewOrUndefined(lView);
2078 if (flags & InjectFlags.SkipSelf) {
2079 ngDevMode && assertTNodeForTView(tNode, lView[TVIEW]);
2080 let parentTNode = tNode;
2081 let parentLView = lView;
2082 while (true) {
2083 ngDevMode && assertDefined(parentTNode, 'Parent TNode should be defined');
2084 parentTNode = parentTNode.parent;
2085 if (parentTNode === null && !(flags & InjectFlags.Host)) {
2086 parentTNode = getDeclarationTNode(parentLView);
2087 if (parentTNode === null)
2088 break;
2089 // In this case, a parent exists and is definitely an element. So it will definitely
2090 // have an existing lView as the declaration view, which is why we can assume it's defined.
2091 ngDevMode && assertDefined(parentLView, 'Parent LView should be defined');
2092 parentLView = parentLView[DECLARATION_VIEW];
2093 // In Ivy there are Comment nodes that correspond to ngIf and NgFor embedded directives
2094 // We want to skip those and look only at Elements and ElementContainers to ensure
2095 // we're looking at true parent nodes, and not content or other types.
2096 if (parentTNode.type & (2 /* Element */ | 8 /* ElementContainer */)) {
2097 break;
2098 }
2099 }
2100 else {
2101 break;
2102 }
2103 }
2104 if (parentTNode === null) {
2105 // If we failed to find a parent TNode this means that we should use module injector.
2106 return false;
2107 }
2108 else {
2109 tNode = parentTNode;
2110 lView = parentLView;
2111 }
2112 }
2113 ngDevMode && assertTNodeForLView(tNode, lView);
2114 const lFrame = instructionState.lFrame = allocLFrame();
2115 lFrame.currentTNode = tNode;
2116 lFrame.lView = lView;
2117 return true;
2118}
2119/**
2120 * Swap the current lView with a new lView.
2121 *
2122 * For performance reasons we store the lView in the top level of the module.
2123 * This way we minimize the number of properties to read. Whenever a new view
2124 * is entered we have to store the lView for later, and when the view is
2125 * exited the state has to be restored
2126 *
2127 * @param newView New lView to become active
2128 * @returns the previously active lView;
2129 */
2130function enterView(newView) {
2131 ngDevMode && assertNotEqual(newView[0], newView[1], '????');
2132 ngDevMode && assertLViewOrUndefined(newView);
2133 const newLFrame = allocLFrame();
2134 if (ngDevMode) {
2135 assertEqual(newLFrame.isParent, true, 'Expected clean LFrame');
2136 assertEqual(newLFrame.lView, null, 'Expected clean LFrame');
2137 assertEqual(newLFrame.tView, null, 'Expected clean LFrame');
2138 assertEqual(newLFrame.selectedIndex, -1, 'Expected clean LFrame');
2139 assertEqual(newLFrame.elementDepthCount, 0, 'Expected clean LFrame');
2140 assertEqual(newLFrame.currentDirectiveIndex, -1, 'Expected clean LFrame');
2141 assertEqual(newLFrame.currentNamespace, null, 'Expected clean LFrame');
2142 assertEqual(newLFrame.bindingRootIndex, -1, 'Expected clean LFrame');
2143 assertEqual(newLFrame.currentQueryIndex, 0, 'Expected clean LFrame');
2144 }
2145 const tView = newView[TVIEW];
2146 instructionState.lFrame = newLFrame;
2147 ngDevMode && tView.firstChild && assertTNodeForTView(tView.firstChild, tView);
2148 newLFrame.currentTNode = tView.firstChild;
2149 newLFrame.lView = newView;
2150 newLFrame.tView = tView;
2151 newLFrame.contextLView = newView;
2152 newLFrame.bindingIndex = tView.bindingStartIndex;
2153 newLFrame.inI18n = false;
2154}
2155/**
2156 * Allocates next free LFrame. This function tries to reuse the `LFrame`s to lower memory pressure.
2157 */
2158function allocLFrame() {
2159 const currentLFrame = instructionState.lFrame;
2160 const childLFrame = currentLFrame === null ? null : currentLFrame.child;
2161 const newLFrame = childLFrame === null ? createLFrame(currentLFrame) : childLFrame;
2162 return newLFrame;
2163}
2164function createLFrame(parent) {
2165 const lFrame = {
2166 currentTNode: null,
2167 isParent: true,
2168 lView: null,
2169 tView: null,
2170 selectedIndex: -1,
2171 contextLView: null,
2172 elementDepthCount: 0,
2173 currentNamespace: null,
2174 currentDirectiveIndex: -1,
2175 bindingRootIndex: -1,
2176 bindingIndex: -1,
2177 currentQueryIndex: 0,
2178 parent: parent,
2179 child: null,
2180 inI18n: false,
2181 };
2182 parent !== null && (parent.child = lFrame); // link the new LFrame for reuse.
2183 return lFrame;
2184}
2185/**
2186 * A lightweight version of leave which is used with DI.
2187 *
2188 * This function only resets `currentTNode` and `LView` as those are the only properties
2189 * used with DI (`enterDI()`).
2190 *
2191 * NOTE: This function is reexported as `leaveDI`. However `leaveDI` has return type of `void` where
2192 * as `leaveViewLight` has `LFrame`. This is so that `leaveViewLight` can be used in `leaveView`.
2193 */
2194function leaveViewLight() {
2195 const oldLFrame = instructionState.lFrame;
2196 instructionState.lFrame = oldLFrame.parent;
2197 oldLFrame.currentTNode = null;
2198 oldLFrame.lView = null;
2199 return oldLFrame;
2200}
2201/**
2202 * This is a lightweight version of the `leaveView` which is needed by the DI system.
2203 *
2204 * NOTE: this function is an alias so that we can change the type of the function to have `void`
2205 * return type.
2206 */
2207const leaveDI = leaveViewLight;
2208/**
2209 * Leave the current `LView`
2210 *
2211 * This pops the `LFrame` with the associated `LView` from the stack.
2212 *
2213 * IMPORTANT: We must zero out the `LFrame` values here otherwise they will be retained. This is
2214 * because for performance reasons we don't release `LFrame` but rather keep it for next use.
2215 */
2216function leaveView() {
2217 const oldLFrame = leaveViewLight();
2218 oldLFrame.isParent = true;
2219 oldLFrame.tView = null;
2220 oldLFrame.selectedIndex = -1;
2221 oldLFrame.contextLView = null;
2222 oldLFrame.elementDepthCount = 0;
2223 oldLFrame.currentDirectiveIndex = -1;
2224 oldLFrame.currentNamespace = null;
2225 oldLFrame.bindingRootIndex = -1;
2226 oldLFrame.bindingIndex = -1;
2227 oldLFrame.currentQueryIndex = 0;
2228}
2229function nextContextImpl(level) {
2230 const contextLView = instructionState.lFrame.contextLView =
2231 walkUpViews(level, instructionState.lFrame.contextLView);
2232 return contextLView[CONTEXT];
2233}
2234function walkUpViews(nestingLevel, currentView) {
2235 while (nestingLevel > 0) {
2236 ngDevMode &&
2237 assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
2238 currentView = currentView[DECLARATION_VIEW];
2239 nestingLevel--;
2240 }
2241 return currentView;
2242}
2243/**
2244 * Gets the currently selected element index.
2245 *
2246 * Used with {@link property} instruction (and more in the future) to identify the index in the
2247 * current `LView` to act on.
2248 */
2249function getSelectedIndex() {
2250 return instructionState.lFrame.selectedIndex;
2251}
2252/**
2253 * Sets the most recent index passed to {@link select}
2254 *
2255 * Used with {@link property} instruction (and more in the future) to identify the index in the
2256 * current `LView` to act on.
2257 *
2258 * (Note that if an "exit function" was set earlier (via `setElementExitFn()`) then that will be
2259 * run if and when the provided `index` value is different from the current selected index value.)
2260 */
2261function setSelectedIndex(index) {
2262 ngDevMode && index !== -1 &&
2263 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Index must be past HEADER_OFFSET (or -1).');
2264 ngDevMode &&
2265 assertLessThan(index, instructionState.lFrame.lView.length, 'Can\'t set index passed end of LView');
2266 instructionState.lFrame.selectedIndex = index;
2267}
2268/**
2269 * Gets the `tNode` that represents currently selected element.
2270 */
2271function getSelectedTNode() {
2272 const lFrame = instructionState.lFrame;
2273 return getTNode(lFrame.tView, lFrame.selectedIndex);
2274}
2275/**
2276 * Sets the namespace used to create elements to `'http://www.w3.org/2000/svg'` in global state.
2277 *
2278 * @codeGenApi
2279 */
2280function ɵɵnamespaceSVG() {
2281 instructionState.lFrame.currentNamespace = SVG_NAMESPACE;
2282}
2283/**
2284 * Sets the namespace used to create elements to `'http://www.w3.org/1998/MathML/'` in global state.
2285 *
2286 * @codeGenApi
2287 */
2288function ɵɵnamespaceMathML() {
2289 instructionState.lFrame.currentNamespace = MATH_ML_NAMESPACE;
2290}
2291/**
2292 * Sets the namespace used to create elements to `null`, which forces element creation to use
2293 * `createElement` rather than `createElementNS`.
2294 *
2295 * @codeGenApi
2296 */
2297function ɵɵnamespaceHTML() {
2298 namespaceHTMLInternal();
2299}
2300/**
2301 * Sets the namespace used to create elements to `null`, which forces element creation to use
2302 * `createElement` rather than `createElementNS`.
2303 */
2304function namespaceHTMLInternal() {
2305 instructionState.lFrame.currentNamespace = null;
2306}
2307function getNamespace$1() {
2308 return instructionState.lFrame.currentNamespace;
2309}
2310
2311/**
2312 * @license
2313 * Copyright Google LLC All Rights Reserved.
2314 *
2315 * Use of this source code is governed by an MIT-style license that can be
2316 * found in the LICENSE file at https://angular.io/license
2317 */
2318/**
2319 * Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.
2320 *
2321 * Must be run *only* on the first template pass.
2322 *
2323 * Sets up the pre-order hooks on the provided `tView`,
2324 * see {@link HookData} for details about the data structure.
2325 *
2326 * @param directiveIndex The index of the directive in LView
2327 * @param directiveDef The definition containing the hooks to setup in tView
2328 * @param tView The current TView
2329 */
2330function registerPreOrderHooks(directiveIndex, directiveDef, tView) {
2331 ngDevMode && assertFirstCreatePass(tView);
2332 const { ngOnChanges, ngOnInit, ngDoCheck } = directiveDef.type.prototype;
2333 if (ngOnChanges) {
2334 const wrappedOnChanges = NgOnChangesFeatureImpl(directiveDef);
2335 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, wrappedOnChanges);
2336 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = []))
2337 .push(directiveIndex, wrappedOnChanges);
2338 }
2339 if (ngOnInit) {
2340 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(0 - directiveIndex, ngOnInit);
2341 }
2342 if (ngDoCheck) {
2343 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(directiveIndex, ngDoCheck);
2344 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(directiveIndex, ngDoCheck);
2345 }
2346}
2347/**
2348 *
2349 * Loops through the directives on the provided `tNode` and queues hooks to be
2350 * run that are not initialization hooks.
2351 *
2352 * Should be executed during `elementEnd()` and similar to
2353 * preserve hook execution order. Content, view, and destroy hooks for projected
2354 * components and directives must be called *before* their hosts.
2355 *
2356 * Sets up the content, view, and destroy hooks on the provided `tView`,
2357 * see {@link HookData} for details about the data structure.
2358 *
2359 * NOTE: This does not set up `onChanges`, `onInit` or `doCheck`, those are set up
2360 * separately at `elementStart`.
2361 *
2362 * @param tView The current TView
2363 * @param tNode The TNode whose directives are to be searched for hooks to queue
2364 */
2365function registerPostOrderHooks(tView, tNode) {
2366 ngDevMode && assertFirstCreatePass(tView);
2367 // It's necessary to loop through the directives at elementEnd() (rather than processing in
2368 // directiveCreate) so we can preserve the current hook order. Content, view, and destroy
2369 // hooks for projected components and directives must be called *before* their hosts.
2370 for (let i = tNode.directiveStart, end = tNode.directiveEnd; i < end; i++) {
2371 const directiveDef = tView.data[i];
2372 ngDevMode && assertDefined(directiveDef, 'Expecting DirectiveDef');
2373 const lifecycleHooks = directiveDef.type.prototype;
2374 const { ngAfterContentInit, ngAfterContentChecked, ngAfterViewInit, ngAfterViewChecked, ngOnDestroy } = lifecycleHooks;
2375 if (ngAfterContentInit) {
2376 (tView.contentHooks || (tView.contentHooks = [])).push(-i, ngAfterContentInit);
2377 }
2378 if (ngAfterContentChecked) {
2379 (tView.contentHooks || (tView.contentHooks = [])).push(i, ngAfterContentChecked);
2380 (tView.contentCheckHooks || (tView.contentCheckHooks = [])).push(i, ngAfterContentChecked);
2381 }
2382 if (ngAfterViewInit) {
2383 (tView.viewHooks || (tView.viewHooks = [])).push(-i, ngAfterViewInit);
2384 }
2385 if (ngAfterViewChecked) {
2386 (tView.viewHooks || (tView.viewHooks = [])).push(i, ngAfterViewChecked);
2387 (tView.viewCheckHooks || (tView.viewCheckHooks = [])).push(i, ngAfterViewChecked);
2388 }
2389 if (ngOnDestroy != null) {
2390 (tView.destroyHooks || (tView.destroyHooks = [])).push(i, ngOnDestroy);
2391 }
2392 }
2393}
2394/**
2395 * Executing hooks requires complex logic as we need to deal with 2 constraints.
2396 *
2397 * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only
2398 * once, across many change detection cycles. This must be true even if some hooks throw, or if
2399 * some recursively trigger a change detection cycle.
2400 * To solve that, it is required to track the state of the execution of these init hooks.
2401 * This is done by storing and maintaining flags in the view: the {@link InitPhaseState},
2402 * and the index within that phase. They can be seen as a cursor in the following structure:
2403 * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]]
2404 * They are are stored as flags in LView[FLAGS].
2405 *
2406 * 2. Pre-order hooks can be executed in batches, because of the select instruction.
2407 * To be able to pause and resume their execution, we also need some state about the hook's array
2408 * that is being processed:
2409 * - the index of the next hook to be executed
2410 * - the number of init hooks already found in the processed part of the array
2411 * They are are stored as flags in LView[PREORDER_HOOK_FLAGS].
2412 */
2413/**
2414 * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were
2415 * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read
2416 * / write of the init-hooks related flags.
2417 * @param lView The LView where hooks are defined
2418 * @param hooks Hooks to be run
2419 * @param nodeIndex 3 cases depending on the value:
2420 * - undefined: all hooks from the array should be executed (post-order case)
2421 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
2422 * flushing the remaining hooks)
2423 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
2424 * case, when executing select(number))
2425 */
2426function executeCheckHooks(lView, hooks, nodeIndex) {
2427 callHooks(lView, hooks, 3 /* InitPhaseCompleted */, nodeIndex);
2428}
2429/**
2430 * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked,
2431 * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed.
2432 * @param lView The LView where hooks are defined
2433 * @param hooks Hooks to be run
2434 * @param initPhase A phase for which hooks should be run
2435 * @param nodeIndex 3 cases depending on the value:
2436 * - undefined: all hooks from the array should be executed (post-order case)
2437 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
2438 * flushing the remaining hooks)
2439 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
2440 * case, when executing select(number))
2441 */
2442function executeInitAndCheckHooks(lView, hooks, initPhase, nodeIndex) {
2443 ngDevMode &&
2444 assertNotEqual(initPhase, 3 /* InitPhaseCompleted */, 'Init pre-order hooks should not be called more than once');
2445 if ((lView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
2446 callHooks(lView, hooks, initPhase, nodeIndex);
2447 }
2448}
2449function incrementInitPhaseFlags(lView, initPhase) {
2450 ngDevMode &&
2451 assertNotEqual(initPhase, 3 /* InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');
2452 let flags = lView[FLAGS];
2453 if ((flags & 3 /* InitPhaseStateMask */) === initPhase) {
2454 flags &= 2047 /* IndexWithinInitPhaseReset */;
2455 flags += 1 /* InitPhaseStateIncrementer */;
2456 lView[FLAGS] = flags;
2457 }
2458}
2459/**
2460 * Calls lifecycle hooks with their contexts, skipping init hooks if it's not
2461 * the first LView pass
2462 *
2463 * @param currentView The current view
2464 * @param arr The array in which the hooks are found
2465 * @param initPhaseState the current state of the init phase
2466 * @param currentNodeIndex 3 cases depending on the value:
2467 * - undefined: all hooks from the array should be executed (post-order case)
2468 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
2469 * flushing the remaining hooks)
2470 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
2471 * case, when executing select(number))
2472 */
2473function callHooks(currentView, arr, initPhase, currentNodeIndex) {
2474 ngDevMode &&
2475 assertEqual(isInCheckNoChangesMode(), false, 'Hooks should never be run when in check no changes mode.');
2476 const startIndex = currentNodeIndex !== undefined ?
2477 (currentView[PREORDER_HOOK_FLAGS] & 65535 /* IndexOfTheNextPreOrderHookMaskMask */) :
2478 0;
2479 const nodeIndexLimit = currentNodeIndex != null ? currentNodeIndex : -1;
2480 const max = arr.length - 1; // Stop the loop at length - 1, because we look for the hook at i + 1
2481 let lastNodeIndexFound = 0;
2482 for (let i = startIndex; i < max; i++) {
2483 const hook = arr[i + 1];
2484 if (typeof hook === 'number') {
2485 lastNodeIndexFound = arr[i];
2486 if (currentNodeIndex != null && lastNodeIndexFound >= currentNodeIndex) {
2487 break;
2488 }
2489 }
2490 else {
2491 const isInitHook = arr[i] < 0;
2492 if (isInitHook)
2493 currentView[PREORDER_HOOK_FLAGS] += 65536 /* NumberOfInitHooksCalledIncrementer */;
2494 if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {
2495 callHook(currentView, initPhase, arr, i);
2496 currentView[PREORDER_HOOK_FLAGS] =
2497 (currentView[PREORDER_HOOK_FLAGS] & 4294901760 /* NumberOfInitHooksCalledMask */) + i +
2498 2;
2499 }
2500 i++;
2501 }
2502 }
2503}
2504/**
2505 * Execute one hook against the current `LView`.
2506 *
2507 * @param currentView The current view
2508 * @param initPhaseState the current state of the init phase
2509 * @param arr The array in which the hooks are found
2510 * @param i The current index within the hook data array
2511 */
2512function callHook(currentView, initPhase, arr, i) {
2513 const isInitHook = arr[i] < 0;
2514 const hook = arr[i + 1];
2515 const directiveIndex = isInitHook ? -arr[i] : arr[i];
2516 const directive = currentView[directiveIndex];
2517 if (isInitHook) {
2518 const indexWithintInitPhase = currentView[FLAGS] >> 11 /* IndexWithinInitPhaseShift */;
2519 // The init phase state must be always checked here as it may have been recursively updated.
2520 if (indexWithintInitPhase <
2521 (currentView[PREORDER_HOOK_FLAGS] >> 16 /* NumberOfInitHooksCalledShift */) &&
2522 (currentView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
2523 currentView[FLAGS] += 2048 /* IndexWithinInitPhaseIncrementer */;
2524 profiler(4 /* LifecycleHookStart */, directive, hook);
2525 try {
2526 hook.call(directive);
2527 }
2528 finally {
2529 profiler(5 /* LifecycleHookEnd */, directive, hook);
2530 }
2531 }
2532 }
2533 else {
2534 profiler(4 /* LifecycleHookStart */, directive, hook);
2535 try {
2536 hook.call(directive);
2537 }
2538 finally {
2539 profiler(5 /* LifecycleHookEnd */, directive, hook);
2540 }
2541 }
2542}
2543
2544/**
2545 * @license
2546 * Copyright Google LLC All Rights Reserved.
2547 *
2548 * Use of this source code is governed by an MIT-style license that can be
2549 * found in the LICENSE file at https://angular.io/license
2550 */
2551const NO_PARENT_INJECTOR = -1;
2552/**
2553 * Each injector is saved in 9 contiguous slots in `LView` and 9 contiguous slots in
2554 * `TView.data`. This allows us to store information about the current node's tokens (which
2555 * can be shared in `TView`) as well as the tokens of its ancestor nodes (which cannot be
2556 * shared, so they live in `LView`).
2557 *
2558 * Each of these slots (aside from the last slot) contains a bloom filter. This bloom filter
2559 * determines whether a directive is available on the associated node or not. This prevents us
2560 * from searching the directives array at this level unless it's probable the directive is in it.
2561 *
2562 * See: https://en.wikipedia.org/wiki/Bloom_filter for more about bloom filters.
2563 *
2564 * Because all injectors have been flattened into `LView` and `TViewData`, they cannot typed
2565 * using interfaces as they were previously. The start index of each `LInjector` and `TInjector`
2566 * will differ based on where it is flattened into the main array, so it's not possible to know
2567 * the indices ahead of time and save their types here. The interfaces are still included here
2568 * for documentation purposes.
2569 *
2570 * export interface LInjector extends Array<any> {
2571 *
2572 * // Cumulative bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)
2573 * [0]: number;
2574 *
2575 * // Cumulative bloom for directive IDs 32-63
2576 * [1]: number;
2577 *
2578 * // Cumulative bloom for directive IDs 64-95
2579 * [2]: number;
2580 *
2581 * // Cumulative bloom for directive IDs 96-127
2582 * [3]: number;
2583 *
2584 * // Cumulative bloom for directive IDs 128-159
2585 * [4]: number;
2586 *
2587 * // Cumulative bloom for directive IDs 160 - 191
2588 * [5]: number;
2589 *
2590 * // Cumulative bloom for directive IDs 192 - 223
2591 * [6]: number;
2592 *
2593 * // Cumulative bloom for directive IDs 224 - 255
2594 * [7]: number;
2595 *
2596 * // We need to store a reference to the injector's parent so DI can keep looking up
2597 * // the injector tree until it finds the dependency it's looking for.
2598 * [PARENT_INJECTOR]: number;
2599 * }
2600 *
2601 * export interface TInjector extends Array<any> {
2602 *
2603 * // Shared node bloom for directive IDs 0-31 (IDs are % BLOOM_SIZE)
2604 * [0]: number;
2605 *
2606 * // Shared node bloom for directive IDs 32-63
2607 * [1]: number;
2608 *
2609 * // Shared node bloom for directive IDs 64-95
2610 * [2]: number;
2611 *
2612 * // Shared node bloom for directive IDs 96-127
2613 * [3]: number;
2614 *
2615 * // Shared node bloom for directive IDs 128-159
2616 * [4]: number;
2617 *
2618 * // Shared node bloom for directive IDs 160 - 191
2619 * [5]: number;
2620 *
2621 * // Shared node bloom for directive IDs 192 - 223
2622 * [6]: number;
2623 *
2624 * // Shared node bloom for directive IDs 224 - 255
2625 * [7]: number;
2626 *
2627 * // Necessary to find directive indices for a particular node.
2628 * [TNODE]: TElementNode|TElementContainerNode|TContainerNode;
2629 * }
2630 */
2631/**
2632 * Factory for creating instances of injectors in the NodeInjector.
2633 *
2634 * This factory is complicated by the fact that it can resolve `multi` factories as well.
2635 *
2636 * NOTE: Some of the fields are optional which means that this class has two hidden classes.
2637 * - One without `multi` support (most common)
2638 * - One with `multi` values, (rare).
2639 *
2640 * Since VMs can cache up to 4 inline hidden classes this is OK.
2641 *
2642 * - Single factory: Only `resolving` and `factory` is defined.
2643 * - `providers` factory: `componentProviders` is a number and `index = -1`.
2644 * - `viewProviders` factory: `componentProviders` is a number and `index` points to `providers`.
2645 */
2646class NodeInjectorFactory {
2647 constructor(
2648 /**
2649 * Factory to invoke in order to create a new instance.
2650 */
2651 factory,
2652 /**
2653 * Set to `true` if the token is declared in `viewProviders` (or if it is component).
2654 */
2655 isViewProvider, injectImplementation) {
2656 this.factory = factory;
2657 /**
2658 * Marker set to true during factory invocation to see if we get into recursive loop.
2659 * Recursive loop causes an error to be displayed.
2660 */
2661 this.resolving = false;
2662 ngDevMode && assertDefined(factory, 'Factory not specified');
2663 ngDevMode && assertEqual(typeof factory, 'function', 'Expected factory function.');
2664 this.canSeeViewProviders = isViewProvider;
2665 this.injectImpl = injectImplementation;
2666 }
2667}
2668function isFactory(obj) {
2669 return obj instanceof NodeInjectorFactory;
2670}
2671// Note: This hack is necessary so we don't erroneously get a circular dependency
2672// failure based on types.
2673const unusedValueExportToPlacateAjd$5 = 1;
2674
2675/**
2676 * Converts `TNodeType` into human readable text.
2677 * Make sure this matches with `TNodeType`
2678 */
2679function toTNodeTypeAsString(tNodeType) {
2680 let text = '';
2681 (tNodeType & 1 /* Text */) && (text += '|Text');
2682 (tNodeType & 2 /* Element */) && (text += '|Element');
2683 (tNodeType & 4 /* Container */) && (text += '|Container');
2684 (tNodeType & 8 /* ElementContainer */) && (text += '|ElementContainer');
2685 (tNodeType & 16 /* Projection */) && (text += '|Projection');
2686 (tNodeType & 32 /* Icu */) && (text += '|IcuContainer');
2687 (tNodeType & 64 /* Placeholder */) && (text += '|Placeholder');
2688 return text.length > 0 ? text.substring(1) : text;
2689}
2690// Note: This hack is necessary so we don't erroneously get a circular dependency
2691// failure based on types.
2692const unusedValueExportToPlacateAjd$4 = 1;
2693/**
2694 * Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.
2695 *
2696 * ```
2697 * <div my-dir [class]="exp"></div>
2698 * ```
2699 * and
2700 * ```
2701 * @Directive({
2702 * })
2703 * class MyDirective {
2704 * @Input()
2705 * class: string;
2706 * }
2707 * ```
2708 *
2709 * In the above case it is necessary to write the reconciled styling information into the
2710 * directive's input.
2711 *
2712 * @param tNode
2713 */
2714function hasClassInput(tNode) {
2715 return (tNode.flags & 16 /* hasClassInput */) !== 0;
2716}
2717/**
2718 * Returns `true` if the `TNode` has a directive which has `@Input()` for `style` binding.
2719 *
2720 * ```
2721 * <div my-dir [style]="exp"></div>
2722 * ```
2723 * and
2724 * ```
2725 * @Directive({
2726 * })
2727 * class MyDirective {
2728 * @Input()
2729 * class: string;
2730 * }
2731 * ```
2732 *
2733 * In the above case it is necessary to write the reconciled styling information into the
2734 * directive's input.
2735 *
2736 * @param tNode
2737 */
2738function hasStyleInput(tNode) {
2739 return (tNode.flags & 32 /* hasStyleInput */) !== 0;
2740}
2741
2742/**
2743 * @license
2744 * Copyright Google LLC All Rights Reserved.
2745 *
2746 * Use of this source code is governed by an MIT-style license that can be
2747 * found in the LICENSE file at https://angular.io/license
2748 */
2749function assertTNodeType(tNode, expectedTypes, message) {
2750 assertDefined(tNode, 'should be called with a TNode');
2751 if ((tNode.type & expectedTypes) === 0) {
2752 throwError(message ||
2753 `Expected [${toTNodeTypeAsString(expectedTypes)}] but got ${toTNodeTypeAsString(tNode.type)}.`);
2754 }
2755}
2756function assertPureTNodeType(type) {
2757 if (!(type === 2 /* Element */ || //
2758 type === 1 /* Text */ || //
2759 type === 4 /* Container */ || //
2760 type === 8 /* ElementContainer */ || //
2761 type === 32 /* Icu */ || //
2762 type === 16 /* Projection */ || //
2763 type === 64 /* Placeholder */)) {
2764 throwError(`Expected TNodeType to have only a single type selected, but got ${toTNodeTypeAsString(type)}.`);
2765 }
2766}
2767
2768/**
2769 * Assigns all attribute values to the provided element via the inferred renderer.
2770 *
2771 * This function accepts two forms of attribute entries:
2772 *
2773 * default: (key, value):
2774 * attrs = [key1, value1, key2, value2]
2775 *
2776 * namespaced: (NAMESPACE_MARKER, uri, name, value)
2777 * attrs = [NAMESPACE_MARKER, uri, name, value, NAMESPACE_MARKER, uri, name, value]
2778 *
2779 * The `attrs` array can contain a mix of both the default and namespaced entries.
2780 * The "default" values are set without a marker, but if the function comes across
2781 * a marker value then it will attempt to set a namespaced value. If the marker is
2782 * not of a namespaced value then the function will quit and return the index value
2783 * where it stopped during the iteration of the attrs array.
2784 *
2785 * See [AttributeMarker] to understand what the namespace marker value is.
2786 *
2787 * Note that this instruction does not support assigning style and class values to
2788 * an element. See `elementStart` and `elementHostAttrs` to learn how styling values
2789 * are applied to an element.
2790 * @param renderer The renderer to be used
2791 * @param native The element that the attributes will be assigned to
2792 * @param attrs The attribute array of values that will be assigned to the element
2793 * @returns the index value that was last accessed in the attributes array
2794 */
2795function setUpAttributes(renderer, native, attrs) {
2796 const isProc = isProceduralRenderer(renderer);
2797 let i = 0;
2798 while (i < attrs.length) {
2799 const value = attrs[i];
2800 if (typeof value === 'number') {
2801 // only namespaces are supported. Other value types (such as style/class
2802 // entries) are not supported in this function.
2803 if (value !== 0 /* NamespaceURI */) {
2804 break;
2805 }
2806 // we just landed on the marker value ... therefore
2807 // we should skip to the next entry
2808 i++;
2809 const namespaceURI = attrs[i++];
2810 const attrName = attrs[i++];
2811 const attrVal = attrs[i++];
2812 ngDevMode && ngDevMode.rendererSetAttribute++;
2813 isProc ?
2814 renderer.setAttribute(native, attrName, attrVal, namespaceURI) :
2815 native.setAttributeNS(namespaceURI, attrName, attrVal);
2816 }
2817 else {
2818 // attrName is string;
2819 const attrName = value;
2820 const attrVal = attrs[++i];
2821 // Standard attributes
2822 ngDevMode && ngDevMode.rendererSetAttribute++;
2823 if (isAnimationProp(attrName)) {
2824 if (isProc) {
2825 renderer.setProperty(native, attrName, attrVal);
2826 }
2827 }
2828 else {
2829 isProc ?
2830 renderer.setAttribute(native, attrName, attrVal) :
2831 native.setAttribute(attrName, attrVal);
2832 }
2833 i++;
2834 }
2835 }
2836 // another piece of code may iterate over the same attributes array. Therefore
2837 // it may be helpful to return the exact spot where the attributes array exited
2838 // whether by running into an unsupported marker or if all the static values were
2839 // iterated over.
2840 return i;
2841}
2842/**
2843 * Test whether the given value is a marker that indicates that the following
2844 * attribute values in a `TAttributes` array are only the names of attributes,
2845 * and not name-value pairs.
2846 * @param marker The attribute marker to test.
2847 * @returns true if the marker is a "name-only" marker (e.g. `Bindings`, `Template` or `I18n`).
2848 */
2849function isNameOnlyAttributeMarker(marker) {
2850 return marker === 3 /* Bindings */ || marker === 4 /* Template */ ||
2851 marker === 6 /* I18n */;
2852}
2853function isAnimationProp(name) {
2854 // Perf note: accessing charCodeAt to check for the first character of a string is faster as
2855 // compared to accessing a character at index 0 (ex. name[0]). The main reason for this is that
2856 // charCodeAt doesn't allocate memory to return a substring.
2857 return name.charCodeAt(0) === 64 /* AT_SIGN */;
2858}
2859/**
2860 * Merges `src` `TAttributes` into `dst` `TAttributes` removing any duplicates in the process.
2861 *
2862 * This merge function keeps the order of attrs same.
2863 *
2864 * @param dst Location of where the merged `TAttributes` should end up.
2865 * @param src `TAttributes` which should be appended to `dst`
2866 */
2867function mergeHostAttrs(dst, src) {
2868 if (src === null || src.length === 0) {
2869 // do nothing
2870 }
2871 else if (dst === null || dst.length === 0) {
2872 // We have source, but dst is empty, just make a copy.
2873 dst = src.slice();
2874 }
2875 else {
2876 let srcMarker = -1 /* ImplicitAttributes */;
2877 for (let i = 0; i < src.length; i++) {
2878 const item = src[i];
2879 if (typeof item === 'number') {
2880 srcMarker = item;
2881 }
2882 else {
2883 if (srcMarker === 0 /* NamespaceURI */) {
2884 // Case where we need to consume `key1`, `key2`, `value` items.
2885 }
2886 else if (srcMarker === -1 /* ImplicitAttributes */ ||
2887 srcMarker === 2 /* Styles */) {
2888 // Case where we have to consume `key1` and `value` only.
2889 mergeHostAttribute(dst, srcMarker, item, null, src[++i]);
2890 }
2891 else {
2892 // Case where we have to consume `key1` only.
2893 mergeHostAttribute(dst, srcMarker, item, null, null);
2894 }
2895 }
2896 }
2897 }
2898 return dst;
2899}
2900/**
2901 * Append `key`/`value` to existing `TAttributes` taking region marker and duplicates into account.
2902 *
2903 * @param dst `TAttributes` to append to.
2904 * @param marker Region where the `key`/`value` should be added.
2905 * @param key1 Key to add to `TAttributes`
2906 * @param key2 Key to add to `TAttributes` (in case of `AttributeMarker.NamespaceURI`)
2907 * @param value Value to add or to overwrite to `TAttributes` Only used if `marker` is not Class.
2908 */
2909function mergeHostAttribute(dst, marker, key1, key2, value) {
2910 let i = 0;
2911 // Assume that new markers will be inserted at the end.
2912 let markerInsertPosition = dst.length;
2913 // scan until correct type.
2914 if (marker === -1 /* ImplicitAttributes */) {
2915 markerInsertPosition = -1;
2916 }
2917 else {
2918 while (i < dst.length) {
2919 const dstValue = dst[i++];
2920 if (typeof dstValue === 'number') {
2921 if (dstValue === marker) {
2922 markerInsertPosition = -1;
2923 break;
2924 }
2925 else if (dstValue > marker) {
2926 // We need to save this as we want the markers to be inserted in specific order.
2927 markerInsertPosition = i - 1;
2928 break;
2929 }
2930 }
2931 }
2932 }
2933 // search until you find place of insertion
2934 while (i < dst.length) {
2935 const item = dst[i];
2936 if (typeof item === 'number') {
2937 // since `i` started as the index after the marker, we did not find it if we are at the next
2938 // marker
2939 break;
2940 }
2941 else if (item === key1) {
2942 // We already have same token
2943 if (key2 === null) {
2944 if (value !== null) {
2945 dst[i + 1] = value;
2946 }
2947 return;
2948 }
2949 else if (key2 === dst[i + 1]) {
2950 dst[i + 2] = value;
2951 return;
2952 }
2953 }
2954 // Increment counter.
2955 i++;
2956 if (key2 !== null)
2957 i++;
2958 if (value !== null)
2959 i++;
2960 }
2961 // insert at location.
2962 if (markerInsertPosition !== -1) {
2963 dst.splice(markerInsertPosition, 0, marker);
2964 i = markerInsertPosition + 1;
2965 }
2966 dst.splice(i++, 0, key1);
2967 if (key2 !== null) {
2968 dst.splice(i++, 0, key2);
2969 }
2970 if (value !== null) {
2971 dst.splice(i++, 0, value);
2972 }
2973}
2974
2975/**
2976 * @license
2977 * Copyright Google LLC All Rights Reserved.
2978 *
2979 * Use of this source code is governed by an MIT-style license that can be
2980 * found in the LICENSE file at https://angular.io/license
2981 */
2982/// Parent Injector Utils ///////////////////////////////////////////////////////////////
2983function hasParentInjector(parentLocation) {
2984 return parentLocation !== NO_PARENT_INJECTOR;
2985}
2986function getParentInjectorIndex(parentLocation) {
2987 ngDevMode && assertNumber(parentLocation, 'Number expected');
2988 ngDevMode && assertNotEqual(parentLocation, -1, 'Not a valid state.');
2989 const parentInjectorIndex = parentLocation & 32767 /* InjectorIndexMask */;
2990 ngDevMode &&
2991 assertGreaterThan(parentInjectorIndex, HEADER_OFFSET, 'Parent injector must be pointing past HEADER_OFFSET.');
2992 return parentLocation & 32767 /* InjectorIndexMask */;
2993}
2994function getParentInjectorViewOffset(parentLocation) {
2995 return parentLocation >> 16 /* ViewOffsetShift */;
2996}
2997/**
2998 * Unwraps a parent injector location number to find the view offset from the current injector,
2999 * then walks up the declaration view tree until the view is found that contains the parent
3000 * injector.
3001 *
3002 * @param location The location of the parent injector, which contains the view offset
3003 * @param startView The LView instance from which to start walking up the view tree
3004 * @returns The LView instance that contains the parent injector
3005 */
3006function getParentInjectorView(location, startView) {
3007 let viewOffset = getParentInjectorViewOffset(location);
3008 let parentView = startView;
3009 // For most cases, the parent injector can be found on the host node (e.g. for component
3010 // or container), but we must keep the loop here to support the rarer case of deeply nested
3011 // <ng-template> tags or inline views, where the parent injector might live many views
3012 // above the child injector.
3013 while (viewOffset > 0) {
3014 parentView = parentView[DECLARATION_VIEW];
3015 viewOffset--;
3016 }
3017 return parentView;
3018}
3019
3020/**
3021 * @license
3022 * Copyright Google LLC All Rights Reserved.
3023 *
3024 * Use of this source code is governed by an MIT-style license that can be
3025 * found in the LICENSE file at https://angular.io/license
3026 */
3027/**
3028 * Defines if the call to `inject` should include `viewProviders` in its resolution.
3029 *
3030 * This is set to true when we try to instantiate a component. This value is reset in
3031 * `getNodeInjectable` to a value which matches the declaration location of the token about to be
3032 * instantiated. This is done so that if we are injecting a token which was declared outside of
3033 * `viewProviders` we don't accidentally pull `viewProviders` in.
3034 *
3035 * Example:
3036 *
3037 * ```
3038 * @Injectable()
3039 * class MyService {
3040 * constructor(public value: String) {}
3041 * }
3042 *
3043 * @Component({
3044 * providers: [
3045 * MyService,
3046 * {provide: String, value: 'providers' }
3047 * ]
3048 * viewProviders: [
3049 * {provide: String, value: 'viewProviders'}
3050 * ]
3051 * })
3052 * class MyComponent {
3053 * constructor(myService: MyService, value: String) {
3054 * // We expect that Component can see into `viewProviders`.
3055 * expect(value).toEqual('viewProviders');
3056 * // `MyService` was not declared in `viewProviders` hence it can't see it.
3057 * expect(myService.value).toEqual('providers');
3058 * }
3059 * }
3060 *
3061 * ```
3062 */
3063let includeViewProviders = true;
3064function setIncludeViewProviders(v) {
3065 const oldValue = includeViewProviders;
3066 includeViewProviders = v;
3067 return oldValue;
3068}
3069/**
3070 * The number of slots in each bloom filter (used by DI). The larger this number, the fewer
3071 * directives that will share slots, and thus, the fewer false positives when checking for
3072 * the existence of a directive.
3073 */
3074const BLOOM_SIZE = 256;
3075const BLOOM_MASK = BLOOM_SIZE - 1;
3076/**
3077 * The number of bits that is represented by a single bloom bucket. JS bit operations are 32 bits,
3078 * so each bucket represents 32 distinct tokens which accounts for log2(32) = 5 bits of a bloom hash
3079 * number.
3080 */
3081const BLOOM_BUCKET_BITS = 5;
3082/** Counter used to generate unique IDs for directives. */
3083let nextNgElementId = 0;
3084/**
3085 * Registers this directive as present in its node's injector by flipping the directive's
3086 * corresponding bit in the injector's bloom filter.
3087 *
3088 * @param injectorIndex The index of the node injector where this token should be registered
3089 * @param tView The TView for the injector's bloom filters
3090 * @param type The directive token to register
3091 */
3092function bloomAdd(injectorIndex, tView, type) {
3093 ngDevMode && assertEqual(tView.firstCreatePass, true, 'expected firstCreatePass to be true');
3094 let id;
3095 if (typeof type === 'string') {
3096 id = type.charCodeAt(0) || 0;
3097 }
3098 else if (type.hasOwnProperty(NG_ELEMENT_ID)) {
3099 id = type[NG_ELEMENT_ID];
3100 }
3101 // Set a unique ID on the directive type, so if something tries to inject the directive,
3102 // we can easily retrieve the ID and hash it into the bloom bit that should be checked.
3103 if (id == null) {
3104 id = type[NG_ELEMENT_ID] = nextNgElementId++;
3105 }
3106 // We only have BLOOM_SIZE (256) slots in our bloom filter (8 buckets * 32 bits each),
3107 // so all unique IDs must be modulo-ed into a number from 0 - 255 to fit into the filter.
3108 const bloomHash = id & BLOOM_MASK;
3109 // Create a mask that targets the specific bit associated with the directive.
3110 // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
3111 // to bit positions 0 - 31 in a 32 bit integer.
3112 const mask = 1 << bloomHash;
3113 // Each bloom bucket in `tData` represents `BLOOM_BUCKET_BITS` number of bits of `bloomHash`.
3114 // Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset that the mask
3115 // should be written to.
3116 tView.data[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)] |= mask;
3117}
3118/**
3119 * Creates (or gets an existing) injector for a given element or container.
3120 *
3121 * @param tNode for which an injector should be retrieved / created.
3122 * @param lView View where the node is stored
3123 * @returns Node injector
3124 */
3125function getOrCreateNodeInjectorForNode(tNode, lView) {
3126 const existingInjectorIndex = getInjectorIndex(tNode, lView);
3127 if (existingInjectorIndex !== -1) {
3128 return existingInjectorIndex;
3129 }
3130 const tView = lView[TVIEW];
3131 if (tView.firstCreatePass) {
3132 tNode.injectorIndex = lView.length;
3133 insertBloom(tView.data, tNode); // foundation for node bloom
3134 insertBloom(lView, null); // foundation for cumulative bloom
3135 insertBloom(tView.blueprint, null);
3136 }
3137 const parentLoc = getParentInjectorLocation(tNode, lView);
3138 const injectorIndex = tNode.injectorIndex;
3139 // If a parent injector can't be found, its location is set to -1.
3140 // In that case, we don't need to set up a cumulative bloom
3141 if (hasParentInjector(parentLoc)) {
3142 const parentIndex = getParentInjectorIndex(parentLoc);
3143 const parentLView = getParentInjectorView(parentLoc, lView);
3144 const parentData = parentLView[TVIEW].data;
3145 // Creates a cumulative bloom filter that merges the parent's bloom filter
3146 // and its own cumulative bloom (which contains tokens for all ancestors)
3147 for (let i = 0; i < 8 /* BLOOM_SIZE */; i++) {
3148 lView[injectorIndex + i] = parentLView[parentIndex + i] | parentData[parentIndex + i];
3149 }
3150 }
3151 lView[injectorIndex + 8 /* PARENT */] = parentLoc;
3152 return injectorIndex;
3153}
3154function insertBloom(arr, footer) {
3155 arr.push(0, 0, 0, 0, 0, 0, 0, 0, footer);
3156}
3157function getInjectorIndex(tNode, lView) {
3158 if (tNode.injectorIndex === -1 ||
3159 // If the injector index is the same as its parent's injector index, then the index has been
3160 // copied down from the parent node. No injector has been created yet on this node.
3161 (tNode.parent && tNode.parent.injectorIndex === tNode.injectorIndex) ||
3162 // After the first template pass, the injector index might exist but the parent values
3163 // might not have been calculated yet for this instance
3164 lView[tNode.injectorIndex + 8 /* PARENT */] === null) {
3165 return -1;
3166 }
3167 else {
3168 ngDevMode && assertIndexInRange(lView, tNode.injectorIndex);
3169 return tNode.injectorIndex;
3170 }
3171}
3172/**
3173 * Finds the index of the parent injector, with a view offset if applicable. Used to set the
3174 * parent injector initially.
3175 *
3176 * @returns Returns a number that is the combination of the number of LViews that we have to go up
3177 * to find the LView containing the parent inject AND the index of the injector within that LView.
3178 */
3179function getParentInjectorLocation(tNode, lView) {
3180 if (tNode.parent && tNode.parent.injectorIndex !== -1) {
3181 // If we have a parent `TNode` and there is an injector associated with it we are done, because
3182 // the parent injector is within the current `LView`.
3183 return tNode.parent.injectorIndex; // ViewOffset is 0
3184 }
3185 // When parent injector location is computed it may be outside of the current view. (ie it could
3186 // be pointing to a declared parent location). This variable stores number of declaration parents
3187 // we need to walk up in order to find the parent injector location.
3188 let declarationViewOffset = 0;
3189 let parentTNode = null;
3190 let lViewCursor = lView;
3191 // The parent injector is not in the current `LView`. We will have to walk the declared parent
3192 // `LView` hierarchy and look for it. If we walk of the top, that means that there is no parent
3193 // `NodeInjector`.
3194 while (lViewCursor !== null) {
3195 // First determine the `parentTNode` location. The parent pointer differs based on `TView.type`.
3196 const tView = lViewCursor[TVIEW];
3197 const tViewType = tView.type;
3198 if (tViewType === 2 /* Embedded */) {
3199 ngDevMode &&
3200 assertDefined(tView.declTNode, 'Embedded TNodes should have declaration parents.');
3201 parentTNode = tView.declTNode;
3202 }
3203 else if (tViewType === 1 /* Component */) {
3204 // Components don't have `TView.declTNode` because each instance of component could be
3205 // inserted in different location, hence `TView.declTNode` is meaningless.
3206 parentTNode = lViewCursor[T_HOST];
3207 }
3208 else {
3209 ngDevMode && assertEqual(tView.type, 0 /* Root */, 'Root type expected');
3210 parentTNode = null;
3211 }
3212 if (parentTNode === null) {
3213 // If we have no parent, than we are done.
3214 return NO_PARENT_INJECTOR;
3215 }
3216 ngDevMode && parentTNode && assertTNodeForLView(parentTNode, lViewCursor[DECLARATION_VIEW]);
3217 // Every iteration of the loop requires that we go to the declared parent.
3218 declarationViewOffset++;
3219 lViewCursor = lViewCursor[DECLARATION_VIEW];
3220 if (parentTNode.injectorIndex !== -1) {
3221 // We found a NodeInjector which points to something.
3222 return (parentTNode.injectorIndex |
3223 (declarationViewOffset << 16 /* ViewOffsetShift */));
3224 }
3225 }
3226 return NO_PARENT_INJECTOR;
3227}
3228/**
3229 * Makes a type or an injection token public to the DI system by adding it to an
3230 * injector's bloom filter.
3231 *
3232 * @param di The node injector in which a directive will be added
3233 * @param token The type or the injection token to be made public
3234 */
3235function diPublicInInjector(injectorIndex, tView, token) {
3236 bloomAdd(injectorIndex, tView, token);
3237}
3238/**
3239 * Inject static attribute value into directive constructor.
3240 *
3241 * This method is used with `factory` functions which are generated as part of
3242 * `defineDirective` or `defineComponent`. The method retrieves the static value
3243 * of an attribute. (Dynamic attributes are not supported since they are not resolved
3244 * at the time of injection and can change over time.)
3245 *
3246 * # Example
3247 * Given:
3248 * ```
3249 * @Component(...)
3250 * class MyComponent {
3251 * constructor(@Attribute('title') title: string) { ... }
3252 * }
3253 * ```
3254 * When instantiated with
3255 * ```
3256 * <my-component title="Hello"></my-component>
3257 * ```
3258 *
3259 * Then factory method generated is:
3260 * ```
3261 * MyComponent.ɵcmp = defineComponent({
3262 * factory: () => new MyComponent(injectAttribute('title'))
3263 * ...
3264 * })
3265 * ```
3266 *
3267 * @publicApi
3268 */
3269function injectAttributeImpl(tNode, attrNameToInject) {
3270 ngDevMode && assertTNodeType(tNode, 12 /* AnyContainer */ | 3 /* AnyRNode */);
3271 ngDevMode && assertDefined(tNode, 'expecting tNode');
3272 if (attrNameToInject === 'class') {
3273 return tNode.classes;
3274 }
3275 if (attrNameToInject === 'style') {
3276 return tNode.styles;
3277 }
3278 const attrs = tNode.attrs;
3279 if (attrs) {
3280 const attrsLength = attrs.length;
3281 let i = 0;
3282 while (i < attrsLength) {
3283 const value = attrs[i];
3284 // If we hit a `Bindings` or `Template` marker then we are done.
3285 if (isNameOnlyAttributeMarker(value))
3286 break;
3287 // Skip namespaced attributes
3288 if (value === 0 /* NamespaceURI */) {
3289 // we skip the next two values
3290 // as namespaced attributes looks like
3291 // [..., AttributeMarker.NamespaceURI, 'http://someuri.com/test', 'test:exist',
3292 // 'existValue', ...]
3293 i = i + 2;
3294 }
3295 else if (typeof value === 'number') {
3296 // Skip to the first value of the marked attribute.
3297 i++;
3298 while (i < attrsLength && typeof attrs[i] === 'string') {
3299 i++;
3300 }
3301 }
3302 else if (value === attrNameToInject) {
3303 return attrs[i + 1];
3304 }
3305 else {
3306 i = i + 2;
3307 }
3308 }
3309 }
3310 return null;
3311}
3312function notFoundValueOrThrow(notFoundValue, token, flags) {
3313 if (flags & InjectFlags.Optional) {
3314 return notFoundValue;
3315 }
3316 else {
3317 throwProviderNotFoundError(token, 'NodeInjector');
3318 }
3319}
3320/**
3321 * Returns the value associated to the given token from the ModuleInjector or throws exception
3322 *
3323 * @param lView The `LView` that contains the `tNode`
3324 * @param token The token to look for
3325 * @param flags Injection flags
3326 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
3327 * @returns the value from the injector or throws an exception
3328 */
3329function lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue) {
3330 if (flags & InjectFlags.Optional && notFoundValue === undefined) {
3331 // This must be set or the NullInjector will throw for optional deps
3332 notFoundValue = null;
3333 }
3334 if ((flags & (InjectFlags.Self | InjectFlags.Host)) === 0) {
3335 const moduleInjector = lView[INJECTOR$1];
3336 // switch to `injectInjectorOnly` implementation for module injector, since module injector
3337 // should not have access to Component/Directive DI scope (that may happen through
3338 // `directiveInject` implementation)
3339 const previousInjectImplementation = setInjectImplementation(undefined);
3340 try {
3341 if (moduleInjector) {
3342 return moduleInjector.get(token, notFoundValue, flags & InjectFlags.Optional);
3343 }
3344 else {
3345 return injectRootLimpMode(token, notFoundValue, flags & InjectFlags.Optional);
3346 }
3347 }
3348 finally {
3349 setInjectImplementation(previousInjectImplementation);
3350 }
3351 }
3352 return notFoundValueOrThrow(notFoundValue, token, flags);
3353}
3354/**
3355 * Returns the value associated to the given token from the NodeInjectors => ModuleInjector.
3356 *
3357 * Look for the injector providing the token by walking up the node injector tree and then
3358 * the module injector tree.
3359 *
3360 * This function patches `token` with `__NG_ELEMENT_ID__` which contains the id for the bloom
3361 * filter. `-1` is reserved for injecting `Injector` (implemented by `NodeInjector`)
3362 *
3363 * @param tNode The Node where the search for the injector should start
3364 * @param lView The `LView` that contains the `tNode`
3365 * @param token The token to look for
3366 * @param flags Injection flags
3367 * @param notFoundValue The value to return when the injection flags is `InjectFlags.Optional`
3368 * @returns the value from the injector, `null` when not found, or `notFoundValue` if provided
3369 */
3370function getOrCreateInjectable(tNode, lView, token, flags = InjectFlags.Default, notFoundValue) {
3371 if (tNode !== null) {
3372 const bloomHash = bloomHashBitOrFactory(token);
3373 // If the ID stored here is a function, this is a special object like ElementRef or TemplateRef
3374 // so just call the factory function to create it.
3375 if (typeof bloomHash === 'function') {
3376 if (!enterDI(lView, tNode, flags)) {
3377 // Failed to enter DI, try module injector instead. If a token is injected with the @Host
3378 // flag, the module injector is not searched for that token in Ivy.
3379 return (flags & InjectFlags.Host) ?
3380 notFoundValueOrThrow(notFoundValue, token, flags) :
3381 lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);
3382 }
3383 try {
3384 const value = bloomHash(flags);
3385 if (value == null && !(flags & InjectFlags.Optional)) {
3386 throwProviderNotFoundError(token);
3387 }
3388 else {
3389 return value;
3390 }
3391 }
3392 finally {
3393 leaveDI();
3394 }
3395 }
3396 else if (typeof bloomHash === 'number') {
3397 // A reference to the previous injector TView that was found while climbing the element
3398 // injector tree. This is used to know if viewProviders can be accessed on the current
3399 // injector.
3400 let previousTView = null;
3401 let injectorIndex = getInjectorIndex(tNode, lView);
3402 let parentLocation = NO_PARENT_INJECTOR;
3403 let hostTElementNode = flags & InjectFlags.Host ? lView[DECLARATION_COMPONENT_VIEW][T_HOST] : null;
3404 // If we should skip this injector, or if there is no injector on this node, start by
3405 // searching the parent injector.
3406 if (injectorIndex === -1 || flags & InjectFlags.SkipSelf) {
3407 parentLocation = injectorIndex === -1 ? getParentInjectorLocation(tNode, lView) :
3408 lView[injectorIndex + 8 /* PARENT */];
3409 if (parentLocation === NO_PARENT_INJECTOR || !shouldSearchParent(flags, false)) {
3410 injectorIndex = -1;
3411 }
3412 else {
3413 previousTView = lView[TVIEW];
3414 injectorIndex = getParentInjectorIndex(parentLocation);
3415 lView = getParentInjectorView(parentLocation, lView);
3416 }
3417 }
3418 // Traverse up the injector tree until we find a potential match or until we know there
3419 // *isn't* a match.
3420 while (injectorIndex !== -1) {
3421 ngDevMode && assertNodeInjector(lView, injectorIndex);
3422 // Check the current injector. If it matches, see if it contains token.
3423 const tView = lView[TVIEW];
3424 ngDevMode &&
3425 assertTNodeForLView(tView.data[injectorIndex + 8 /* TNODE */], lView);
3426 if (bloomHasToken(bloomHash, injectorIndex, tView.data)) {
3427 // At this point, we have an injector which *may* contain the token, so we step through
3428 // the providers and directives associated with the injector's corresponding node to get
3429 // the instance.
3430 const instance = searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode);
3431 if (instance !== NOT_FOUND) {
3432 return instance;
3433 }
3434 }
3435 parentLocation = lView[injectorIndex + 8 /* PARENT */];
3436 if (parentLocation !== NO_PARENT_INJECTOR &&
3437 shouldSearchParent(flags, lView[TVIEW].data[injectorIndex + 8 /* TNODE */] === hostTElementNode) &&
3438 bloomHasToken(bloomHash, injectorIndex, lView)) {
3439 // The def wasn't found anywhere on this node, so it was a false positive.
3440 // Traverse up the tree and continue searching.
3441 previousTView = tView;
3442 injectorIndex = getParentInjectorIndex(parentLocation);
3443 lView = getParentInjectorView(parentLocation, lView);
3444 }
3445 else {
3446 // If we should not search parent OR If the ancestor bloom filter value does not have the
3447 // bit corresponding to the directive we can give up on traversing up to find the specific
3448 // injector.
3449 injectorIndex = -1;
3450 }
3451 }
3452 }
3453 }
3454 return lookupTokenUsingModuleInjector(lView, token, flags, notFoundValue);
3455}
3456const NOT_FOUND = {};
3457function createNodeInjector() {
3458 return new NodeInjector(getCurrentTNode(), getLView());
3459}
3460function searchTokensOnInjector(injectorIndex, lView, token, previousTView, flags, hostTElementNode) {
3461 const currentTView = lView[TVIEW];
3462 const tNode = currentTView.data[injectorIndex + 8 /* TNODE */];
3463 // First, we need to determine if view providers can be accessed by the starting element.
3464 // There are two possibilities
3465 const canAccessViewProviders = previousTView == null ?
3466 // 1) This is the first invocation `previousTView == null` which means that we are at the
3467 // `TNode` of where injector is starting to look. In such a case the only time we are allowed
3468 // to look into the ViewProviders is if:
3469 // - we are on a component
3470 // - AND the injector set `includeViewProviders` to true (implying that the token can see
3471 // ViewProviders because it is the Component or a Service which itself was declared in
3472 // ViewProviders)
3473 (isComponentHost(tNode) && includeViewProviders) :
3474 // 2) `previousTView != null` which means that we are now walking across the parent nodes.
3475 // In such a case we are only allowed to look into the ViewProviders if:
3476 // - We just crossed from child View to Parent View `previousTView != currentTView`
3477 // - AND the parent TNode is an Element.
3478 // This means that we just came from the Component's View and therefore are allowed to see
3479 // into the ViewProviders.
3480 (previousTView != currentTView && ((tNode.type & 3 /* AnyRNode */) !== 0));
3481 // This special case happens when there is a @host on the inject and when we are searching
3482 // on the host element node.
3483 const isHostSpecialCase = (flags & InjectFlags.Host) && hostTElementNode === tNode;
3484 const injectableIdx = locateDirectiveOrProvider(tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase);
3485 if (injectableIdx !== null) {
3486 return getNodeInjectable(lView, currentTView, injectableIdx, tNode);
3487 }
3488 else {
3489 return NOT_FOUND;
3490 }
3491}
3492/**
3493 * Searches for the given token among the node's directives and providers.
3494 *
3495 * @param tNode TNode on which directives are present.
3496 * @param tView The tView we are currently processing
3497 * @param token Provider token or type of a directive to look for.
3498 * @param canAccessViewProviders Whether view providers should be considered.
3499 * @param isHostSpecialCase Whether the host special case applies.
3500 * @returns Index of a found directive or provider, or null when none found.
3501 */
3502function locateDirectiveOrProvider(tNode, tView, token, canAccessViewProviders, isHostSpecialCase) {
3503 const nodeProviderIndexes = tNode.providerIndexes;
3504 const tInjectables = tView.data;
3505 const injectablesStart = nodeProviderIndexes & 1048575 /* ProvidersStartIndexMask */;
3506 const directivesStart = tNode.directiveStart;
3507 const directiveEnd = tNode.directiveEnd;
3508 const cptViewProvidersCount = nodeProviderIndexes >> 20 /* CptViewProvidersCountShift */;
3509 const startingIndex = canAccessViewProviders ? injectablesStart : injectablesStart + cptViewProvidersCount;
3510 // When the host special case applies, only the viewProviders and the component are visible
3511 const endIndex = isHostSpecialCase ? injectablesStart + cptViewProvidersCount : directiveEnd;
3512 for (let i = startingIndex; i < endIndex; i++) {
3513 const providerTokenOrDef = tInjectables[i];
3514 if (i < directivesStart && token === providerTokenOrDef ||
3515 i >= directivesStart && providerTokenOrDef.type === token) {
3516 return i;
3517 }
3518 }
3519 if (isHostSpecialCase) {
3520 const dirDef = tInjectables[directivesStart];
3521 if (dirDef && isComponentDef(dirDef) && dirDef.type === token) {
3522 return directivesStart;
3523 }
3524 }
3525 return null;
3526}
3527/**
3528 * Retrieve or instantiate the injectable from the `LView` at particular `index`.
3529 *
3530 * This function checks to see if the value has already been instantiated and if so returns the
3531 * cached `injectable`. Otherwise if it detects that the value is still a factory it
3532 * instantiates the `injectable` and caches the value.
3533 */
3534function getNodeInjectable(lView, tView, index, tNode) {
3535 let value = lView[index];
3536 const tData = tView.data;
3537 if (isFactory(value)) {
3538 const factory = value;
3539 if (factory.resolving) {
3540 throwCyclicDependencyError(stringifyForError(tData[index]));
3541 }
3542 const previousIncludeViewProviders = setIncludeViewProviders(factory.canSeeViewProviders);
3543 factory.resolving = true;
3544 const previousInjectImplementation = factory.injectImpl ? setInjectImplementation(factory.injectImpl) : null;
3545 const success = enterDI(lView, tNode, InjectFlags.Default);
3546 ngDevMode &&
3547 assertEqual(success, true, 'Because flags do not contain \`SkipSelf\' we expect this to always succeed.');
3548 try {
3549 value = lView[index] = factory.factory(undefined, tData, lView, tNode);
3550 // This code path is hit for both directives and providers.
3551 // For perf reasons, we want to avoid searching for hooks on providers.
3552 // It does no harm to try (the hooks just won't exist), but the extra
3553 // checks are unnecessary and this is a hot path. So we check to see
3554 // if the index of the dependency is in the directive range for this
3555 // tNode. If it's not, we know it's a provider and skip hook registration.
3556 if (tView.firstCreatePass && index >= tNode.directiveStart) {
3557 ngDevMode && assertDirectiveDef(tData[index]);
3558 registerPreOrderHooks(index, tData[index], tView);
3559 }
3560 }
3561 finally {
3562 previousInjectImplementation !== null &&
3563 setInjectImplementation(previousInjectImplementation);
3564 setIncludeViewProviders(previousIncludeViewProviders);
3565 factory.resolving = false;
3566 leaveDI();
3567 }
3568 }
3569 return value;
3570}
3571/**
3572 * Returns the bit in an injector's bloom filter that should be used to determine whether or not
3573 * the directive might be provided by the injector.
3574 *
3575 * When a directive is public, it is added to the bloom filter and given a unique ID that can be
3576 * retrieved on the Type. When the directive isn't public or the token is not a directive `null`
3577 * is returned as the node injector can not possibly provide that token.
3578 *
3579 * @param token the injection token
3580 * @returns the matching bit to check in the bloom filter or `null` if the token is not known.
3581 * When the returned value is negative then it represents special values such as `Injector`.
3582 */
3583function bloomHashBitOrFactory(token) {
3584 ngDevMode && assertDefined(token, 'token must be defined');
3585 if (typeof token === 'string') {
3586 return token.charCodeAt(0) || 0;
3587 }
3588 const tokenId =
3589 // First check with `hasOwnProperty` so we don't get an inherited ID.
3590 token.hasOwnProperty(NG_ELEMENT_ID) ? token[NG_ELEMENT_ID] : undefined;
3591 // Negative token IDs are used for special objects such as `Injector`
3592 if (typeof tokenId === 'number') {
3593 if (tokenId >= 0) {
3594 return tokenId & BLOOM_MASK;
3595 }
3596 else {
3597 ngDevMode &&
3598 assertEqual(tokenId, -1 /* Injector */, 'Expecting to get Special Injector Id');
3599 return createNodeInjector;
3600 }
3601 }
3602 else {
3603 return tokenId;
3604 }
3605}
3606function bloomHasToken(bloomHash, injectorIndex, injectorView) {
3607 // Create a mask that targets the specific bit associated with the directive we're looking for.
3608 // JS bit operations are 32 bits, so this will be a number between 2^0 and 2^31, corresponding
3609 // to bit positions 0 - 31 in a 32 bit integer.
3610 const mask = 1 << bloomHash;
3611 // Each bloom bucket in `injectorView` represents `BLOOM_BUCKET_BITS` number of bits of
3612 // `bloomHash`. Any bits in `bloomHash` beyond `BLOOM_BUCKET_BITS` indicate the bucket offset
3613 // that should be used.
3614 const value = injectorView[injectorIndex + (bloomHash >> BLOOM_BUCKET_BITS)];
3615 // If the bloom filter value has the bit corresponding to the directive's bloomBit flipped on,
3616 // this injector is a potential match.
3617 return !!(value & mask);
3618}
3619/** Returns true if flags prevent parent injector from being searched for tokens */
3620function shouldSearchParent(flags, isFirstHostTNode) {
3621 return !(flags & InjectFlags.Self) && !(flags & InjectFlags.Host && isFirstHostTNode);
3622}
3623class NodeInjector {
3624 constructor(_tNode, _lView) {
3625 this._tNode = _tNode;
3626 this._lView = _lView;
3627 }
3628 get(token, notFoundValue, flags) {
3629 return getOrCreateInjectable(this._tNode, this._lView, token, flags, notFoundValue);
3630 }
3631}
3632/**
3633 * @codeGenApi
3634 */
3635function ɵɵgetInheritedFactory(type) {
3636 return noSideEffects(() => {
3637 const ownConstructor = type.prototype.constructor;
3638 const ownFactory = ownConstructor[NG_FACTORY_DEF] || getFactoryOf(ownConstructor);
3639 const objectPrototype = Object.prototype;
3640 let parent = Object.getPrototypeOf(type.prototype).constructor;
3641 // Go up the prototype until we hit `Object`.
3642 while (parent && parent !== objectPrototype) {
3643 const factory = parent[NG_FACTORY_DEF] || getFactoryOf(parent);
3644 // If we hit something that has a factory and the factory isn't the same as the type,
3645 // we've found the inherited factory. Note the check that the factory isn't the type's
3646 // own factory is redundant in most cases, but if the user has custom decorators on the
3647 // class, this lookup will start one level down in the prototype chain, causing us to
3648 // find the own factory first and potentially triggering an infinite loop downstream.
3649 if (factory && factory !== ownFactory) {
3650 return factory;
3651 }
3652 parent = Object.getPrototypeOf(parent);
3653 }
3654 // There is no factory defined. Either this was improper usage of inheritance
3655 // (no Angular decorator on the superclass) or there is no constructor at all
3656 // in the inheritance chain. Since the two cases cannot be distinguished, the
3657 // latter has to be assumed.
3658 return t => new t();
3659 });
3660}
3661function getFactoryOf(type) {
3662 if (isForwardRef(type)) {
3663 return () => {
3664 const factory = getFactoryOf(resolveForwardRef(type));
3665 return factory && factory();
3666 };
3667 }
3668 return getFactoryDef(type);
3669}
3670
3671/**
3672 * @license
3673 * Copyright Google LLC All Rights Reserved.
3674 *
3675 * Use of this source code is governed by an MIT-style license that can be
3676 * found in the LICENSE file at https://angular.io/license
3677 */
3678/**
3679 * Facade for the attribute injection from DI.
3680 *
3681 * @codeGenApi
3682 */
3683function ɵɵinjectAttribute(attrNameToInject) {
3684 return injectAttributeImpl(getCurrentTNode(), attrNameToInject);
3685}
3686
3687/**
3688 * @license
3689 * Copyright Google LLC All Rights Reserved.
3690 *
3691 * Use of this source code is governed by an MIT-style license that can be
3692 * found in the LICENSE file at https://angular.io/license
3693 */
3694const ANNOTATIONS = '__annotations__';
3695const PARAMETERS = '__parameters__';
3696const PROP_METADATA = '__prop__metadata__';
3697/**
3698 * @suppress {globalThis}
3699 */
3700function makeDecorator(name, props, parentClass, additionalProcessing, typeFn) {
3701 return noSideEffects(() => {
3702 const metaCtor = makeMetadataCtor(props);
3703 function DecoratorFactory(...args) {
3704 if (this instanceof DecoratorFactory) {
3705 metaCtor.call(this, ...args);
3706 return this;
3707 }
3708 const annotationInstance = new DecoratorFactory(...args);
3709 return function TypeDecorator(cls) {
3710 if (typeFn)
3711 typeFn(cls, ...args);
3712 // Use of Object.defineProperty is important since it creates non-enumerable property which
3713 // prevents the property is copied during subclassing.
3714 const annotations = cls.hasOwnProperty(ANNOTATIONS) ?
3715 cls[ANNOTATIONS] :
3716 Object.defineProperty(cls, ANNOTATIONS, { value: [] })[ANNOTATIONS];
3717 annotations.push(annotationInstance);
3718 if (additionalProcessing)
3719 additionalProcessing(cls);
3720 return cls;
3721 };
3722 }
3723 if (parentClass) {
3724 DecoratorFactory.prototype = Object.create(parentClass.prototype);
3725 }
3726 DecoratorFactory.prototype.ngMetadataName = name;
3727 DecoratorFactory.annotationCls = DecoratorFactory;
3728 return DecoratorFactory;
3729 });
3730}
3731function makeMetadataCtor(props) {
3732 return function ctor(...args) {
3733 if (props) {
3734 const values = props(...args);
3735 for (const propName in values) {
3736 this[propName] = values[propName];
3737 }
3738 }
3739 };
3740}
3741function makeParamDecorator(name, props, parentClass) {
3742 return noSideEffects(() => {
3743 const metaCtor = makeMetadataCtor(props);
3744 function ParamDecoratorFactory(...args) {
3745 if (this instanceof ParamDecoratorFactory) {
3746 metaCtor.apply(this, args);
3747 return this;
3748 }
3749 const annotationInstance = new ParamDecoratorFactory(...args);
3750 ParamDecorator.annotation = annotationInstance;
3751 return ParamDecorator;
3752 function ParamDecorator(cls, unusedKey, index) {
3753 // Use of Object.defineProperty is important since it creates non-enumerable property which
3754 // prevents the property is copied during subclassing.
3755 const parameters = cls.hasOwnProperty(PARAMETERS) ?
3756 cls[PARAMETERS] :
3757 Object.defineProperty(cls, PARAMETERS, { value: [] })[PARAMETERS];
3758 // there might be gaps if some in between parameters do not have annotations.
3759 // we pad with nulls.
3760 while (parameters.length <= index) {
3761 parameters.push(null);
3762 }
3763 (parameters[index] = parameters[index] || []).push(annotationInstance);
3764 return cls;
3765 }
3766 }
3767 if (parentClass) {
3768 ParamDecoratorFactory.prototype = Object.create(parentClass.prototype);
3769 }
3770 ParamDecoratorFactory.prototype.ngMetadataName = name;
3771 ParamDecoratorFactory.annotationCls = ParamDecoratorFactory;
3772 return ParamDecoratorFactory;
3773 });
3774}
3775function makePropDecorator(name, props, parentClass, additionalProcessing) {
3776 return noSideEffects(() => {
3777 const metaCtor = makeMetadataCtor(props);
3778 function PropDecoratorFactory(...args) {
3779 if (this instanceof PropDecoratorFactory) {
3780 metaCtor.apply(this, args);
3781 return this;
3782 }
3783 const decoratorInstance = new PropDecoratorFactory(...args);
3784 function PropDecorator(target, name) {
3785 const constructor = target.constructor;
3786 // Use of Object.defineProperty is important because it creates a non-enumerable property
3787 // which prevents the property from being copied during subclassing.
3788 const meta = constructor.hasOwnProperty(PROP_METADATA) ?
3789 constructor[PROP_METADATA] :
3790 Object.defineProperty(constructor, PROP_METADATA, { value: {} })[PROP_METADATA];
3791 meta[name] = meta.hasOwnProperty(name) && meta[name] || [];
3792 meta[name].unshift(decoratorInstance);
3793 if (additionalProcessing)
3794 additionalProcessing(target, name, ...args);
3795 }
3796 return PropDecorator;
3797 }
3798 if (parentClass) {
3799 PropDecoratorFactory.prototype = Object.create(parentClass.prototype);
3800 }
3801 PropDecoratorFactory.prototype.ngMetadataName = name;
3802 PropDecoratorFactory.annotationCls = PropDecoratorFactory;
3803 return PropDecoratorFactory;
3804 });
3805}
3806
3807/**
3808 * @license
3809 * Copyright Google LLC All Rights Reserved.
3810 *
3811 * Use of this source code is governed by an MIT-style license that can be
3812 * found in the LICENSE file at https://angular.io/license
3813 */
3814function CREATE_ATTRIBUTE_DECORATOR__PRE_R3__() {
3815 return makeParamDecorator('Attribute', (attributeName) => ({ attributeName }));
3816}
3817function CREATE_ATTRIBUTE_DECORATOR__POST_R3__() {
3818 return makeParamDecorator('Attribute', (attributeName) => ({ attributeName, __NG_ELEMENT_ID__: () => ɵɵinjectAttribute(attributeName) }));
3819}
3820const CREATE_ATTRIBUTE_DECORATOR_IMPL = CREATE_ATTRIBUTE_DECORATOR__POST_R3__;
3821/**
3822 * Attribute decorator and metadata.
3823 *
3824 * @Annotation
3825 * @publicApi
3826 */
3827const Attribute = CREATE_ATTRIBUTE_DECORATOR_IMPL();
3828
3829/**
3830 * @license
3831 * Copyright Google LLC All Rights Reserved.
3832 *
3833 * Use of this source code is governed by an MIT-style license that can be
3834 * found in the LICENSE file at https://angular.io/license
3835 */
3836/**
3837 * Creates a token that can be used in a DI Provider.
3838 *
3839 * Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a
3840 * runtime representation) such as when injecting an interface, callable type, array or
3841 * parameterized type.
3842 *
3843 * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
3844 * the `Injector`. This provides an additional level of type safety.
3845 *
3846 * ```
3847 * interface MyInterface {...}
3848 * const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
3849 * // myInterface is inferred to be MyInterface.
3850 * ```
3851 *
3852 * When creating an `InjectionToken`, you can optionally specify a factory function which returns
3853 * (possibly by creating) a default value of the parameterized type `T`. This sets up the
3854 * `InjectionToken` using this factory as a provider as if it was defined explicitly in the
3855 * application's root injector. If the factory function, which takes zero arguments, needs to inject
3856 * dependencies, it can do so using the `inject` function.
3857 * As you can see in the Tree-shakable InjectionToken example below.
3858 *
3859 * Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
3860 * overrides the above behavior and marks the token as belonging to a particular `@NgModule`. As
3861 * mentioned above, `'root'` is the default value for `providedIn`.
3862 *
3863 * @usageNotes
3864 * ### Basic Examples
3865 *
3866 * ### Plain InjectionToken
3867 *
3868 * {@example core/di/ts/injector_spec.ts region='InjectionToken'}
3869 *
3870 * ### Tree-shakable InjectionToken
3871 *
3872 * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
3873 *
3874 *
3875 * @publicApi
3876 */
3877class InjectionToken {
3878 /**
3879 * @param _desc Description for the token,
3880 * used only for debugging purposes,
3881 * it should but does not need to be unique
3882 * @param options Options for the token's usage, as described above
3883 */
3884 constructor(_desc, options) {
3885 this._desc = _desc;
3886 /** @internal */
3887 this.ngMetadataName = 'InjectionToken';
3888 this.ɵprov = undefined;
3889 if (typeof options == 'number') {
3890 (typeof ngDevMode === 'undefined' || ngDevMode) &&
3891 assertLessThan(options, 0, 'Only negative numbers are supported here');
3892 // This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
3893 // See `InjectorMarkers`
3894 this.__NG_ELEMENT_ID__ = options;
3895 }
3896 else if (options !== undefined) {
3897 this.ɵprov = ɵɵdefineInjectable({
3898 token: this,
3899 providedIn: options.providedIn || 'root',
3900 factory: options.factory,
3901 });
3902 }
3903 }
3904 toString() {
3905 return `InjectionToken ${this._desc}`;
3906 }
3907}
3908
3909/**
3910 * @license
3911 * Copyright Google LLC All Rights Reserved.
3912 *
3913 * Use of this source code is governed by an MIT-style license that can be
3914 * found in the LICENSE file at https://angular.io/license
3915 */
3916/**
3917 * A DI token that you can use to create a virtual [provider](guide/glossary#provider)
3918 * that will populate the `entryComponents` field of components and NgModules
3919 * based on its `useValue` property value.
3920 * All components that are referenced in the `useValue` value (either directly
3921 * or in a nested array or map) are added to the `entryComponents` property.
3922 *
3923 * @usageNotes
3924 *
3925 * The following example shows how the router can populate the `entryComponents`
3926 * field of an NgModule based on a router configuration that refers
3927 * to components.
3928 *
3929 * ```typescript
3930 * // helper function inside the router
3931 * function provideRoutes(routes) {
3932 * return [
3933 * {provide: ROUTES, useValue: routes},
3934 * {provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: routes, multi: true}
3935 * ];
3936 * }
3937 *
3938 * // user code
3939 * let routes = [
3940 * {path: '/root', component: RootComp},
3941 * {path: '/teams', component: TeamsComp}
3942 * ];
3943 *
3944 * @NgModule({
3945 * providers: [provideRoutes(routes)]
3946 * })
3947 * class ModuleWithRoutes {}
3948 * ```
3949 *
3950 * @publicApi
3951 * @deprecated Since 9.0.0. With Ivy, this property is no longer necessary.
3952 */
3953const ANALYZE_FOR_ENTRY_COMPONENTS = new InjectionToken('AnalyzeForEntryComponents');
3954// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
3955// explicitly set.
3956const emitDistinctChangesOnlyDefaultValue = true;
3957/**
3958 * Base class for query metadata.
3959 *
3960 * @see `ContentChildren`.
3961 * @see `ContentChild`.
3962 * @see `ViewChildren`.
3963 * @see `ViewChild`.
3964 *
3965 * @publicApi
3966 */
3967class Query {
3968}
3969/**
3970 * ContentChildren decorator and metadata.
3971 *
3972 *
3973 * @Annotation
3974 * @publicApi
3975 */
3976const ContentChildren = makePropDecorator('ContentChildren', (selector, data = {}) => (Object.assign({ selector, first: false, isViewQuery: false, descendants: false, emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue }, data)), Query);
3977/**
3978 * ContentChild decorator and metadata.
3979 *
3980 *
3981 * @Annotation
3982 *
3983 * @publicApi
3984 */
3985const ContentChild = makePropDecorator('ContentChild', (selector, data = {}) => (Object.assign({ selector, first: true, isViewQuery: false, descendants: true }, data)), Query);
3986/**
3987 * ViewChildren decorator and metadata.
3988 *
3989 * @Annotation
3990 * @publicApi
3991 */
3992const ViewChildren = makePropDecorator('ViewChildren', (selector, data = {}) => (Object.assign({ selector, first: false, isViewQuery: true, descendants: true, emitDistinctChangesOnly: emitDistinctChangesOnlyDefaultValue }, data)), Query);
3993/**
3994 * ViewChild decorator and metadata.
3995 *
3996 * @Annotation
3997 * @publicApi
3998 */
3999const ViewChild = makePropDecorator('ViewChild', (selector, data) => (Object.assign({ selector, first: true, isViewQuery: true, descendants: true }, data)), Query);
4000
4001/**
4002 * @license
4003 * Copyright Google LLC All Rights Reserved.
4004 *
4005 * Use of this source code is governed by an MIT-style license that can be
4006 * found in the LICENSE file at https://angular.io/license
4007 */
4008var FactoryTarget;
4009(function (FactoryTarget) {
4010 FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
4011 FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
4012 FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
4013 FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
4014 FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
4015})(FactoryTarget || (FactoryTarget = {}));
4016var ViewEncapsulation;
4017(function (ViewEncapsulation) {
4018 ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated";
4019 // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.
4020 ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
4021 ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
4022})(ViewEncapsulation || (ViewEncapsulation = {}));
4023
4024/**
4025 * @license
4026 * Copyright Google LLC All Rights Reserved.
4027 *
4028 * Use of this source code is governed by an MIT-style license that can be
4029 * found in the LICENSE file at https://angular.io/license
4030 */
4031function getCompilerFacade(request) {
4032 const globalNg = _global['ng'];
4033 if (globalNg && globalNg.ɵcompilerFacade) {
4034 return globalNg.ɵcompilerFacade;
4035 }
4036 if (typeof ngDevMode === 'undefined' || ngDevMode) {
4037 // Log the type as an error so that a developer can easily navigate to the type from the
4038 // console.
4039 console.error(`JIT compilation failed for ${request.kind}`, request.type);
4040 let message = `The ${request.kind} '${request
4041 .type.name}' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available.\n\n`;
4042 if (request.usage === 1 /* PartialDeclaration */) {
4043 message += `The ${request.kind} is part of a library that has been partially compiled.\n`;
4044 message +=
4045 `However, the Angular Linker has not processed the library such that JIT compilation is used as fallback.\n`;
4046 message += '\n';
4047 message +=
4048 `Ideally, the library is processed using the Angular Linker to become fully AOT compiled.\n`;
4049 }
4050 else {
4051 message +=
4052 `JIT compilation is discouraged for production use-cases! Consider using AOT mode instead.\n`;
4053 }
4054 message +=
4055 `Alternatively, the JIT compiler should be loaded by bootstrapping using '@angular/platform-browser-dynamic' or '@angular/platform-server',\n`;
4056 message +=
4057 `or manually provide the compiler with 'import "@angular/compiler";' before bootstrapping.`;
4058 throw new Error(message);
4059 }
4060 else {
4061 throw new Error('JIT compiler unavailable');
4062 }
4063}
4064
4065/**
4066 * @license
4067 * Copyright Google LLC All Rights Reserved.
4068 *
4069 * Use of this source code is governed by an MIT-style license that can be
4070 * found in the LICENSE file at https://angular.io/license
4071 */
4072/**
4073 * @description
4074 *
4075 * Represents a type that a Component or other object is instances of.
4076 *
4077 * An example of a `Type` is `MyCustomComponent` class, which in JavaScript is represented by
4078 * the `MyCustomComponent` constructor function.
4079 *
4080 * @publicApi
4081 */
4082const Type = Function;
4083function isType(v) {
4084 return typeof v === 'function';
4085}
4086
4087/**
4088 * @license
4089 * Copyright Google LLC All Rights Reserved.
4090 *
4091 * Use of this source code is governed by an MIT-style license that can be
4092 * found in the LICENSE file at https://angular.io/license
4093 */
4094/**
4095 * Equivalent to ES6 spread, add each item to an array.
4096 *
4097 * @param items The items to add
4098 * @param arr The array to which you want to add the items
4099 */
4100function addAllToArray(items, arr) {
4101 for (let i = 0; i < items.length; i++) {
4102 arr.push(items[i]);
4103 }
4104}
4105/**
4106 * Determines if the contents of two arrays is identical
4107 *
4108 * @param a first array
4109 * @param b second array
4110 * @param identityAccessor Optional function for extracting stable object identity from a value in
4111 * the array.
4112 */
4113function arrayEquals(a, b, identityAccessor) {
4114 if (a.length !== b.length)
4115 return false;
4116 for (let i = 0; i < a.length; i++) {
4117 let valueA = a[i];
4118 let valueB = b[i];
4119 if (identityAccessor) {
4120 valueA = identityAccessor(valueA);
4121 valueB = identityAccessor(valueB);
4122 }
4123 if (valueB !== valueA) {
4124 return false;
4125 }
4126 }
4127 return true;
4128}
4129/**
4130 * Flattens an array.
4131 */
4132function flatten(list, dst) {
4133 if (dst === undefined)
4134 dst = list;
4135 for (let i = 0; i < list.length; i++) {
4136 let item = list[i];
4137 if (Array.isArray(item)) {
4138 // we need to inline it.
4139 if (dst === list) {
4140 // Our assumption that the list was already flat was wrong and
4141 // we need to clone flat since we need to write to it.
4142 dst = list.slice(0, i);
4143 }
4144 flatten(item, dst);
4145 }
4146 else if (dst !== list) {
4147 dst.push(item);
4148 }
4149 }
4150 return dst;
4151}
4152function deepForEach(input, fn) {
4153 input.forEach(value => Array.isArray(value) ? deepForEach(value, fn) : fn(value));
4154}
4155function addToArray(arr, index, value) {
4156 // perf: array.push is faster than array.splice!
4157 if (index >= arr.length) {
4158 arr.push(value);
4159 }
4160 else {
4161 arr.splice(index, 0, value);
4162 }
4163}
4164function removeFromArray(arr, index) {
4165 // perf: array.pop is faster than array.splice!
4166 if (index >= arr.length - 1) {
4167 return arr.pop();
4168 }
4169 else {
4170 return arr.splice(index, 1)[0];
4171 }
4172}
4173function newArray(size, value) {
4174 const list = [];
4175 for (let i = 0; i < size; i++) {
4176 list.push(value);
4177 }
4178 return list;
4179}
4180/**
4181 * Remove item from array (Same as `Array.splice()` but faster.)
4182 *
4183 * `Array.splice()` is not as fast because it has to allocate an array for the elements which were
4184 * removed. This causes memory pressure and slows down code when most of the time we don't
4185 * care about the deleted items array.
4186 *
4187 * https://jsperf.com/fast-array-splice (About 20x faster)
4188 *
4189 * @param array Array to splice
4190 * @param index Index of element in array to remove.
4191 * @param count Number of items to remove.
4192 */
4193function arraySplice(array, index, count) {
4194 const length = array.length - count;
4195 while (index < length) {
4196 array[index] = array[index + count];
4197 index++;
4198 }
4199 while (count--) {
4200 array.pop(); // shrink the array
4201 }
4202}
4203/**
4204 * Same as `Array.splice(index, 0, value)` but faster.
4205 *
4206 * `Array.splice()` is not fast because it has to allocate an array for the elements which were
4207 * removed. This causes memory pressure and slows down code when most of the time we don't
4208 * care about the deleted items array.
4209 *
4210 * @param array Array to splice.
4211 * @param index Index in array where the `value` should be added.
4212 * @param value Value to add to array.
4213 */
4214function arrayInsert(array, index, value) {
4215 ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.');
4216 let end = array.length;
4217 while (end > index) {
4218 const previousEnd = end - 1;
4219 array[end] = array[previousEnd];
4220 end = previousEnd;
4221 }
4222 array[index] = value;
4223}
4224/**
4225 * Same as `Array.splice2(index, 0, value1, value2)` 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 value1 Value to add to array.
4234 * @param value2 Value to add to array.
4235 */
4236function arrayInsert2(array, index, value1, value2) {
4237 ngDevMode && assertLessThanOrEqual(index, array.length, 'Can\'t insert past array end.');
4238 let end = array.length;
4239 if (end == index) {
4240 // inserting at the end.
4241 array.push(value1, value2);
4242 }
4243 else if (end === 1) {
4244 // corner case when we have less items in array than we have items to insert.
4245 array.push(value2, array[0]);
4246 array[0] = value1;
4247 }
4248 else {
4249 end--;
4250 array.push(array[end - 1], array[end]);
4251 while (end > index) {
4252 const previousEnd = end - 2;
4253 array[end] = array[previousEnd];
4254 end--;
4255 }
4256 array[index] = value1;
4257 array[index + 1] = value2;
4258 }
4259}
4260/**
4261 * Insert a `value` into an `array` so that the array remains sorted.
4262 *
4263 * NOTE:
4264 * - Duplicates are not allowed, and are ignored.
4265 * - This uses binary search algorithm for fast inserts.
4266 *
4267 * @param array A sorted array to insert into.
4268 * @param value The value to insert.
4269 * @returns index of the inserted value.
4270 */
4271function arrayInsertSorted(array, value) {
4272 let index = arrayIndexOfSorted(array, value);
4273 if (index < 0) {
4274 // if we did not find it insert it.
4275 index = ~index;
4276 arrayInsert(array, index, value);
4277 }
4278 return index;
4279}
4280/**
4281 * Remove `value` from a sorted `array`.
4282 *
4283 * NOTE:
4284 * - This uses binary search algorithm for fast removals.
4285 *
4286 * @param array A sorted array to remove from.
4287 * @param value The value to remove.
4288 * @returns index of the removed value.
4289 * - positive index if value found and removed.
4290 * - negative index if value not found. (`~index` to get the value where it should have been
4291 * inserted)
4292 */
4293function arrayRemoveSorted(array, value) {
4294 const index = arrayIndexOfSorted(array, value);
4295 if (index >= 0) {
4296 arraySplice(array, index, 1);
4297 }
4298 return index;
4299}
4300/**
4301 * Get an index of an `value` in a sorted `array`.
4302 *
4303 * NOTE:
4304 * - This uses binary search algorithm for fast removals.
4305 *
4306 * @param array A sorted array to binary search.
4307 * @param value The value to look for.
4308 * @returns index of the value.
4309 * - positive index if value found.
4310 * - negative index if value not found. (`~index` to get the value where it should have been
4311 * located)
4312 */
4313function arrayIndexOfSorted(array, value) {
4314 return _arrayIndexOfSorted(array, value, 0);
4315}
4316/**
4317 * Set a `value` for a `key`.
4318 *
4319 * @param keyValueArray to modify.
4320 * @param key The key to locate or create.
4321 * @param value The value to set for a `key`.
4322 * @returns index (always even) of where the value vas set.
4323 */
4324function keyValueArraySet(keyValueArray, key, value) {
4325 let index = keyValueArrayIndexOf(keyValueArray, key);
4326 if (index >= 0) {
4327 // if we found it set it.
4328 keyValueArray[index | 1] = value;
4329 }
4330 else {
4331 index = ~index;
4332 arrayInsert2(keyValueArray, index, key, value);
4333 }
4334 return index;
4335}
4336/**
4337 * Retrieve a `value` for a `key` (on `undefined` if not found.)
4338 *
4339 * @param keyValueArray to search.
4340 * @param key The key to locate.
4341 * @return The `value` stored at the `key` location or `undefined if not found.
4342 */
4343function keyValueArrayGet(keyValueArray, key) {
4344 const index = keyValueArrayIndexOf(keyValueArray, key);
4345 if (index >= 0) {
4346 // if we found it retrieve it.
4347 return keyValueArray[index | 1];
4348 }
4349 return undefined;
4350}
4351/**
4352 * Retrieve a `key` index value in the array or `-1` if not found.
4353 *
4354 * @param keyValueArray to search.
4355 * @param key The key to locate.
4356 * @returns index of where the key is (or should have been.)
4357 * - positive (even) index if key found.
4358 * - negative index if key not found. (`~index` (even) to get the index where it should have
4359 * been inserted.)
4360 */
4361function keyValueArrayIndexOf(keyValueArray, key) {
4362 return _arrayIndexOfSorted(keyValueArray, key, 1);
4363}
4364/**
4365 * Delete a `key` (and `value`) from the `KeyValueArray`.
4366 *
4367 * @param keyValueArray to modify.
4368 * @param key The key to locate or delete (if exist).
4369 * @returns index of where the key was (or should have been.)
4370 * - positive (even) index if key found and deleted.
4371 * - negative index if key not found. (`~index` (even) to get the index where it should have
4372 * been.)
4373 */
4374function keyValueArrayDelete(keyValueArray, key) {
4375 const index = keyValueArrayIndexOf(keyValueArray, key);
4376 if (index >= 0) {
4377 // if we found it remove it.
4378 arraySplice(keyValueArray, index, 2);
4379 }
4380 return index;
4381}
4382/**
4383 * INTERNAL: Get an index of an `value` in a sorted `array` by grouping search by `shift`.
4384 *
4385 * NOTE:
4386 * - This uses binary search algorithm for fast removals.
4387 *
4388 * @param array A sorted array to binary search.
4389 * @param value The value to look for.
4390 * @param shift grouping shift.
4391 * - `0` means look at every location
4392 * - `1` means only look at every other (even) location (the odd locations are to be ignored as
4393 * they are values.)
4394 * @returns index of the value.
4395 * - positive index if value found.
4396 * - negative index if value not found. (`~index` to get the value where it should have been
4397 * inserted)
4398 */
4399function _arrayIndexOfSorted(array, value, shift) {
4400 ngDevMode && assertEqual(Array.isArray(array), true, 'Expecting an array');
4401 let start = 0;
4402 let end = array.length >> shift;
4403 while (end !== start) {
4404 const middle = start + ((end - start) >> 1); // find the middle.
4405 const current = array[middle << shift];
4406 if (value === current) {
4407 return (middle << shift);
4408 }
4409 else if (current > value) {
4410 end = middle;
4411 }
4412 else {
4413 start = middle + 1; // We already searched middle so make it non-inclusive by adding 1
4414 }
4415 }
4416 return ~(end << shift);
4417}
4418
4419/**
4420 * @license
4421 * Copyright Google LLC All Rights Reserved.
4422 *
4423 * Use of this source code is governed by an MIT-style license that can be
4424 * found in the LICENSE file at https://angular.io/license
4425 */
4426/*
4427 * #########################
4428 * Attention: These Regular expressions have to hold even if the code is minified!
4429 * ##########################
4430 */
4431/**
4432 * Regular expression that detects pass-through constructors for ES5 output. This Regex
4433 * intends to capture the common delegation pattern emitted by TypeScript and Babel. Also
4434 * it intends to capture the pattern where existing constructors have been downleveled from
4435 * ES2015 to ES5 using TypeScript w/ downlevel iteration. e.g.
4436 *
4437 * ```
4438 * function MyClass() {
4439 * var _this = _super.apply(this, arguments) || this;
4440 * ```
4441 *
4442 * downleveled to ES5 with `downlevelIteration` for TypeScript < 4.2:
4443 * ```
4444 * function MyClass() {
4445 * var _this = _super.apply(this, __spread(arguments)) || this;
4446 * ```
4447 *
4448 * or downleveled to ES5 with `downlevelIteration` for TypeScript >= 4.2:
4449 * ```
4450 * function MyClass() {
4451 * var _this = _super.apply(this, __spreadArray([], __read(arguments), false)) || this;
4452 * ```
4453 *
4454 * More details can be found in: https://github.com/angular/angular/issues/38453.
4455 */
4456const ES5_DELEGATE_CTOR = /^function\s+\S+\(\)\s*{[\s\S]+\.apply\(this,\s*(arguments|(?:[^()]+\(\[\],)?[^()]+\(arguments\).*)\)/;
4457/** Regular expression that detects ES2015 classes which extend from other classes. */
4458const ES2015_INHERITED_CLASS = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{/;
4459/**
4460 * Regular expression that detects ES2015 classes which extend from other classes and
4461 * have an explicit constructor defined.
4462 */
4463const ES2015_INHERITED_CLASS_WITH_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(/;
4464/**
4465 * Regular expression that detects ES2015 classes which extend from other classes
4466 * and inherit a constructor.
4467 */
4468const ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR = /^class\s+[A-Za-z\d$_]*\s*extends\s+[^{]+{[\s\S]*constructor\s*\(\)\s*{\s*super\(\.\.\.arguments\)/;
4469/**
4470 * Determine whether a stringified type is a class which delegates its constructor
4471 * to its parent.
4472 *
4473 * This is not trivial since compiled code can actually contain a constructor function
4474 * even if the original source code did not. For instance, when the child class contains
4475 * an initialized instance property.
4476 */
4477function isDelegateCtor(typeStr) {
4478 return ES5_DELEGATE_CTOR.test(typeStr) ||
4479 ES2015_INHERITED_CLASS_WITH_DELEGATE_CTOR.test(typeStr) ||
4480 (ES2015_INHERITED_CLASS.test(typeStr) && !ES2015_INHERITED_CLASS_WITH_CTOR.test(typeStr));
4481}
4482class ReflectionCapabilities {
4483 constructor(reflect) {
4484 this._reflect = reflect || _global['Reflect'];
4485 }
4486 isReflectionEnabled() {
4487 return true;
4488 }
4489 factory(t) {
4490 return (...args) => new t(...args);
4491 }
4492 /** @internal */
4493 _zipTypesAndAnnotations(paramTypes, paramAnnotations) {
4494 let result;
4495 if (typeof paramTypes === 'undefined') {
4496 result = newArray(paramAnnotations.length);
4497 }
4498 else {
4499 result = newArray(paramTypes.length);
4500 }
4501 for (let i = 0; i < result.length; i++) {
4502 // TS outputs Object for parameters without types, while Traceur omits
4503 // the annotations. For now we preserve the Traceur behavior to aid
4504 // migration, but this can be revisited.
4505 if (typeof paramTypes === 'undefined') {
4506 result[i] = [];
4507 }
4508 else if (paramTypes[i] && paramTypes[i] != Object) {
4509 result[i] = [paramTypes[i]];
4510 }
4511 else {
4512 result[i] = [];
4513 }
4514 if (paramAnnotations && paramAnnotations[i] != null) {
4515 result[i] = result[i].concat(paramAnnotations[i]);
4516 }
4517 }
4518 return result;
4519 }
4520 _ownParameters(type, parentCtor) {
4521 const typeStr = type.toString();
4522 // If we have no decorators, we only have function.length as metadata.
4523 // In that case, to detect whether a child class declared an own constructor or not,
4524 // we need to look inside of that constructor to check whether it is
4525 // just calling the parent.
4526 // This also helps to work around for https://github.com/Microsoft/TypeScript/issues/12439
4527 // that sets 'design:paramtypes' to []
4528 // if a class inherits from another class but has no ctor declared itself.
4529 if (isDelegateCtor(typeStr)) {
4530 return null;
4531 }
4532 // Prefer the direct API.
4533 if (type.parameters && type.parameters !== parentCtor.parameters) {
4534 return type.parameters;
4535 }
4536 // API of tsickle for lowering decorators to properties on the class.
4537 const tsickleCtorParams = type.ctorParameters;
4538 if (tsickleCtorParams && tsickleCtorParams !== parentCtor.ctorParameters) {
4539 // Newer tsickle uses a function closure
4540 // Retain the non-function case for compatibility with older tsickle
4541 const ctorParameters = typeof tsickleCtorParams === 'function' ? tsickleCtorParams() : tsickleCtorParams;
4542 const paramTypes = ctorParameters.map((ctorParam) => ctorParam && ctorParam.type);
4543 const paramAnnotations = ctorParameters.map((ctorParam) => ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators));
4544 return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
4545 }
4546 // API for metadata created by invoking the decorators.
4547 const paramAnnotations = type.hasOwnProperty(PARAMETERS) && type[PARAMETERS];
4548 const paramTypes = this._reflect && this._reflect.getOwnMetadata &&
4549 this._reflect.getOwnMetadata('design:paramtypes', type);
4550 if (paramTypes || paramAnnotations) {
4551 return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
4552 }
4553 // If a class has no decorators, at least create metadata
4554 // based on function.length.
4555 // Note: We know that this is a real constructor as we checked
4556 // the content of the constructor above.
4557 return newArray(type.length);
4558 }
4559 parameters(type) {
4560 // Note: only report metadata if we have at least one class decorator
4561 // to stay in sync with the static reflector.
4562 if (!isType(type)) {
4563 return [];
4564 }
4565 const parentCtor = getParentCtor(type);
4566 let parameters = this._ownParameters(type, parentCtor);
4567 if (!parameters && parentCtor !== Object) {
4568 parameters = this.parameters(parentCtor);
4569 }
4570 return parameters || [];
4571 }
4572 _ownAnnotations(typeOrFunc, parentCtor) {
4573 // Prefer the direct API.
4574 if (typeOrFunc.annotations && typeOrFunc.annotations !== parentCtor.annotations) {
4575 let annotations = typeOrFunc.annotations;
4576 if (typeof annotations === 'function' && annotations.annotations) {
4577 annotations = annotations.annotations;
4578 }
4579 return annotations;
4580 }
4581 // API of tsickle for lowering decorators to properties on the class.
4582 if (typeOrFunc.decorators && typeOrFunc.decorators !== parentCtor.decorators) {
4583 return convertTsickleDecoratorIntoMetadata(typeOrFunc.decorators);
4584 }
4585 // API for metadata created by invoking the decorators.
4586 if (typeOrFunc.hasOwnProperty(ANNOTATIONS)) {
4587 return typeOrFunc[ANNOTATIONS];
4588 }
4589 return null;
4590 }
4591 annotations(typeOrFunc) {
4592 if (!isType(typeOrFunc)) {
4593 return [];
4594 }
4595 const parentCtor = getParentCtor(typeOrFunc);
4596 const ownAnnotations = this._ownAnnotations(typeOrFunc, parentCtor) || [];
4597 const parentAnnotations = parentCtor !== Object ? this.annotations(parentCtor) : [];
4598 return parentAnnotations.concat(ownAnnotations);
4599 }
4600 _ownPropMetadata(typeOrFunc, parentCtor) {
4601 // Prefer the direct API.
4602 if (typeOrFunc.propMetadata &&
4603 typeOrFunc.propMetadata !== parentCtor.propMetadata) {
4604 let propMetadata = typeOrFunc.propMetadata;
4605 if (typeof propMetadata === 'function' && propMetadata.propMetadata) {
4606 propMetadata = propMetadata.propMetadata;
4607 }
4608 return propMetadata;
4609 }
4610 // API of tsickle for lowering decorators to properties on the class.
4611 if (typeOrFunc.propDecorators &&
4612 typeOrFunc.propDecorators !== parentCtor.propDecorators) {
4613 const propDecorators = typeOrFunc.propDecorators;
4614 const propMetadata = {};
4615 Object.keys(propDecorators).forEach(prop => {
4616 propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]);
4617 });
4618 return propMetadata;
4619 }
4620 // API for metadata created by invoking the decorators.
4621 if (typeOrFunc.hasOwnProperty(PROP_METADATA)) {
4622 return typeOrFunc[PROP_METADATA];
4623 }
4624 return null;
4625 }
4626 propMetadata(typeOrFunc) {
4627 if (!isType(typeOrFunc)) {
4628 return {};
4629 }
4630 const parentCtor = getParentCtor(typeOrFunc);
4631 const propMetadata = {};
4632 if (parentCtor !== Object) {
4633 const parentPropMetadata = this.propMetadata(parentCtor);
4634 Object.keys(parentPropMetadata).forEach((propName) => {
4635 propMetadata[propName] = parentPropMetadata[propName];
4636 });
4637 }
4638 const ownPropMetadata = this._ownPropMetadata(typeOrFunc, parentCtor);
4639 if (ownPropMetadata) {
4640 Object.keys(ownPropMetadata).forEach((propName) => {
4641 const decorators = [];
4642 if (propMetadata.hasOwnProperty(propName)) {
4643 decorators.push(...propMetadata[propName]);
4644 }
4645 decorators.push(...ownPropMetadata[propName]);
4646 propMetadata[propName] = decorators;
4647 });
4648 }
4649 return propMetadata;
4650 }
4651 ownPropMetadata(typeOrFunc) {
4652 if (!isType(typeOrFunc)) {
4653 return {};
4654 }
4655 return this._ownPropMetadata(typeOrFunc, getParentCtor(typeOrFunc)) || {};
4656 }
4657 hasLifecycleHook(type, lcProperty) {
4658 return type instanceof Type && lcProperty in type.prototype;
4659 }
4660 guards(type) {
4661 return {};
4662 }
4663 getter(name) {
4664 return new Function('o', 'return o.' + name + ';');
4665 }
4666 setter(name) {
4667 return new Function('o', 'v', 'return o.' + name + ' = v;');
4668 }
4669 method(name) {
4670 const functionBody = `if (!o.${name}) throw new Error('"${name}" is undefined');
4671 return o.${name}.apply(o, args);`;
4672 return new Function('o', 'args', functionBody);
4673 }
4674 // There is not a concept of import uri in Js, but this is useful in developing Dart applications.
4675 importUri(type) {
4676 // StaticSymbol
4677 if (typeof type === 'object' && type['filePath']) {
4678 return type['filePath'];
4679 }
4680 // Runtime type
4681 return `./${stringify(type)}`;
4682 }
4683 resourceUri(type) {
4684 return `./${stringify(type)}`;
4685 }
4686 resolveIdentifier(name, moduleUrl, members, runtime) {
4687 return runtime;
4688 }
4689 resolveEnum(enumIdentifier, name) {
4690 return enumIdentifier[name];
4691 }
4692}
4693function convertTsickleDecoratorIntoMetadata(decoratorInvocations) {
4694 if (!decoratorInvocations) {
4695 return [];
4696 }
4697 return decoratorInvocations.map(decoratorInvocation => {
4698 const decoratorType = decoratorInvocation.type;
4699 const annotationCls = decoratorType.annotationCls;
4700 const annotationArgs = decoratorInvocation.args ? decoratorInvocation.args : [];
4701 return new annotationCls(...annotationArgs);
4702 });
4703}
4704function getParentCtor(ctor) {
4705 const parentProto = ctor.prototype ? Object.getPrototypeOf(ctor.prototype) : null;
4706 const parentCtor = parentProto ? parentProto.constructor : null;
4707 // Note: We always use `Object` as the null value
4708 // to simplify checking later on.
4709 return parentCtor || Object;
4710}
4711
4712/**
4713 * @license
4714 * Copyright Google LLC All Rights Reserved.
4715 *
4716 * Use of this source code is governed by an MIT-style license that can be
4717 * found in the LICENSE file at https://angular.io/license
4718 */
4719const _THROW_IF_NOT_FOUND = {};
4720const THROW_IF_NOT_FOUND = _THROW_IF_NOT_FOUND;
4721/*
4722 * Name of a property (that we patch onto DI decorator), which is used as an annotation of which
4723 * InjectFlag this decorator represents. This allows to avoid direct references to the DI decorators
4724 * in the code, thus making them tree-shakable.
4725 */
4726const DI_DECORATOR_FLAG = '__NG_DI_FLAG__';
4727const NG_TEMP_TOKEN_PATH = 'ngTempTokenPath';
4728const NG_TOKEN_PATH = 'ngTokenPath';
4729const NEW_LINE = /\n/gm;
4730const NO_NEW_LINE$1 = 'ɵ';
4731const SOURCE = '__source';
4732const USE_VALUE$2 = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
4733/**
4734 * Current injector value used by `inject`.
4735 * - `undefined`: it is an error to call `inject`
4736 * - `null`: `inject` can be called but there is no injector (limp-mode).
4737 * - Injector instance: Use the injector for resolution.
4738 */
4739let _currentInjector = undefined;
4740function setCurrentInjector(injector) {
4741 const former = _currentInjector;
4742 _currentInjector = injector;
4743 return former;
4744}
4745function injectInjectorOnly(token, flags = InjectFlags.Default) {
4746 if (_currentInjector === undefined) {
4747 throw new Error(`inject() must be called from an injection context`);
4748 }
4749 else if (_currentInjector === null) {
4750 return injectRootLimpMode(token, undefined, flags);
4751 }
4752 else {
4753 return _currentInjector.get(token, flags & InjectFlags.Optional ? null : undefined, flags);
4754 }
4755}
4756function ɵɵinject(token, flags = InjectFlags.Default) {
4757 return (getInjectImplementation() || injectInjectorOnly)(resolveForwardRef(token), flags);
4758}
4759/**
4760 * Throws an error indicating that a factory function could not be generated by the compiler for a
4761 * particular class.
4762 *
4763 * This instruction allows the actual error message to be optimized away when ngDevMode is turned
4764 * off, saving bytes of generated code while still providing a good experience in dev mode.
4765 *
4766 * The name of the class is not mentioned here, but will be in the generated factory function name
4767 * and thus in the stack trace.
4768 *
4769 * @codeGenApi
4770 */
4771function ɵɵinvalidFactoryDep(index) {
4772 const msg = ngDevMode ?
4773 `This constructor is not compatible with Angular Dependency Injection because its dependency at index ${index} of the parameter list is invalid.
4774This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.
4775
4776Please 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.` :
4777 'invalid';
4778 throw new Error(msg);
4779}
4780/**
4781 * Injects a token from the currently active injector.
4782 *
4783 * Must be used in the context of a factory function such as one defined for an
4784 * `InjectionToken`. Throws an error if not called from such a context.
4785 *
4786 * Within such a factory function, using this function to request injection of a dependency
4787 * is faster and more type-safe than providing an additional array of dependencies
4788 * (as has been common with `useFactory` providers).
4789 *
4790 * @param token The injection token for the dependency to be injected.
4791 * @param flags Optional flags that control how injection is executed.
4792 * The flags correspond to injection strategies that can be specified with
4793 * parameter decorators `@Host`, `@Self`, `@SkipSef`, and `@Optional`.
4794 * @returns the injected value if injection is successful, `null` otherwise.
4795 *
4796 * @usageNotes
4797 *
4798 * ### Example
4799 *
4800 * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
4801 *
4802 * @publicApi
4803 */
4804const inject = ɵɵinject;
4805function injectArgs(types) {
4806 const args = [];
4807 for (let i = 0; i < types.length; i++) {
4808 const arg = resolveForwardRef(types[i]);
4809 if (Array.isArray(arg)) {
4810 if (arg.length === 0) {
4811 throw new Error('Arguments array must have arguments.');
4812 }
4813 let type = undefined;
4814 let flags = InjectFlags.Default;
4815 for (let j = 0; j < arg.length; j++) {
4816 const meta = arg[j];
4817 const flag = getInjectFlag(meta);
4818 if (typeof flag === 'number') {
4819 // Special case when we handle @Inject decorator.
4820 if (flag === -1 /* Inject */) {
4821 type = meta.token;
4822 }
4823 else {
4824 flags |= flag;
4825 }
4826 }
4827 else {
4828 type = meta;
4829 }
4830 }
4831 args.push(ɵɵinject(type, flags));
4832 }
4833 else {
4834 args.push(ɵɵinject(arg));
4835 }
4836 }
4837 return args;
4838}
4839/**
4840 * Attaches a given InjectFlag to a given decorator using monkey-patching.
4841 * Since DI decorators can be used in providers `deps` array (when provider is configured using
4842 * `useFactory`) without initialization (e.g. `Host`) and as an instance (e.g. `new Host()`), we
4843 * attach the flag to make it available both as a static property and as a field on decorator
4844 * instance.
4845 *
4846 * @param decorator Provided DI decorator.
4847 * @param flag InjectFlag that should be applied.
4848 */
4849function attachInjectFlag(decorator, flag) {
4850 decorator[DI_DECORATOR_FLAG] = flag;
4851 decorator.prototype[DI_DECORATOR_FLAG] = flag;
4852 return decorator;
4853}
4854/**
4855 * Reads monkey-patched property that contains InjectFlag attached to a decorator.
4856 *
4857 * @param token Token that may contain monkey-patched DI flags property.
4858 */
4859function getInjectFlag(token) {
4860 return token[DI_DECORATOR_FLAG];
4861}
4862function catchInjectorError(e, token, injectorErrorName, source) {
4863 const tokenPath = e[NG_TEMP_TOKEN_PATH];
4864 if (token[SOURCE]) {
4865 tokenPath.unshift(token[SOURCE]);
4866 }
4867 e.message = formatError('\n' + e.message, tokenPath, injectorErrorName, source);
4868 e[NG_TOKEN_PATH] = tokenPath;
4869 e[NG_TEMP_TOKEN_PATH] = null;
4870 throw e;
4871}
4872function formatError(text, obj, injectorErrorName, source = null) {
4873 text = text && text.charAt(0) === '\n' && text.charAt(1) == NO_NEW_LINE$1 ? text.substr(2) : text;
4874 let context = stringify(obj);
4875 if (Array.isArray(obj)) {
4876 context = obj.map(stringify).join(' -> ');
4877 }
4878 else if (typeof obj === 'object') {
4879 let parts = [];
4880 for (let key in obj) {
4881 if (obj.hasOwnProperty(key)) {
4882 let value = obj[key];
4883 parts.push(key + ':' + (typeof value === 'string' ? JSON.stringify(value) : stringify(value)));
4884 }
4885 }
4886 context = `{${parts.join(', ')}}`;
4887 }
4888 return `${injectorErrorName}${source ? '(' + source + ')' : ''}[${context}]: ${text.replace(NEW_LINE, '\n ')}`;
4889}
4890
4891/**
4892 * @license
4893 * Copyright Google LLC All Rights Reserved.
4894 *
4895 * Use of this source code is governed by an MIT-style license that can be
4896 * found in the LICENSE file at https://angular.io/license
4897 */
4898/**
4899 * Inject decorator and metadata.
4900 *
4901 * @Annotation
4902 * @publicApi
4903 */
4904const Inject = attachInjectFlag(
4905// Disable tslint because `DecoratorFlags` is a const enum which gets inlined.
4906// tslint:disable-next-line: no-toplevel-property-access
4907makeParamDecorator('Inject', (token) => ({ token })), -1 /* Inject */);
4908/**
4909 * Optional decorator and metadata.
4910 *
4911 * @Annotation
4912 * @publicApi
4913 */
4914const Optional =
4915// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4916// tslint:disable-next-line: no-toplevel-property-access
4917attachInjectFlag(makeParamDecorator('Optional'), 8 /* Optional */);
4918/**
4919 * Self decorator and metadata.
4920 *
4921 * @Annotation
4922 * @publicApi
4923 */
4924const Self =
4925// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4926// tslint:disable-next-line: no-toplevel-property-access
4927attachInjectFlag(makeParamDecorator('Self'), 2 /* Self */);
4928/**
4929 * `SkipSelf` decorator and metadata.
4930 *
4931 * @Annotation
4932 * @publicApi
4933 */
4934const SkipSelf =
4935// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4936// tslint:disable-next-line: no-toplevel-property-access
4937attachInjectFlag(makeParamDecorator('SkipSelf'), 4 /* SkipSelf */);
4938/**
4939 * Host decorator and metadata.
4940 *
4941 * @Annotation
4942 * @publicApi
4943 */
4944const Host =
4945// Disable tslint because `InternalInjectFlags` is a const enum which gets inlined.
4946// tslint:disable-next-line: no-toplevel-property-access
4947attachInjectFlag(makeParamDecorator('Host'), 1 /* Host */);
4948
4949/**
4950 * @license
4951 * Copyright Google LLC All Rights Reserved.
4952 *
4953 * Use of this source code is governed by an MIT-style license that can be
4954 * found in the LICENSE file at https://angular.io/license
4955 */
4956let _reflect = null;
4957function getReflect() {
4958 return (_reflect = _reflect || new ReflectionCapabilities());
4959}
4960function reflectDependencies(type) {
4961 return convertDependencies(getReflect().parameters(type));
4962}
4963function convertDependencies(deps) {
4964 return deps.map(dep => reflectDependency(dep));
4965}
4966function reflectDependency(dep) {
4967 const meta = {
4968 token: null,
4969 attribute: null,
4970 host: false,
4971 optional: false,
4972 self: false,
4973 skipSelf: false,
4974 };
4975 if (Array.isArray(dep) && dep.length > 0) {
4976 for (let j = 0; j < dep.length; j++) {
4977 const param = dep[j];
4978 if (param === undefined) {
4979 // param may be undefined if type of dep is not set by ngtsc
4980 continue;
4981 }
4982 const proto = Object.getPrototypeOf(param);
4983 if (param instanceof Optional || proto.ngMetadataName === 'Optional') {
4984 meta.optional = true;
4985 }
4986 else if (param instanceof SkipSelf || proto.ngMetadataName === 'SkipSelf') {
4987 meta.skipSelf = true;
4988 }
4989 else if (param instanceof Self || proto.ngMetadataName === 'Self') {
4990 meta.self = true;
4991 }
4992 else if (param instanceof Host || proto.ngMetadataName === 'Host') {
4993 meta.host = true;
4994 }
4995 else if (param instanceof Inject) {
4996 meta.token = param.token;
4997 }
4998 else if (param instanceof Attribute) {
4999 if (param.attributeName === undefined) {
5000 throw new Error(`Attribute name must be defined.`);
5001 }
5002 meta.attribute = param.attributeName;
5003 }
5004 else {
5005 meta.token = param;
5006 }
5007 }
5008 }
5009 else if (dep === undefined || (Array.isArray(dep) && dep.length === 0)) {
5010 meta.token = null;
5011 }
5012 else {
5013 meta.token = dep;
5014 }
5015 return meta;
5016}
5017
5018/**
5019 * @license
5020 * Copyright Google LLC All Rights Reserved.
5021 *
5022 * Use of this source code is governed by an MIT-style license that can be
5023 * found in the LICENSE file at https://angular.io/license
5024 */
5025/**
5026 * Used to resolve resource URLs on `@Component` when used with JIT compilation.
5027 *
5028 * Example:
5029 * ```
5030 * @Component({
5031 * selector: 'my-comp',
5032 * templateUrl: 'my-comp.html', // This requires asynchronous resolution
5033 * })
5034 * class MyComponent{
5035 * }
5036 *
5037 * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process
5038 * // and `MyComponent`'s `@Component.templateUrl` needs to be resolved asynchronously.
5039 *
5040 * // Calling `resolveComponentResources()` will resolve `@Component.templateUrl` into
5041 * // `@Component.template`, which allows `renderComponent` to proceed in a synchronous manner.
5042 *
5043 * // Use browser's `fetch()` function as the default resource resolution strategy.
5044 * resolveComponentResources(fetch).then(() => {
5045 * // After resolution all URLs have been converted into `template` strings.
5046 * renderComponent(MyComponent);
5047 * });
5048 *
5049 * ```
5050 *
5051 * NOTE: In AOT the resolution happens during compilation, and so there should be no need
5052 * to call this method outside JIT mode.
5053 *
5054 * @param resourceResolver a function which is responsible for returning a `Promise` to the
5055 * contents of the resolved URL. Browser's `fetch()` method is a good default implementation.
5056 */
5057function resolveComponentResources(resourceResolver) {
5058 // Store all promises which are fetching the resources.
5059 const componentResolved = [];
5060 // Cache so that we don't fetch the same resource more than once.
5061 const urlMap = new Map();
5062 function cachedResourceResolve(url) {
5063 let promise = urlMap.get(url);
5064 if (!promise) {
5065 const resp = resourceResolver(url);
5066 urlMap.set(url, promise = resp.then(unwrapResponse));
5067 }
5068 return promise;
5069 }
5070 componentResourceResolutionQueue.forEach((component, type) => {
5071 const promises = [];
5072 if (component.templateUrl) {
5073 promises.push(cachedResourceResolve(component.templateUrl).then((template) => {
5074 component.template = template;
5075 }));
5076 }
5077 const styleUrls = component.styleUrls;
5078 const styles = component.styles || (component.styles = []);
5079 const styleOffset = component.styles.length;
5080 styleUrls && styleUrls.forEach((styleUrl, index) => {
5081 styles.push(''); // pre-allocate array.
5082 promises.push(cachedResourceResolve(styleUrl).then((style) => {
5083 styles[styleOffset + index] = style;
5084 styleUrls.splice(styleUrls.indexOf(styleUrl), 1);
5085 if (styleUrls.length == 0) {
5086 component.styleUrls = undefined;
5087 }
5088 }));
5089 });
5090 const fullyResolved = Promise.all(promises).then(() => componentDefResolved(type));
5091 componentResolved.push(fullyResolved);
5092 });
5093 clearResolutionOfComponentResourcesQueue();
5094 return Promise.all(componentResolved).then(() => undefined);
5095}
5096let componentResourceResolutionQueue = new Map();
5097// Track when existing ɵcmp for a Type is waiting on resources.
5098const componentDefPendingResolution = new Set();
5099function maybeQueueResolutionOfComponentResources(type, metadata) {
5100 if (componentNeedsResolution(metadata)) {
5101 componentResourceResolutionQueue.set(type, metadata);
5102 componentDefPendingResolution.add(type);
5103 }
5104}
5105function isComponentDefPendingResolution(type) {
5106 return componentDefPendingResolution.has(type);
5107}
5108function componentNeedsResolution(component) {
5109 return !!((component.templateUrl && !component.hasOwnProperty('template')) ||
5110 component.styleUrls && component.styleUrls.length);
5111}
5112function clearResolutionOfComponentResourcesQueue() {
5113 const old = componentResourceResolutionQueue;
5114 componentResourceResolutionQueue = new Map();
5115 return old;
5116}
5117function restoreComponentResolutionQueue(queue) {
5118 componentDefPendingResolution.clear();
5119 queue.forEach((_, type) => componentDefPendingResolution.add(type));
5120 componentResourceResolutionQueue = queue;
5121}
5122function isComponentResourceResolutionQueueEmpty() {
5123 return componentResourceResolutionQueue.size === 0;
5124}
5125function unwrapResponse(response) {
5126 return typeof response == 'string' ? response : response.text();
5127}
5128function componentDefResolved(type) {
5129 componentDefPendingResolution.delete(type);
5130}
5131
5132/**
5133 * @license
5134 * Copyright Google LLC All Rights Reserved.
5135 *
5136 * Use of this source code is governed by an MIT-style license that can be
5137 * found in the LICENSE file at https://angular.io/license
5138 */
5139/**
5140 * The Trusted Types policy, or null if Trusted Types are not
5141 * enabled/supported, or undefined if the policy has not been created yet.
5142 */
5143let policy$1;
5144/**
5145 * Returns the Trusted Types policy, or null if Trusted Types are not
5146 * enabled/supported. The first call to this function will create the policy.
5147 */
5148function getPolicy$1() {
5149 if (policy$1 === undefined) {
5150 policy$1 = null;
5151 if (_global.trustedTypes) {
5152 try {
5153 policy$1 = _global.trustedTypes.createPolicy('angular', {
5154 createHTML: (s) => s,
5155 createScript: (s) => s,
5156 createScriptURL: (s) => s,
5157 });
5158 }
5159 catch (_a) {
5160 // trustedTypes.createPolicy throws if called with a name that is
5161 // already registered, even in report-only mode. Until the API changes,
5162 // catch the error not to break the applications functionally. In such
5163 // cases, the code will fall back to using strings.
5164 }
5165 }
5166 }
5167 return policy$1;
5168}
5169/**
5170 * Unsafely promote a string to a TrustedHTML, falling back to strings when
5171 * Trusted Types are not available.
5172 * @security This is a security-sensitive function; any use of this function
5173 * must go through security review. In particular, it must be assured that the
5174 * provided string will never cause an XSS vulnerability if used in a context
5175 * that will be interpreted as HTML by a browser, e.g. when assigning to
5176 * element.innerHTML.
5177 */
5178function trustedHTMLFromString(html) {
5179 var _a;
5180 return ((_a = getPolicy$1()) === null || _a === void 0 ? void 0 : _a.createHTML(html)) || html;
5181}
5182/**
5183 * Unsafely promote a string to a TrustedScript, falling back to strings when
5184 * Trusted Types are not available.
5185 * @security In particular, it must be assured that the provided string will
5186 * never cause an XSS vulnerability if used in a context that will be
5187 * interpreted and executed as a script by a browser, e.g. when calling eval.
5188 */
5189function trustedScriptFromString(script) {
5190 var _a;
5191 return ((_a = getPolicy$1()) === null || _a === void 0 ? void 0 : _a.createScript(script)) || script;
5192}
5193/**
5194 * Unsafely promote a string to a TrustedScriptURL, falling back to strings
5195 * when Trusted Types are not available.
5196 * @security This is a security-sensitive function; any use of this function
5197 * must go through security review. In particular, it must be assured that the
5198 * provided string will never cause an XSS vulnerability if used in a context
5199 * that will cause a browser to load and execute a resource, e.g. when
5200 * assigning to script.src.
5201 */
5202function trustedScriptURLFromString(url) {
5203 var _a;
5204 return ((_a = getPolicy$1()) === null || _a === void 0 ? void 0 : _a.createScriptURL(url)) || url;
5205}
5206/**
5207 * Unsafely call the Function constructor with the given string arguments. It
5208 * is only available in development mode, and should be stripped out of
5209 * production code.
5210 * @security This is a security-sensitive function; any use of this function
5211 * must go through security review. In particular, it must be assured that it
5212 * is only called from development code, as use in production code can lead to
5213 * XSS vulnerabilities.
5214 */
5215function newTrustedFunctionForDev(...args) {
5216 if (typeof ngDevMode === 'undefined') {
5217 throw new Error('newTrustedFunctionForDev should never be called in production');
5218 }
5219 if (!_global.trustedTypes) {
5220 // In environments that don't support Trusted Types, fall back to the most
5221 // straightforward implementation:
5222 return new Function(...args);
5223 }
5224 // Chrome currently does not support passing TrustedScript to the Function
5225 // constructor. The following implements the workaround proposed on the page
5226 // below, where the Chromium bug is also referenced:
5227 // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
5228 const fnArgs = args.slice(0, -1).join(',');
5229 const fnBody = args[args.length - 1];
5230 const body = `(function anonymous(${fnArgs}
5231) { ${fnBody}
5232})`;
5233 // Using eval directly confuses the compiler and prevents this module from
5234 // being stripped out of JS binaries even if not used. The global['eval']
5235 // indirection fixes that.
5236 const fn = _global['eval'](trustedScriptFromString(body));
5237 if (fn.bind === undefined) {
5238 // Workaround for a browser bug that only exists in Chrome 83, where passing
5239 // a TrustedScript to eval just returns the TrustedScript back without
5240 // evaluating it. In that case, fall back to the most straightforward
5241 // implementation:
5242 return new Function(...args);
5243 }
5244 // To completely mimic the behavior of calling "new Function", two more
5245 // things need to happen:
5246 // 1. Stringifying the resulting function should return its source code
5247 fn.toString = () => body;
5248 // 2. When calling the resulting function, `this` should refer to `global`
5249 return fn.bind(_global);
5250 // When Trusted Types support in Function constructors is widely available,
5251 // the implementation of this function can be simplified to:
5252 // return new Function(...args.map(a => trustedScriptFromString(a)));
5253}
5254
5255/**
5256 * @license
5257 * Copyright Google LLC All Rights Reserved.
5258 *
5259 * Use of this source code is governed by an MIT-style license that can be
5260 * found in the LICENSE file at https://angular.io/license
5261 */
5262/**
5263 * The Trusted Types policy, or null if Trusted Types are not
5264 * enabled/supported, or undefined if the policy has not been created yet.
5265 */
5266let policy;
5267/**
5268 * Returns the Trusted Types policy, or null if Trusted Types are not
5269 * enabled/supported. The first call to this function will create the policy.
5270 */
5271function getPolicy() {
5272 if (policy === undefined) {
5273 policy = null;
5274 if (_global.trustedTypes) {
5275 try {
5276 policy = _global.trustedTypes
5277 .createPolicy('angular#unsafe-bypass', {
5278 createHTML: (s) => s,
5279 createScript: (s) => s,
5280 createScriptURL: (s) => s,
5281 });
5282 }
5283 catch (_a) {
5284 // trustedTypes.createPolicy throws if called with a name that is
5285 // already registered, even in report-only mode. Until the API changes,
5286 // catch the error not to break the applications functionally. In such
5287 // cases, the code will fall back to using strings.
5288 }
5289 }
5290 }
5291 return policy;
5292}
5293/**
5294 * Unsafely promote a string to a TrustedHTML, falling back to strings when
5295 * Trusted Types are not available.
5296 * @security This is a security-sensitive function; any use of this function
5297 * must go through security review. In particular, it must be assured that it
5298 * is only passed strings that come directly from custom sanitizers or the
5299 * bypassSecurityTrust* functions.
5300 */
5301function trustedHTMLFromStringBypass(html) {
5302 var _a;
5303 return ((_a = getPolicy()) === null || _a === void 0 ? void 0 : _a.createHTML(html)) || html;
5304}
5305/**
5306 * Unsafely promote a string to a TrustedScript, falling back to strings when
5307 * Trusted Types are not available.
5308 * @security This is a security-sensitive function; any use of this function
5309 * must go through security review. In particular, it must be assured that it
5310 * is only passed strings that come directly from custom sanitizers or the
5311 * bypassSecurityTrust* functions.
5312 */
5313function trustedScriptFromStringBypass(script) {
5314 var _a;
5315 return ((_a = getPolicy()) === null || _a === void 0 ? void 0 : _a.createScript(script)) || script;
5316}
5317/**
5318 * Unsafely promote a string to a TrustedScriptURL, falling back to strings
5319 * when Trusted Types are not available.
5320 * @security This is a security-sensitive function; any use of this function
5321 * must go through security review. In particular, it must be assured that it
5322 * is only passed strings that come directly from custom sanitizers or the
5323 * bypassSecurityTrust* functions.
5324 */
5325function trustedScriptURLFromStringBypass(url) {
5326 var _a;
5327 return ((_a = getPolicy()) === null || _a === void 0 ? void 0 : _a.createScriptURL(url)) || url;
5328}
5329
5330/**
5331 * @license
5332 * Copyright Google LLC All Rights Reserved.
5333 *
5334 * Use of this source code is governed by an MIT-style license that can be
5335 * found in the LICENSE file at https://angular.io/license
5336 */
5337class SafeValueImpl {
5338 constructor(changingThisBreaksApplicationSecurity) {
5339 this.changingThisBreaksApplicationSecurity = changingThisBreaksApplicationSecurity;
5340 }
5341 toString() {
5342 return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` +
5343 ` (see https://g.co/ng/security#xss)`;
5344 }
5345}
5346class SafeHtmlImpl extends SafeValueImpl {
5347 getTypeName() {
5348 return "HTML" /* Html */;
5349 }
5350}
5351class SafeStyleImpl extends SafeValueImpl {
5352 getTypeName() {
5353 return "Style" /* Style */;
5354 }
5355}
5356class SafeScriptImpl extends SafeValueImpl {
5357 getTypeName() {
5358 return "Script" /* Script */;
5359 }
5360}
5361class SafeUrlImpl extends SafeValueImpl {
5362 getTypeName() {
5363 return "URL" /* Url */;
5364 }
5365}
5366class SafeResourceUrlImpl extends SafeValueImpl {
5367 getTypeName() {
5368 return "ResourceURL" /* ResourceUrl */;
5369 }
5370}
5371function unwrapSafeValue(value) {
5372 return value instanceof SafeValueImpl ? value.changingThisBreaksApplicationSecurity :
5373 value;
5374}
5375function allowSanitizationBypassAndThrow(value, type) {
5376 const actualType = getSanitizationBypassType(value);
5377 if (actualType != null && actualType !== type) {
5378 // Allow ResourceURLs in URL contexts, they are strictly more trusted.
5379 if (actualType === "ResourceURL" /* ResourceUrl */ && type === "URL" /* Url */)
5380 return true;
5381 throw new Error(`Required a safe ${type}, got a ${actualType} (see https://g.co/ng/security#xss)`);
5382 }
5383 return actualType === type;
5384}
5385function getSanitizationBypassType(value) {
5386 return value instanceof SafeValueImpl && value.getTypeName() || null;
5387}
5388/**
5389 * Mark `html` string as trusted.
5390 *
5391 * This function wraps the trusted string in `String` and brands it in a way which makes it
5392 * recognizable to {@link htmlSanitizer} to be trusted implicitly.
5393 *
5394 * @param trustedHtml `html` string which needs to be implicitly trusted.
5395 * @returns a `html` which has been branded to be implicitly trusted.
5396 */
5397function bypassSanitizationTrustHtml(trustedHtml) {
5398 return new SafeHtmlImpl(trustedHtml);
5399}
5400/**
5401 * Mark `style` string as trusted.
5402 *
5403 * This function wraps the trusted string in `String` and brands it in a way which makes it
5404 * recognizable to {@link styleSanitizer} to be trusted implicitly.
5405 *
5406 * @param trustedStyle `style` string which needs to be implicitly trusted.
5407 * @returns a `style` hich has been branded to be implicitly trusted.
5408 */
5409function bypassSanitizationTrustStyle(trustedStyle) {
5410 return new SafeStyleImpl(trustedStyle);
5411}
5412/**
5413 * Mark `script` string as trusted.
5414 *
5415 * This function wraps the trusted string in `String` and brands it in a way which makes it
5416 * recognizable to {@link scriptSanitizer} to be trusted implicitly.
5417 *
5418 * @param trustedScript `script` string which needs to be implicitly trusted.
5419 * @returns a `script` which has been branded to be implicitly trusted.
5420 */
5421function bypassSanitizationTrustScript(trustedScript) {
5422 return new SafeScriptImpl(trustedScript);
5423}
5424/**
5425 * Mark `url` string as trusted.
5426 *
5427 * This function wraps the trusted string in `String` and brands it in a way which makes it
5428 * recognizable to {@link urlSanitizer} to be trusted implicitly.
5429 *
5430 * @param trustedUrl `url` string which needs to be implicitly trusted.
5431 * @returns a `url` which has been branded to be implicitly trusted.
5432 */
5433function bypassSanitizationTrustUrl(trustedUrl) {
5434 return new SafeUrlImpl(trustedUrl);
5435}
5436/**
5437 * Mark `url` string as trusted.
5438 *
5439 * This function wraps the trusted string in `String` and brands it in a way which makes it
5440 * recognizable to {@link resourceUrlSanitizer} to be trusted implicitly.
5441 *
5442 * @param trustedResourceUrl `url` string which needs to be implicitly trusted.
5443 * @returns a `url` which has been branded to be implicitly trusted.
5444 */
5445function bypassSanitizationTrustResourceUrl(trustedResourceUrl) {
5446 return new SafeResourceUrlImpl(trustedResourceUrl);
5447}
5448
5449/**
5450 * @license
5451 * Copyright Google LLC All Rights Reserved.
5452 *
5453 * Use of this source code is governed by an MIT-style license that can be
5454 * found in the LICENSE file at https://angular.io/license
5455 */
5456/**
5457 * This helper is used to get hold of an inert tree of DOM elements containing dirty HTML
5458 * that needs sanitizing.
5459 * Depending upon browser support we use one of two strategies for doing this.
5460 * Default: DOMParser strategy
5461 * Fallback: InertDocument strategy
5462 */
5463function getInertBodyHelper(defaultDoc) {
5464 const inertDocumentHelper = new InertDocumentHelper(defaultDoc);
5465 return isDOMParserAvailable() ? new DOMParserHelper(inertDocumentHelper) : inertDocumentHelper;
5466}
5467/**
5468 * Uses DOMParser to create and fill an inert body element.
5469 * This is the default strategy used in browsers that support it.
5470 */
5471class DOMParserHelper {
5472 constructor(inertDocumentHelper) {
5473 this.inertDocumentHelper = inertDocumentHelper;
5474 }
5475 getInertBodyElement(html) {
5476 // We add these extra elements to ensure that the rest of the content is parsed as expected
5477 // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the
5478 // `<head>` tag. Note that the `<body>` tag is closed implicitly to prevent unclosed tags
5479 // in `html` from consuming the otherwise explicit `</body>` tag.
5480 html = '<body><remove></remove>' + html;
5481 try {
5482 const body = new window.DOMParser()
5483 .parseFromString(trustedHTMLFromString(html), 'text/html')
5484 .body;
5485 if (body === null) {
5486 // In some browsers (e.g. Mozilla/5.0 iPad AppleWebKit Mobile) the `body` property only
5487 // becomes available in the following tick of the JS engine. In that case we fall back to
5488 // the `inertDocumentHelper` instead.
5489 return this.inertDocumentHelper.getInertBodyElement(html);
5490 }
5491 body.removeChild(body.firstChild);
5492 return body;
5493 }
5494 catch (_a) {
5495 return null;
5496 }
5497 }
5498}
5499/**
5500 * Use an HTML5 `template` element, if supported, or an inert body element created via
5501 * `createHtmlDocument` to create and fill an inert DOM element.
5502 * This is the fallback strategy if the browser does not support DOMParser.
5503 */
5504class InertDocumentHelper {
5505 constructor(defaultDoc) {
5506 this.defaultDoc = defaultDoc;
5507 this.inertDocument = this.defaultDoc.implementation.createHTMLDocument('sanitization-inert');
5508 if (this.inertDocument.body == null) {
5509 // usually there should be only one body element in the document, but IE doesn't have any, so
5510 // we need to create one.
5511 const inertHtml = this.inertDocument.createElement('html');
5512 this.inertDocument.appendChild(inertHtml);
5513 const inertBodyElement = this.inertDocument.createElement('body');
5514 inertHtml.appendChild(inertBodyElement);
5515 }
5516 }
5517 getInertBodyElement(html) {
5518 // Prefer using <template> element if supported.
5519 const templateEl = this.inertDocument.createElement('template');
5520 if ('content' in templateEl) {
5521 templateEl.innerHTML = trustedHTMLFromString(html);
5522 return templateEl;
5523 }
5524 // Note that previously we used to do something like `this.inertDocument.body.innerHTML = html`
5525 // and we returned the inert `body` node. This was changed, because IE seems to treat setting
5526 // `innerHTML` on an inserted element differently, compared to one that hasn't been inserted
5527 // yet. In particular, IE appears to split some of the text into multiple text nodes rather
5528 // than keeping them in a single one which ends up messing with Ivy's i18n parsing further
5529 // down the line. This has been worked around by creating a new inert `body` and using it as
5530 // the root node in which we insert the HTML.
5531 const inertBody = this.inertDocument.createElement('body');
5532 inertBody.innerHTML = trustedHTMLFromString(html);
5533 // Support: IE 11 only
5534 // strip custom-namespaced attributes on IE<=11
5535 if (this.defaultDoc.documentMode) {
5536 this.stripCustomNsAttrs(inertBody);
5537 }
5538 return inertBody;
5539 }
5540 /**
5541 * When IE11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1'
5542 * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g.
5543 * 'ns1:xlink:foo').
5544 *
5545 * This is undesirable since we don't want to allow any of these custom attributes. This method
5546 * strips them all.
5547 */
5548 stripCustomNsAttrs(el) {
5549 const elAttrs = el.attributes;
5550 // loop backwards so that we can support removals.
5551 for (let i = elAttrs.length - 1; 0 < i; i--) {
5552 const attrib = elAttrs.item(i);
5553 const attrName = attrib.name;
5554 if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
5555 el.removeAttribute(attrName);
5556 }
5557 }
5558 let childNode = el.firstChild;
5559 while (childNode) {
5560 if (childNode.nodeType === Node.ELEMENT_NODE)
5561 this.stripCustomNsAttrs(childNode);
5562 childNode = childNode.nextSibling;
5563 }
5564 }
5565}
5566/**
5567 * We need to determine whether the DOMParser exists in the global context and
5568 * supports parsing HTML; HTML parsing support is not as wide as other formats, see
5569 * https://developer.mozilla.org/en-US/docs/Web/API/DOMParser#Browser_compatibility.
5570 *
5571 * @suppress {uselessCode}
5572 */
5573function isDOMParserAvailable() {
5574 try {
5575 return !!new window.DOMParser().parseFromString(trustedHTMLFromString(''), 'text/html');
5576 }
5577 catch (_a) {
5578 return false;
5579 }
5580}
5581
5582/**
5583 * @license
5584 * Copyright Google LLC All Rights Reserved.
5585 *
5586 * Use of this source code is governed by an MIT-style license that can be
5587 * found in the LICENSE file at https://angular.io/license
5588 */
5589/**
5590 * A pattern that recognizes a commonly useful subset of URLs that are safe.
5591 *
5592 * This regular expression matches a subset of URLs that will not cause script
5593 * execution if used in URL context within a HTML document. Specifically, this
5594 * regular expression matches if (comment from here on and regex copied from
5595 * Soy's EscapingConventions):
5596 * (1) Either an allowed protocol (http, https, mailto or ftp).
5597 * (2) or no protocol. A protocol must be followed by a colon. The below
5598 * allows that by allowing colons only after one of the characters [/?#].
5599 * A colon after a hash (#) must be in the fragment.
5600 * Otherwise, a colon after a (?) must be in a query.
5601 * Otherwise, a colon after a single solidus (/) must be in a path.
5602 * Otherwise, a colon after a double solidus (//) must be in the authority
5603 * (before port).
5604 *
5605 * The pattern disallows &, used in HTML entity declarations before
5606 * one of the characters in [/?#]. This disallows HTML entities used in the
5607 * protocol name, which should never happen, e.g. "h&#116;tp" for "http".
5608 * It also disallows HTML entities in the first path part of a relative path,
5609 * e.g. "foo&lt;bar/baz". Our existing escaping functions should not produce
5610 * that. More importantly, it disallows masking of a colon,
5611 * e.g. "javascript&#58;...".
5612 *
5613 * This regular expression was taken from the Closure sanitization library.
5614 */
5615const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file|sms):|[^&:/?#]*(?:[/?#]|$))/gi;
5616/* A pattern that matches safe srcset values */
5617const SAFE_SRCSET_PATTERN = /^(?:(?:https?|file):|[^&:/?#]*(?:[/?#]|$))/gi;
5618/** A pattern that matches safe data URLs. Only matches image, video and audio types. */
5619const 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;
5620function _sanitizeUrl(url) {
5621 url = String(url);
5622 if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN))
5623 return url;
5624 if (typeof ngDevMode === 'undefined' || ngDevMode) {
5625 console.warn(`WARNING: sanitizing unsafe URL value ${url} (see https://g.co/ng/security#xss)`);
5626 }
5627 return 'unsafe:' + url;
5628}
5629function sanitizeSrcset(srcset) {
5630 srcset = String(srcset);
5631 return srcset.split(',').map((srcset) => _sanitizeUrl(srcset.trim())).join(', ');
5632}
5633
5634/**
5635 * @license
5636 * Copyright Google LLC All Rights Reserved.
5637 *
5638 * Use of this source code is governed by an MIT-style license that can be
5639 * found in the LICENSE file at https://angular.io/license
5640 */
5641function tagSet(tags) {
5642 const res = {};
5643 for (const t of tags.split(','))
5644 res[t] = true;
5645 return res;
5646}
5647function merge(...sets) {
5648 const res = {};
5649 for (const s of sets) {
5650 for (const v in s) {
5651 if (s.hasOwnProperty(v))
5652 res[v] = true;
5653 }
5654 }
5655 return res;
5656}
5657// Good source of info about elements and attributes
5658// https://html.spec.whatwg.org/#semantics
5659// https://simon.html5.org/html-elements
5660// Safe Void Elements - HTML5
5661// https://html.spec.whatwg.org/#void-elements
5662const VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr');
5663// Elements that you can, intentionally, leave open (and which close themselves)
5664// https://html.spec.whatwg.org/#optional-tags
5665const OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr');
5666const OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt');
5667const OPTIONAL_END_TAG_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS);
5668// Safe Block Elements - HTML5
5669const BLOCK_ELEMENTS = merge(OPTIONAL_END_TAG_BLOCK_ELEMENTS, tagSet('address,article,' +
5670 'aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' +
5671 'h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul'));
5672// Inline Elements - HTML5
5673const INLINE_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, tagSet('a,abbr,acronym,audio,b,' +
5674 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' +
5675 'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video'));
5676const VALID_ELEMENTS = merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS);
5677// Attributes that have href and hence need to be sanitized
5678const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href');
5679// Attributes that have special href set hence need to be sanitized
5680const SRCSET_ATTRS = tagSet('srcset');
5681const HTML_ATTRS = tagSet('abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' +
5682 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' +
5683 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' +
5684 'scope,scrolling,shape,size,sizes,span,srclang,start,summary,tabindex,target,title,translate,type,usemap,' +
5685 'valign,value,vspace,width');
5686// Accessibility attributes as per WAI-ARIA 1.1 (W3C Working Draft 14 December 2018)
5687const ARIA_ATTRS = tagSet('aria-activedescendant,aria-atomic,aria-autocomplete,aria-busy,aria-checked,aria-colcount,aria-colindex,' +
5688 'aria-colspan,aria-controls,aria-current,aria-describedby,aria-details,aria-disabled,aria-dropeffect,' +
5689 'aria-errormessage,aria-expanded,aria-flowto,aria-grabbed,aria-haspopup,aria-hidden,aria-invalid,' +
5690 'aria-keyshortcuts,aria-label,aria-labelledby,aria-level,aria-live,aria-modal,aria-multiline,' +
5691 'aria-multiselectable,aria-orientation,aria-owns,aria-placeholder,aria-posinset,aria-pressed,aria-readonly,' +
5692 'aria-relevant,aria-required,aria-roledescription,aria-rowcount,aria-rowindex,aria-rowspan,aria-selected,' +
5693 'aria-setsize,aria-sort,aria-valuemax,aria-valuemin,aria-valuenow,aria-valuetext');
5694// NB: This currently consciously doesn't support SVG. SVG sanitization has had several security
5695// issues in the past, so it seems safer to leave it out if possible. If support for binding SVG via
5696// innerHTML is required, SVG attributes should be added here.
5697// NB: Sanitization does not allow <form> elements or other active elements (<button> etc). Those
5698// can be sanitized, but they increase security surface area without a legitimate use case, so they
5699// are left out here.
5700const VALID_ATTRS = merge(URI_ATTRS, SRCSET_ATTRS, HTML_ATTRS, ARIA_ATTRS);
5701// Elements whose content should not be traversed/preserved, if the elements themselves are invalid.
5702//
5703// Typically, `<invalid>Some content</invalid>` would traverse (and in this case preserve)
5704// `Some content`, but strip `invalid-element` opening/closing tags. For some elements, though, we
5705// don't want to preserve the content, if the elements themselves are going to be removed.
5706const SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS = tagSet('script,style,template');
5707/**
5708 * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe
5709 * attributes.
5710 */
5711class SanitizingHtmlSerializer {
5712 constructor() {
5713 // Explicitly track if something was stripped, to avoid accidentally warning of sanitization just
5714 // because characters were re-encoded.
5715 this.sanitizedSomething = false;
5716 this.buf = [];
5717 }
5718 sanitizeChildren(el) {
5719 // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters.
5720 // However this code never accesses properties off of `document` before deleting its contents
5721 // again, so it shouldn't be vulnerable to DOM clobbering.
5722 let current = el.firstChild;
5723 let traverseContent = true;
5724 while (current) {
5725 if (current.nodeType === Node.ELEMENT_NODE) {
5726 traverseContent = this.startElement(current);
5727 }
5728 else if (current.nodeType === Node.TEXT_NODE) {
5729 this.chars(current.nodeValue);
5730 }
5731 else {
5732 // Strip non-element, non-text nodes.
5733 this.sanitizedSomething = true;
5734 }
5735 if (traverseContent && current.firstChild) {
5736 current = current.firstChild;
5737 continue;
5738 }
5739 while (current) {
5740 // Leaving the element. Walk up and to the right, closing tags as we go.
5741 if (current.nodeType === Node.ELEMENT_NODE) {
5742 this.endElement(current);
5743 }
5744 let next = this.checkClobberedElement(current, current.nextSibling);
5745 if (next) {
5746 current = next;
5747 break;
5748 }
5749 current = this.checkClobberedElement(current, current.parentNode);
5750 }
5751 }
5752 return this.buf.join('');
5753 }
5754 /**
5755 * Sanitizes an opening element tag (if valid) and returns whether the element's contents should
5756 * be traversed. Element content must always be traversed (even if the element itself is not
5757 * valid/safe), unless the element is one of `SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS`.
5758 *
5759 * @param element The element to sanitize.
5760 * @return True if the element's contents should be traversed.
5761 */
5762 startElement(element) {
5763 const tagName = element.nodeName.toLowerCase();
5764 if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {
5765 this.sanitizedSomething = true;
5766 return !SKIP_TRAVERSING_CONTENT_IF_INVALID_ELEMENTS.hasOwnProperty(tagName);
5767 }
5768 this.buf.push('<');
5769 this.buf.push(tagName);
5770 const elAttrs = element.attributes;
5771 for (let i = 0; i < elAttrs.length; i++) {
5772 const elAttr = elAttrs.item(i);
5773 const attrName = elAttr.name;
5774 const lower = attrName.toLowerCase();
5775 if (!VALID_ATTRS.hasOwnProperty(lower)) {
5776 this.sanitizedSomething = true;
5777 continue;
5778 }
5779 let value = elAttr.value;
5780 // TODO(martinprobst): Special case image URIs for data:image/...
5781 if (URI_ATTRS[lower])
5782 value = _sanitizeUrl(value);
5783 if (SRCSET_ATTRS[lower])
5784 value = sanitizeSrcset(value);
5785 this.buf.push(' ', attrName, '="', encodeEntities(value), '"');
5786 }
5787 this.buf.push('>');
5788 return true;
5789 }
5790 endElement(current) {
5791 const tagName = current.nodeName.toLowerCase();
5792 if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) {
5793 this.buf.push('</');
5794 this.buf.push(tagName);
5795 this.buf.push('>');
5796 }
5797 }
5798 chars(chars) {
5799 this.buf.push(encodeEntities(chars));
5800 }
5801 checkClobberedElement(node, nextNode) {
5802 if (nextNode &&
5803 (node.compareDocumentPosition(nextNode) &
5804 Node.DOCUMENT_POSITION_CONTAINED_BY) === Node.DOCUMENT_POSITION_CONTAINED_BY) {
5805 throw new Error(`Failed to sanitize html because the element is clobbered: ${node.outerHTML}`);
5806 }
5807 return nextNode;
5808 }
5809}
5810// Regular Expressions for parsing tags and attributes
5811const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
5812// ! to ~ is the ASCII range.
5813const NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;
5814/**
5815 * Escapes all potentially dangerous characters, so that the
5816 * resulting string can be safely inserted into attribute or
5817 * element text.
5818 * @param value
5819 */
5820function encodeEntities(value) {
5821 return value.replace(/&/g, '&amp;')
5822 .replace(SURROGATE_PAIR_REGEXP, function (match) {
5823 const hi = match.charCodeAt(0);
5824 const low = match.charCodeAt(1);
5825 return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
5826 })
5827 .replace(NON_ALPHANUMERIC_REGEXP, function (match) {
5828 return '&#' + match.charCodeAt(0) + ';';
5829 })
5830 .replace(/</g, '&lt;')
5831 .replace(/>/g, '&gt;');
5832}
5833let inertBodyHelper;
5834/**
5835 * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to
5836 * the DOM in a browser environment.
5837 */
5838function _sanitizeHtml(defaultDoc, unsafeHtmlInput) {
5839 let inertBodyElement = null;
5840 try {
5841 inertBodyHelper = inertBodyHelper || getInertBodyHelper(defaultDoc);
5842 // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime).
5843 let unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : '';
5844 inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
5845 // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser
5846 // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous.
5847 let mXSSAttempts = 5;
5848 let parsedHtml = unsafeHtml;
5849 do {
5850 if (mXSSAttempts === 0) {
5851 throw new Error('Failed to sanitize html because the input is unstable');
5852 }
5853 mXSSAttempts--;
5854 unsafeHtml = parsedHtml;
5855 parsedHtml = inertBodyElement.innerHTML;
5856 inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
5857 } while (unsafeHtml !== parsedHtml);
5858 const sanitizer = new SanitizingHtmlSerializer();
5859 const safeHtml = sanitizer.sanitizeChildren(getTemplateContent(inertBodyElement) || inertBodyElement);
5860 if ((typeof ngDevMode === 'undefined' || ngDevMode) && sanitizer.sanitizedSomething) {
5861 console.warn('WARNING: sanitizing HTML stripped some content, see https://g.co/ng/security#xss');
5862 }
5863 return trustedHTMLFromString(safeHtml);
5864 }
5865 finally {
5866 // In case anything goes wrong, clear out inertElement to reset the entire DOM structure.
5867 if (inertBodyElement) {
5868 const parent = getTemplateContent(inertBodyElement) || inertBodyElement;
5869 while (parent.firstChild) {
5870 parent.removeChild(parent.firstChild);
5871 }
5872 }
5873 }
5874}
5875function getTemplateContent(el) {
5876 return 'content' in el /** Microsoft/TypeScript#21517 */ && isTemplateElement(el) ?
5877 el.content :
5878 null;
5879}
5880function isTemplateElement(el) {
5881 return el.nodeType === Node.ELEMENT_NODE && el.nodeName === 'TEMPLATE';
5882}
5883
5884/**
5885 * @license
5886 * Copyright Google LLC All Rights Reserved.
5887 *
5888 * Use of this source code is governed by an MIT-style license that can be
5889 * found in the LICENSE file at https://angular.io/license
5890 */
5891/**
5892 * A SecurityContext marks a location that has dangerous security implications, e.g. a DOM property
5893 * like `innerHTML` that could cause Cross Site Scripting (XSS) security bugs when improperly
5894 * handled.
5895 *
5896 * See DomSanitizer for more details on security in Angular applications.
5897 *
5898 * @publicApi
5899 */
5900var SecurityContext;
5901(function (SecurityContext) {
5902 SecurityContext[SecurityContext["NONE"] = 0] = "NONE";
5903 SecurityContext[SecurityContext["HTML"] = 1] = "HTML";
5904 SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE";
5905 SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
5906 SecurityContext[SecurityContext["URL"] = 4] = "URL";
5907 SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
5908})(SecurityContext || (SecurityContext = {}));
5909
5910/**
5911 * @license
5912 * Copyright Google LLC All Rights Reserved.
5913 *
5914 * Use of this source code is governed by an MIT-style license that can be
5915 * found in the LICENSE file at https://angular.io/license
5916 */
5917/**
5918 * An `html` sanitizer which converts untrusted `html` **string** into trusted string by removing
5919 * dangerous content.
5920 *
5921 * This method parses the `html` and locates potentially dangerous content (such as urls and
5922 * javascript) and removes it.
5923 *
5924 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustHtml}.
5925 *
5926 * @param unsafeHtml untrusted `html`, typically from the user.
5927 * @returns `html` string which is safe to display to user, because all of the dangerous javascript
5928 * and urls have been removed.
5929 *
5930 * @codeGenApi
5931 */
5932function ɵɵsanitizeHtml(unsafeHtml) {
5933 const sanitizer = getSanitizer();
5934 if (sanitizer) {
5935 return trustedHTMLFromStringBypass(sanitizer.sanitize(SecurityContext.HTML, unsafeHtml) || '');
5936 }
5937 if (allowSanitizationBypassAndThrow(unsafeHtml, "HTML" /* Html */)) {
5938 return trustedHTMLFromStringBypass(unwrapSafeValue(unsafeHtml));
5939 }
5940 return _sanitizeHtml(getDocument(), renderStringify(unsafeHtml));
5941}
5942/**
5943 * A `style` sanitizer which converts untrusted `style` **string** into trusted string by removing
5944 * dangerous content.
5945 *
5946 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustStyle}.
5947 *
5948 * @param unsafeStyle untrusted `style`, typically from the user.
5949 * @returns `style` string which is safe to bind to the `style` properties.
5950 *
5951 * @codeGenApi
5952 */
5953function ɵɵsanitizeStyle(unsafeStyle) {
5954 const sanitizer = getSanitizer();
5955 if (sanitizer) {
5956 return sanitizer.sanitize(SecurityContext.STYLE, unsafeStyle) || '';
5957 }
5958 if (allowSanitizationBypassAndThrow(unsafeStyle, "Style" /* Style */)) {
5959 return unwrapSafeValue(unsafeStyle);
5960 }
5961 return renderStringify(unsafeStyle);
5962}
5963/**
5964 * A `url` sanitizer which converts untrusted `url` **string** into trusted string by removing
5965 * dangerous
5966 * content.
5967 *
5968 * This method parses the `url` and locates potentially dangerous content (such as javascript) and
5969 * removes it.
5970 *
5971 * It is possible to mark a string as trusted by calling {@link bypassSanitizationTrustUrl}.
5972 *
5973 * @param unsafeUrl untrusted `url`, typically from the user.
5974 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because
5975 * all of the dangerous javascript has been removed.
5976 *
5977 * @codeGenApi
5978 */
5979function ɵɵsanitizeUrl(unsafeUrl) {
5980 const sanitizer = getSanitizer();
5981 if (sanitizer) {
5982 return sanitizer.sanitize(SecurityContext.URL, unsafeUrl) || '';
5983 }
5984 if (allowSanitizationBypassAndThrow(unsafeUrl, "URL" /* Url */)) {
5985 return unwrapSafeValue(unsafeUrl);
5986 }
5987 return _sanitizeUrl(renderStringify(unsafeUrl));
5988}
5989/**
5990 * A `url` sanitizer which only lets trusted `url`s through.
5991 *
5992 * This passes only `url`s marked trusted by calling {@link bypassSanitizationTrustResourceUrl}.
5993 *
5994 * @param unsafeResourceUrl untrusted `url`, typically from the user.
5995 * @returns `url` string which is safe to bind to the `src` properties such as `<img src>`, because
5996 * only trusted `url`s have been allowed to pass.
5997 *
5998 * @codeGenApi
5999 */
6000function ɵɵsanitizeResourceUrl(unsafeResourceUrl) {
6001 const sanitizer = getSanitizer();
6002 if (sanitizer) {
6003 return trustedScriptURLFromStringBypass(sanitizer.sanitize(SecurityContext.RESOURCE_URL, unsafeResourceUrl) || '');
6004 }
6005 if (allowSanitizationBypassAndThrow(unsafeResourceUrl, "ResourceURL" /* ResourceUrl */)) {
6006 return trustedScriptURLFromStringBypass(unwrapSafeValue(unsafeResourceUrl));
6007 }
6008 throw new Error('unsafe value used in a resource URL context (see https://g.co/ng/security#xss)');
6009}
6010/**
6011 * A `script` sanitizer which only lets trusted javascript through.
6012 *
6013 * This passes only `script`s marked trusted by calling {@link
6014 * bypassSanitizationTrustScript}.
6015 *
6016 * @param unsafeScript untrusted `script`, typically from the user.
6017 * @returns `url` string which is safe to bind to the `<script>` element such as `<img src>`,
6018 * because only trusted `scripts` have been allowed to pass.
6019 *
6020 * @codeGenApi
6021 */
6022function ɵɵsanitizeScript(unsafeScript) {
6023 const sanitizer = getSanitizer();
6024 if (sanitizer) {
6025 return trustedScriptFromStringBypass(sanitizer.sanitize(SecurityContext.SCRIPT, unsafeScript) || '');
6026 }
6027 if (allowSanitizationBypassAndThrow(unsafeScript, "Script" /* Script */)) {
6028 return trustedScriptFromStringBypass(unwrapSafeValue(unsafeScript));
6029 }
6030 throw new Error('unsafe value used in a script context');
6031}
6032/**
6033 * A template tag function for promoting the associated constant literal to a
6034 * TrustedHTML. Interpolation is explicitly not allowed.
6035 *
6036 * @param html constant template literal containing trusted HTML.
6037 * @returns TrustedHTML wrapping `html`.
6038 *
6039 * @security This is a security-sensitive function and should only be used to
6040 * convert constant values of attributes and properties found in
6041 * application-provided Angular templates to TrustedHTML.
6042 *
6043 * @codeGenApi
6044 */
6045function ɵɵtrustConstantHtml(html) {
6046 // The following runtime check ensures that the function was called as a
6047 // template tag (e.g. ɵɵtrustConstantHtml`content`), without any interpolation
6048 // (e.g. not ɵɵtrustConstantHtml`content ${variable}`). A TemplateStringsArray
6049 // is an array with a `raw` property that is also an array. The associated
6050 // template literal has no interpolation if and only if the length of the
6051 // TemplateStringsArray is 1.
6052 if (ngDevMode && (!Array.isArray(html) || !Array.isArray(html.raw) || html.length !== 1)) {
6053 throw new Error(`Unexpected interpolation in trusted HTML constant: ${html.join('?')}`);
6054 }
6055 return trustedHTMLFromString(html[0]);
6056}
6057/**
6058 * A template tag function for promoting the associated constant literal to a
6059 * TrustedScriptURL. Interpolation is explicitly not allowed.
6060 *
6061 * @param url constant template literal containing a trusted script URL.
6062 * @returns TrustedScriptURL wrapping `url`.
6063 *
6064 * @security This is a security-sensitive function and should only be used to
6065 * convert constant values of attributes and properties found in
6066 * application-provided Angular templates to TrustedScriptURL.
6067 *
6068 * @codeGenApi
6069 */
6070function ɵɵtrustConstantResourceUrl(url) {
6071 // The following runtime check ensures that the function was called as a
6072 // template tag (e.g. ɵɵtrustConstantResourceUrl`content`), without any
6073 // interpolation (e.g. not ɵɵtrustConstantResourceUrl`content ${variable}`). A
6074 // TemplateStringsArray is an array with a `raw` property that is also an
6075 // array. The associated template literal has no interpolation if and only if
6076 // the length of the TemplateStringsArray is 1.
6077 if (ngDevMode && (!Array.isArray(url) || !Array.isArray(url.raw) || url.length !== 1)) {
6078 throw new Error(`Unexpected interpolation in trusted URL constant: ${url.join('?')}`);
6079 }
6080 return trustedScriptURLFromString(url[0]);
6081}
6082/**
6083 * Detects which sanitizer to use for URL property, based on tag name and prop name.
6084 *
6085 * The rules are based on the RESOURCE_URL context config from
6086 * `packages/compiler/src/schema/dom_security_schema.ts`.
6087 * If tag and prop names don't match Resource URL schema, use URL sanitizer.
6088 */
6089function getUrlSanitizer(tag, prop) {
6090 if ((prop === 'src' &&
6091 (tag === 'embed' || tag === 'frame' || tag === 'iframe' || tag === 'media' ||
6092 tag === 'script')) ||
6093 (prop === 'href' && (tag === 'base' || tag === 'link'))) {
6094 return ɵɵsanitizeResourceUrl;
6095 }
6096 return ɵɵsanitizeUrl;
6097}
6098/**
6099 * Sanitizes URL, selecting sanitizer function based on tag and property names.
6100 *
6101 * This function is used in case we can't define security context at compile time, when only prop
6102 * name is available. This happens when we generate host bindings for Directives/Components. The
6103 * host element is unknown at compile time, so we defer calculation of specific sanitizer to
6104 * runtime.
6105 *
6106 * @param unsafeUrl untrusted `url`, typically from the user.
6107 * @param tag target element tag name.
6108 * @param prop name of the property that contains the value.
6109 * @returns `url` string which is safe to bind.
6110 *
6111 * @codeGenApi
6112 */
6113function ɵɵsanitizeUrlOrResourceUrl(unsafeUrl, tag, prop) {
6114 return getUrlSanitizer(tag, prop)(unsafeUrl);
6115}
6116function validateAgainstEventProperties(name) {
6117 if (name.toLowerCase().startsWith('on')) {
6118 const msg = `Binding to event property '${name}' is disallowed for security reasons, ` +
6119 `please use (${name.slice(2)})=...` +
6120 `\nIf '${name}' is a directive input, make sure the directive is imported by the` +
6121 ` current module.`;
6122 throw new Error(msg);
6123 }
6124}
6125function validateAgainstEventAttributes(name) {
6126 if (name.toLowerCase().startsWith('on')) {
6127 const msg = `Binding to event attribute '${name}' is disallowed for security reasons, ` +
6128 `please use (${name.slice(2)})=...`;
6129 throw new Error(msg);
6130 }
6131}
6132function getSanitizer() {
6133 const lView = getLView();
6134 return lView && lView[SANITIZER];
6135}
6136
6137/**
6138 * @license
6139 * Copyright Google LLC All Rights Reserved.
6140 *
6141 * Use of this source code is governed by an MIT-style license that can be
6142 * found in the LICENSE file at https://angular.io/license
6143 */
6144/**
6145 * Returns the matching `LContext` data for a given DOM node, directive or component instance.
6146 *
6147 * This function will examine the provided DOM element, component, or directive instance\'s
6148 * monkey-patched property to derive the `LContext` data. Once called then the monkey-patched
6149 * value will be that of the newly created `LContext`.
6150 *
6151 * If the monkey-patched value is the `LView` instance then the context value for that
6152 * target will be created and the monkey-patch reference will be updated. Therefore when this
6153 * function is called it may mutate the provided element\'s, component\'s or any of the associated
6154 * directive\'s monkey-patch values.
6155 *
6156 * If the monkey-patch value is not detected then the code will walk up the DOM until an element
6157 * is found which contains a monkey-patch reference. When that occurs then the provided element
6158 * will be updated with a new context (which is then returned). If the monkey-patch value is not
6159 * detected for a component/directive instance then it will throw an error (all components and
6160 * directives should be automatically monkey-patched by ivy).
6161 *
6162 * @param target Component, Directive or DOM Node.
6163 */
6164function getLContext(target) {
6165 let mpValue = readPatchedData(target);
6166 if (mpValue) {
6167 // only when it's an array is it considered an LView instance
6168 // ... otherwise it's an already constructed LContext instance
6169 if (Array.isArray(mpValue)) {
6170 const lView = mpValue;
6171 let nodeIndex;
6172 let component = undefined;
6173 let directives = undefined;
6174 if (isComponentInstance(target)) {
6175 nodeIndex = findViaComponent(lView, target);
6176 if (nodeIndex == -1) {
6177 throw new Error('The provided component was not found in the application');
6178 }
6179 component = target;
6180 }
6181 else if (isDirectiveInstance(target)) {
6182 nodeIndex = findViaDirective(lView, target);
6183 if (nodeIndex == -1) {
6184 throw new Error('The provided directive was not found in the application');
6185 }
6186 directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
6187 }
6188 else {
6189 nodeIndex = findViaNativeElement(lView, target);
6190 if (nodeIndex == -1) {
6191 return null;
6192 }
6193 }
6194 // the goal is not to fill the entire context full of data because the lookups
6195 // are expensive. Instead, only the target data (the element, component, container, ICU
6196 // expression or directive details) are filled into the context. If called multiple times
6197 // with different target values then the missing target data will be filled in.
6198 const native = unwrapRNode(lView[nodeIndex]);
6199 const existingCtx = readPatchedData(native);
6200 const context = (existingCtx && !Array.isArray(existingCtx)) ?
6201 existingCtx :
6202 createLContext(lView, nodeIndex, native);
6203 // only when the component has been discovered then update the monkey-patch
6204 if (component && context.component === undefined) {
6205 context.component = component;
6206 attachPatchData(context.component, context);
6207 }
6208 // only when the directives have been discovered then update the monkey-patch
6209 if (directives && context.directives === undefined) {
6210 context.directives = directives;
6211 for (let i = 0; i < directives.length; i++) {
6212 attachPatchData(directives[i], context);
6213 }
6214 }
6215 attachPatchData(context.native, context);
6216 mpValue = context;
6217 }
6218 }
6219 else {
6220 const rElement = target;
6221 ngDevMode && assertDomNode(rElement);
6222 // if the context is not found then we need to traverse upwards up the DOM
6223 // to find the nearest element that has already been monkey patched with data
6224 let parent = rElement;
6225 while (parent = parent.parentNode) {
6226 const parentContext = readPatchedData(parent);
6227 if (parentContext) {
6228 let lView;
6229 if (Array.isArray(parentContext)) {
6230 lView = parentContext;
6231 }
6232 else {
6233 lView = parentContext.lView;
6234 }
6235 // the edge of the app was also reached here through another means
6236 // (maybe because the DOM was changed manually).
6237 if (!lView) {
6238 return null;
6239 }
6240 const index = findViaNativeElement(lView, rElement);
6241 if (index >= 0) {
6242 const native = unwrapRNode(lView[index]);
6243 const context = createLContext(lView, index, native);
6244 attachPatchData(native, context);
6245 mpValue = context;
6246 break;
6247 }
6248 }
6249 }
6250 }
6251 return mpValue || null;
6252}
6253/**
6254 * Creates an empty instance of a `LContext` context
6255 */
6256function createLContext(lView, nodeIndex, native) {
6257 return {
6258 lView,
6259 nodeIndex,
6260 native,
6261 component: undefined,
6262 directives: undefined,
6263 localRefs: undefined,
6264 };
6265}
6266/**
6267 * Takes a component instance and returns the view for that component.
6268 *
6269 * @param componentInstance
6270 * @returns The component's view
6271 */
6272function getComponentViewByInstance(componentInstance) {
6273 let lView = readPatchedData(componentInstance);
6274 let view;
6275 if (Array.isArray(lView)) {
6276 const nodeIndex = findViaComponent(lView, componentInstance);
6277 view = getComponentLViewByIndex(nodeIndex, lView);
6278 const context = createLContext(lView, nodeIndex, view[HOST]);
6279 context.component = componentInstance;
6280 attachPatchData(componentInstance, context);
6281 attachPatchData(context.native, context);
6282 }
6283 else {
6284 const context = lView;
6285 view = getComponentLViewByIndex(context.nodeIndex, context.lView);
6286 }
6287 return view;
6288}
6289/**
6290 * This property will be monkey-patched on elements, components and directives.
6291 */
6292const MONKEY_PATCH_KEY_NAME = '__ngContext__';
6293/**
6294 * Assigns the given data to the given target (which could be a component,
6295 * directive or DOM node instance) using monkey-patching.
6296 */
6297function attachPatchData(target, data) {
6298 ngDevMode && assertDefined(target, 'Target expected');
6299 target[MONKEY_PATCH_KEY_NAME] = data;
6300}
6301/**
6302 * Returns the monkey-patch value data present on the target (which could be
6303 * a component, directive or a DOM node).
6304 */
6305function readPatchedData(target) {
6306 ngDevMode && assertDefined(target, 'Target expected');
6307 return target[MONKEY_PATCH_KEY_NAME] || null;
6308}
6309function readPatchedLView(target) {
6310 const value = readPatchedData(target);
6311 if (value) {
6312 return Array.isArray(value) ? value : value.lView;
6313 }
6314 return null;
6315}
6316function isComponentInstance(instance) {
6317 return instance && instance.constructor && instance.constructor.ɵcmp;
6318}
6319function isDirectiveInstance(instance) {
6320 return instance && instance.constructor && instance.constructor.ɵdir;
6321}
6322/**
6323 * Locates the element within the given LView and returns the matching index
6324 */
6325function findViaNativeElement(lView, target) {
6326 const tView = lView[TVIEW];
6327 for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
6328 if (unwrapRNode(lView[i]) === target) {
6329 return i;
6330 }
6331 }
6332 return -1;
6333}
6334/**
6335 * Locates the next tNode (child, sibling or parent).
6336 */
6337function traverseNextElement(tNode) {
6338 if (tNode.child) {
6339 return tNode.child;
6340 }
6341 else if (tNode.next) {
6342 return tNode.next;
6343 }
6344 else {
6345 // Let's take the following template: <div><span>text</span></div><component/>
6346 // After checking the text node, we need to find the next parent that has a "next" TNode,
6347 // in this case the parent `div`, so that we can find the component.
6348 while (tNode.parent && !tNode.parent.next) {
6349 tNode = tNode.parent;
6350 }
6351 return tNode.parent && tNode.parent.next;
6352 }
6353}
6354/**
6355 * Locates the component within the given LView and returns the matching index
6356 */
6357function findViaComponent(lView, componentInstance) {
6358 const componentIndices = lView[TVIEW].components;
6359 if (componentIndices) {
6360 for (let i = 0; i < componentIndices.length; i++) {
6361 const elementComponentIndex = componentIndices[i];
6362 const componentView = getComponentLViewByIndex(elementComponentIndex, lView);
6363 if (componentView[CONTEXT] === componentInstance) {
6364 return elementComponentIndex;
6365 }
6366 }
6367 }
6368 else {
6369 const rootComponentView = getComponentLViewByIndex(HEADER_OFFSET, lView);
6370 const rootComponent = rootComponentView[CONTEXT];
6371 if (rootComponent === componentInstance) {
6372 // we are dealing with the root element here therefore we know that the
6373 // element is the very first element after the HEADER data in the lView
6374 return HEADER_OFFSET;
6375 }
6376 }
6377 return -1;
6378}
6379/**
6380 * Locates the directive within the given LView and returns the matching index
6381 */
6382function findViaDirective(lView, directiveInstance) {
6383 // if a directive is monkey patched then it will (by default)
6384 // have a reference to the LView of the current view. The
6385 // element bound to the directive being search lives somewhere
6386 // in the view data. We loop through the nodes and check their
6387 // list of directives for the instance.
6388 let tNode = lView[TVIEW].firstChild;
6389 while (tNode) {
6390 const directiveIndexStart = tNode.directiveStart;
6391 const directiveIndexEnd = tNode.directiveEnd;
6392 for (let i = directiveIndexStart; i < directiveIndexEnd; i++) {
6393 if (lView[i] === directiveInstance) {
6394 return tNode.index;
6395 }
6396 }
6397 tNode = traverseNextElement(tNode);
6398 }
6399 return -1;
6400}
6401/**
6402 * Returns a list of directives extracted from the given view based on the
6403 * provided list of directive index values.
6404 *
6405 * @param nodeIndex The node index
6406 * @param lView The target view data
6407 * @param includeComponents Whether or not to include components in returned directives
6408 */
6409function getDirectivesAtNodeIndex(nodeIndex, lView, includeComponents) {
6410 const tNode = lView[TVIEW].data[nodeIndex];
6411 let directiveStartIndex = tNode.directiveStart;
6412 if (directiveStartIndex == 0)
6413 return EMPTY_ARRAY;
6414 const directiveEndIndex = tNode.directiveEnd;
6415 if (!includeComponents && tNode.flags & 2 /* isComponentHost */)
6416 directiveStartIndex++;
6417 return lView.slice(directiveStartIndex, directiveEndIndex);
6418}
6419function getComponentAtNodeIndex(nodeIndex, lView) {
6420 const tNode = lView[TVIEW].data[nodeIndex];
6421 let directiveStartIndex = tNode.directiveStart;
6422 return tNode.flags & 2 /* isComponentHost */ ? lView[directiveStartIndex] : null;
6423}
6424/**
6425 * Returns a map of local references (local reference name => element or directive instance) that
6426 * exist on a given element.
6427 */
6428function discoverLocalRefs(lView, nodeIndex) {
6429 const tNode = lView[TVIEW].data[nodeIndex];
6430 if (tNode && tNode.localNames) {
6431 const result = {};
6432 let localIndex = tNode.index + 1;
6433 for (let i = 0; i < tNode.localNames.length; i += 2) {
6434 result[tNode.localNames[i]] = lView[localIndex];
6435 localIndex++;
6436 }
6437 return result;
6438 }
6439 return null;
6440}
6441
6442/**
6443 * @license
6444 * Copyright Google LLC All Rights Reserved.
6445 *
6446 * Use of this source code is governed by an MIT-style license that can be
6447 * found in the LICENSE file at https://angular.io/license
6448 */
6449const ERROR_TYPE = 'ngType';
6450const ERROR_DEBUG_CONTEXT = 'ngDebugContext';
6451const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
6452const ERROR_LOGGER = 'ngErrorLogger';
6453function wrappedError(message, originalError) {
6454 const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
6455 const error = Error(msg);
6456 error[ERROR_ORIGINAL_ERROR] = originalError;
6457 return error;
6458}
6459
6460/**
6461 * @license
6462 * Copyright Google LLC All Rights Reserved.
6463 *
6464 * Use of this source code is governed by an MIT-style license that can be
6465 * found in the LICENSE file at https://angular.io/license
6466 */
6467function getType(error) {
6468 return error[ERROR_TYPE];
6469}
6470function getDebugContext(error) {
6471 return error[ERROR_DEBUG_CONTEXT];
6472}
6473function getOriginalError(error) {
6474 return error[ERROR_ORIGINAL_ERROR];
6475}
6476function getErrorLogger(error) {
6477 return error && error[ERROR_LOGGER] || defaultErrorLogger;
6478}
6479function defaultErrorLogger(console, ...values) {
6480 console.error(...values);
6481}
6482
6483/**
6484 * @license
6485 * Copyright Google LLC All Rights Reserved.
6486 *
6487 * Use of this source code is governed by an MIT-style license that can be
6488 * found in the LICENSE file at https://angular.io/license
6489 */
6490/**
6491 * Provides a hook for centralized exception handling.
6492 *
6493 * The default implementation of `ErrorHandler` prints error messages to the `console`. To
6494 * intercept error handling, write a custom exception handler that replaces this default as
6495 * appropriate for your app.
6496 *
6497 * @usageNotes
6498 * ### Example
6499 *
6500 * ```
6501 * class MyErrorHandler implements ErrorHandler {
6502 * handleError(error) {
6503 * // do something with the exception
6504 * }
6505 * }
6506 *
6507 * @NgModule({
6508 * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
6509 * })
6510 * class MyModule {}
6511 * ```
6512 *
6513 * @publicApi
6514 */
6515class ErrorHandler {
6516 constructor() {
6517 /**
6518 * @internal
6519 */
6520 this._console = console;
6521 }
6522 handleError(error) {
6523 const originalError = this._findOriginalError(error);
6524 const context = this._findContext(error);
6525 // Note: Browser consoles show the place from where console.error was called.
6526 // We can use this to give users additional information about the error.
6527 const errorLogger = getErrorLogger(error);
6528 errorLogger(this._console, `ERROR`, error);
6529 if (originalError) {
6530 errorLogger(this._console, `ORIGINAL ERROR`, originalError);
6531 }
6532 if (context) {
6533 errorLogger(this._console, 'ERROR CONTEXT', context);
6534 }
6535 }
6536 /** @internal */
6537 _findContext(error) {
6538 return error ? (getDebugContext(error) || this._findContext(getOriginalError(error))) : null;
6539 }
6540 /** @internal */
6541 _findOriginalError(error) {
6542 let e = error && getOriginalError(error);
6543 while (e && getOriginalError(e)) {
6544 e = getOriginalError(e);
6545 }
6546 return e || null;
6547 }
6548}
6549
6550/**
6551 * @license
6552 * Copyright Google LLC All Rights Reserved.
6553 *
6554 * Use of this source code is governed by an MIT-style license that can be
6555 * found in the LICENSE file at https://angular.io/license
6556 */
6557/**
6558 * Defines a schema that allows an NgModule to contain the following:
6559 * - Non-Angular elements named with dash case (`-`).
6560 * - Element properties named with dash case (`-`).
6561 * Dash case is the naming convention for custom elements.
6562 *
6563 * @publicApi
6564 */
6565const CUSTOM_ELEMENTS_SCHEMA = {
6566 name: 'custom-elements'
6567};
6568/**
6569 * Defines a schema that allows any property on any element.
6570 *
6571 * This schema allows you to ignore the errors related to any unknown elements or properties in a
6572 * template. The usage of this schema is generally discouraged because it prevents useful validation
6573 * and may hide real errors in your template. Consider using the `CUSTOM_ELEMENTS_SCHEMA` instead.
6574 *
6575 * @publicApi
6576 */
6577const NO_ERRORS_SCHEMA = {
6578 name: 'no-errors-schema'
6579};
6580
6581/**
6582 * @license
6583 * Copyright Google LLC All Rights Reserved.
6584 *
6585 * Use of this source code is governed by an MIT-style license that can be
6586 * found in the LICENSE file at https://angular.io/license
6587 */
6588/**
6589 * Disallowed strings in the comment.
6590 *
6591 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
6592 */
6593const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
6594/**
6595 * Delimiter in the disallowed strings which needs to be wrapped with zero with character.
6596 */
6597const COMMENT_DELIMITER = /(<|>)/;
6598const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
6599/**
6600 * Escape the content of comment strings so that it can be safely inserted into a comment node.
6601 *
6602 * The issue is that HTML does not specify any way to escape comment end text inside the comment.
6603 * Consider: `<!-- The way you close a comment is with ">", and "->" at the beginning or by "-->" or
6604 * "--!>" at the end. -->`. Above the `"-->"` is meant to be text not an end to the comment. This
6605 * can be created programmatically through DOM APIs. (`<!--` are also disallowed.)
6606 *
6607 * see: https://html.spec.whatwg.org/multipage/syntax.html#comments
6608 *
6609 * ```
6610 * div.innerHTML = div.innerHTML
6611 * ```
6612 *
6613 * One would expect that the above code would be safe to do, but it turns out that because comment
6614 * text is not escaped, the comment may contain text which will prematurely close the comment
6615 * opening up the application for XSS attack. (In SSR we programmatically create comment nodes which
6616 * may contain such text and expect them to be safe.)
6617 *
6618 * This function escapes the comment text by looking for comment delimiters (`<` and `>`) and
6619 * surrounding them with `_>_` where the `_` is a zero width space `\u200B`. The result is that if a
6620 * comment contains any of the comment start/end delimiters (such as `<!--`, `-->` or `--!>`) the
6621 * text it will render normally but it will not cause the HTML parser to close/open the comment.
6622 *
6623 * @param value text to make safe for comment node by escaping the comment open/close character
6624 * sequence.
6625 */
6626function escapeCommentText(value) {
6627 return value.replace(COMMENT_DISALLOWED, (text) => text.replace(COMMENT_DELIMITER, COMMENT_DELIMITER_ESCAPED));
6628}
6629
6630/**
6631 * @license
6632 * Copyright Google LLC All Rights Reserved.
6633 *
6634 * Use of this source code is governed by an MIT-style license that can be
6635 * found in the LICENSE file at https://angular.io/license
6636 */
6637function normalizeDebugBindingName(name) {
6638 // Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
6639 name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
6640 return `ng-reflect-${name}`;
6641}
6642const CAMEL_CASE_REGEXP = /([A-Z])/g;
6643function camelCaseToDashCase(input) {
6644 return input.replace(CAMEL_CASE_REGEXP, (...m) => '-' + m[1].toLowerCase());
6645}
6646function normalizeDebugBindingValue(value) {
6647 try {
6648 // Limit the size of the value as otherwise the DOM just gets polluted.
6649 return value != null ? value.toString().slice(0, 30) : value;
6650 }
6651 catch (e) {
6652 return '[ERROR] Exception while trying to serialize the value';
6653 }
6654}
6655
6656/**
6657 * @license
6658 * Copyright Google LLC All Rights Reserved.
6659 *
6660 * Use of this source code is governed by an MIT-style license that can be
6661 * found in the LICENSE file at https://angular.io/license
6662 */
6663const defaultScheduler = (() => (typeof requestAnimationFrame !== 'undefined' &&
6664 requestAnimationFrame || // browser only
6665 setTimeout // everything else
6666)
6667 .bind(_global))();
6668/**
6669 *
6670 * @codeGenApi
6671 */
6672function ɵɵresolveWindow(element) {
6673 return element.ownerDocument.defaultView;
6674}
6675/**
6676 *
6677 * @codeGenApi
6678 */
6679function ɵɵresolveDocument(element) {
6680 return element.ownerDocument;
6681}
6682/**
6683 *
6684 * @codeGenApi
6685 */
6686function ɵɵresolveBody(element) {
6687 return element.ownerDocument.body;
6688}
6689/**
6690 * The special delimiter we use to separate property names, prefixes, and suffixes
6691 * in property binding metadata. See storeBindingMetadata().
6692 *
6693 * We intentionally use the Unicode "REPLACEMENT CHARACTER" (U+FFFD) as a delimiter
6694 * because it is a very uncommon character that is unlikely to be part of a user's
6695 * property names or interpolation strings. If it is in fact used in a property
6696 * binding, DebugElement.properties will not return the correct value for that
6697 * binding. However, there should be no runtime effect for real applications.
6698 *
6699 * This character is typically rendered as a question mark inside of a diamond.
6700 * See https://en.wikipedia.org/wiki/Specials_(Unicode_block)
6701 *
6702 */
6703const INTERPOLATION_DELIMITER = `�`;
6704/**
6705 * Unwrap a value which might be behind a closure (for forward declaration reasons).
6706 */
6707function maybeUnwrapFn(value) {
6708 if (value instanceof Function) {
6709 return value();
6710 }
6711 else {
6712 return value;
6713 }
6714}
6715
6716/**
6717 * @license
6718 * Copyright Google LLC All Rights Reserved.
6719 *
6720 * Use of this source code is governed by an MIT-style license that can be
6721 * found in the LICENSE file at https://angular.io/license
6722 */
6723/** Called when there are multiple component selectors that match a given node */
6724function throwMultipleComponentError(tNode) {
6725 throw new RuntimeError("300" /* MULTIPLE_COMPONENTS_MATCH */, `Multiple components match node with tagname ${tNode.value}`);
6726}
6727/** Throws an ExpressionChangedAfterChecked error if checkNoChanges mode is on. */
6728function throwErrorIfNoChangesMode(creationMode, oldValue, currValue, propName) {
6729 const field = propName ? ` for '${propName}'` : '';
6730 let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value${field}: '${oldValue}'. Current value: '${currValue}'.`;
6731 if (creationMode) {
6732 msg +=
6733 ` It seems like the view has been created after its parent and its children have been dirty checked.` +
6734 ` Has it been created in a change detection hook?`;
6735 }
6736 // TODO: include debug context, see `viewDebugError` function in
6737 // `packages/core/src/view/errors.ts` for reference.
6738 throw new RuntimeError("100" /* EXPRESSION_CHANGED_AFTER_CHECKED */, msg);
6739}
6740function constructDetailsForInterpolation(lView, rootIndex, expressionIndex, meta, changedValue) {
6741 const [propName, prefix, ...chunks] = meta.split(INTERPOLATION_DELIMITER);
6742 let oldValue = prefix, newValue = prefix;
6743 for (let i = 0; i < chunks.length; i++) {
6744 const slotIdx = rootIndex + i;
6745 oldValue += `${lView[slotIdx]}${chunks[i]}`;
6746 newValue += `${slotIdx === expressionIndex ? changedValue : lView[slotIdx]}${chunks[i]}`;
6747 }
6748 return { propName, oldValue, newValue };
6749}
6750/**
6751 * Constructs an object that contains details for the ExpressionChangedAfterItHasBeenCheckedError:
6752 * - property name (for property bindings or interpolations)
6753 * - old and new values, enriched using information from metadata
6754 *
6755 * More information on the metadata storage format can be found in `storePropertyBindingMetadata`
6756 * function description.
6757 */
6758function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValue) {
6759 const tData = lView[TVIEW].data;
6760 const metadata = tData[bindingIndex];
6761 if (typeof metadata === 'string') {
6762 // metadata for property interpolation
6763 if (metadata.indexOf(INTERPOLATION_DELIMITER) > -1) {
6764 return constructDetailsForInterpolation(lView, bindingIndex, bindingIndex, metadata, newValue);
6765 }
6766 // metadata for property binding
6767 return { propName: metadata, oldValue, newValue };
6768 }
6769 // metadata is not available for this expression, check if this expression is a part of the
6770 // property interpolation by going from the current binding index left and look for a string that
6771 // contains INTERPOLATION_DELIMITER, the layout in tView.data for this case will look like this:
6772 // [..., 'id�Prefix � and � suffix', null, null, null, ...]
6773 if (metadata === null) {
6774 let idx = bindingIndex - 1;
6775 while (typeof tData[idx] !== 'string' && tData[idx + 1] === null) {
6776 idx--;
6777 }
6778 const meta = tData[idx];
6779 if (typeof meta === 'string') {
6780 const matches = meta.match(new RegExp(INTERPOLATION_DELIMITER, 'g'));
6781 // first interpolation delimiter separates property name from interpolation parts (in case of
6782 // property interpolations), so we subtract one from total number of found delimiters
6783 if (matches && (matches.length - 1) > bindingIndex - idx) {
6784 return constructDetailsForInterpolation(lView, idx, bindingIndex, meta, newValue);
6785 }
6786 }
6787 }
6788 return { propName: undefined, oldValue, newValue };
6789}
6790
6791/**
6792 * @license
6793 * Copyright Google LLC All Rights Reserved.
6794 *
6795 * Use of this source code is governed by an MIT-style license that can be
6796 * found in the LICENSE file at https://angular.io/license
6797 */
6798/**
6799 * Flags for renderer-specific style modifiers.
6800 * @publicApi
6801 */
6802var RendererStyleFlags2;
6803(function (RendererStyleFlags2) {
6804 // TODO(misko): This needs to be refactored into a separate file so that it can be imported from
6805 // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails
6806 // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.
6807 /**
6808 * Marks a style as important.
6809 */
6810 RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important";
6811 /**
6812 * Marks a style as using dash case naming (this-is-dash-case).
6813 */
6814 RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase";
6815})(RendererStyleFlags2 || (RendererStyleFlags2 = {}));
6816
6817/**
6818 * @license
6819 * Copyright Google LLC All Rights Reserved.
6820 *
6821 * Use of this source code is governed by an MIT-style license that can be
6822 * found in the LICENSE file at https://angular.io/license
6823 */
6824let _icuContainerIterate;
6825/**
6826 * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.
6827 */
6828function icuContainerIterate(tIcuContainerNode, lView) {
6829 return _icuContainerIterate(tIcuContainerNode, lView);
6830}
6831/**
6832 * Ensures that `IcuContainerVisitor`'s implementation is present.
6833 *
6834 * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the
6835 * bundler to tree shake ICU logic and only load it if ICU instruction is executed.
6836 */
6837function ensureIcuContainerVisitorLoaded(loader) {
6838 if (_icuContainerIterate === undefined) {
6839 // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it
6840 // can be inlined into call-site.
6841 _icuContainerIterate = loader();
6842 }
6843}
6844
6845/**
6846 * @license
6847 * Copyright Google LLC All Rights Reserved.
6848 *
6849 * Use of this source code is governed by an MIT-style license that can be
6850 * found in the LICENSE file at https://angular.io/license
6851 */
6852// Note: This hack is necessary so we don't erroneously get a circular dependency
6853// failure based on types.
6854const unusedValueExportToPlacateAjd$3 = 1;
6855
6856/**
6857 * @license
6858 * Copyright Google LLC All Rights Reserved.
6859 *
6860 * Use of this source code is governed by an MIT-style license that can be
6861 * found in the LICENSE file at https://angular.io/license
6862 */
6863/**
6864 * Gets the parent LView of the passed LView, if the PARENT is an LContainer, will get the parent of
6865 * that LContainer, which is an LView
6866 * @param lView the lView whose parent to get
6867 */
6868function getLViewParent(lView) {
6869 ngDevMode && assertLView(lView);
6870 const parent = lView[PARENT];
6871 return isLContainer(parent) ? parent[PARENT] : parent;
6872}
6873/**
6874 * Retrieve the root view from any component or `LView` by walking the parent `LView` until
6875 * reaching the root `LView`.
6876 *
6877 * @param componentOrLView any component or `LView`
6878 */
6879function getRootView(componentOrLView) {
6880 ngDevMode && assertDefined(componentOrLView, 'component');
6881 let lView = isLView(componentOrLView) ? componentOrLView : readPatchedLView(componentOrLView);
6882 while (lView && !(lView[FLAGS] & 512 /* IsRoot */)) {
6883 lView = getLViewParent(lView);
6884 }
6885 ngDevMode && assertLView(lView);
6886 return lView;
6887}
6888/**
6889 * Returns the `RootContext` instance that is associated with
6890 * the application where the target is situated. It does this by walking the parent views until it
6891 * gets to the root view, then getting the context off of that.
6892 *
6893 * @param viewOrComponent the `LView` or component to get the root context for.
6894 */
6895function getRootContext(viewOrComponent) {
6896 const rootView = getRootView(viewOrComponent);
6897 ngDevMode &&
6898 assertDefined(rootView[CONTEXT], 'RootView has no context. Perhaps it is disconnected?');
6899 return rootView[CONTEXT];
6900}
6901/**
6902 * Gets the first `LContainer` in the LView or `null` if none exists.
6903 */
6904function getFirstLContainer(lView) {
6905 return getNearestLContainer(lView[CHILD_HEAD]);
6906}
6907/**
6908 * Gets the next `LContainer` that is a sibling of the given container.
6909 */
6910function getNextLContainer(container) {
6911 return getNearestLContainer(container[NEXT]);
6912}
6913function getNearestLContainer(viewOrContainer) {
6914 while (viewOrContainer !== null && !isLContainer(viewOrContainer)) {
6915 viewOrContainer = viewOrContainer[NEXT];
6916 }
6917 return viewOrContainer;
6918}
6919
6920/**
6921 * @license
6922 * Copyright Google LLC All Rights Reserved.
6923 *
6924 * Use of this source code is governed by an MIT-style license that can be
6925 * found in the LICENSE file at https://angular.io/license
6926 */
6927const unusedValueToPlacateAjd$2 = unusedValueExportToPlacateAjd$8 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3 + unusedValueExportToPlacateAjd$6 + unusedValueExportToPlacateAjd$7;
6928/**
6929 * NOTE: for performance reasons, the possible actions are inlined within the function instead of
6930 * being passed as an argument.
6931 */
6932function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) {
6933 // If this slot was allocated for a text node dynamically created by i18n, the text node itself
6934 // won't be created until i18nApply() in the update block, so this node should be skipped.
6935 // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor"
6936 // in `i18n_spec.ts`.
6937 if (lNodeToHandle != null) {
6938 let lContainer;
6939 let isComponent = false;
6940 // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is
6941 // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if
6942 // it has LContainer so that we can process all of those cases appropriately.
6943 if (isLContainer(lNodeToHandle)) {
6944 lContainer = lNodeToHandle;
6945 }
6946 else if (isLView(lNodeToHandle)) {
6947 isComponent = true;
6948 ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');
6949 lNodeToHandle = lNodeToHandle[HOST];
6950 }
6951 const rNode = unwrapRNode(lNodeToHandle);
6952 ngDevMode && !isProceduralRenderer(renderer) && assertDomNode(rNode);
6953 if (action === 0 /* Create */ && parent !== null) {
6954 if (beforeNode == null) {
6955 nativeAppendChild(renderer, parent, rNode);
6956 }
6957 else {
6958 nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
6959 }
6960 }
6961 else if (action === 1 /* Insert */ && parent !== null) {
6962 nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
6963 }
6964 else if (action === 2 /* Detach */) {
6965 nativeRemoveNode(renderer, rNode, isComponent);
6966 }
6967 else if (action === 3 /* Destroy */) {
6968 ngDevMode && ngDevMode.rendererDestroyNode++;
6969 renderer.destroyNode(rNode);
6970 }
6971 if (lContainer != null) {
6972 applyContainer(renderer, action, lContainer, parent, beforeNode);
6973 }
6974 }
6975}
6976function createTextNode(renderer, value) {
6977 ngDevMode && ngDevMode.rendererCreateTextNode++;
6978 ngDevMode && ngDevMode.rendererSetText++;
6979 return isProceduralRenderer(renderer) ? renderer.createText(value) :
6980 renderer.createTextNode(value);
6981}
6982function updateTextNode(renderer, rNode, value) {
6983 ngDevMode && ngDevMode.rendererSetText++;
6984 isProceduralRenderer(renderer) ? renderer.setValue(rNode, value) : rNode.textContent = value;
6985}
6986function createCommentNode(renderer, value) {
6987 ngDevMode && ngDevMode.rendererCreateComment++;
6988 // isProceduralRenderer check is not needed because both `Renderer2` and `Renderer3` have the same
6989 // method name.
6990 return renderer.createComment(escapeCommentText(value));
6991}
6992/**
6993 * Creates a native element from a tag name, using a renderer.
6994 * @param renderer A renderer to use
6995 * @param name the tag name
6996 * @param namespace Optional namespace for element.
6997 * @returns the element created
6998 */
6999function createElementNode(renderer, name, namespace) {
7000 ngDevMode && ngDevMode.rendererCreateElement++;
7001 if (isProceduralRenderer(renderer)) {
7002 return renderer.createElement(name, namespace);
7003 }
7004 else {
7005 return namespace === null ? renderer.createElement(name) :
7006 renderer.createElementNS(namespace, name);
7007 }
7008}
7009/**
7010 * Removes all DOM elements associated with a view.
7011 *
7012 * Because some root nodes of the view may be containers, we sometimes need
7013 * to propagate deeply into the nested containers to remove all elements in the
7014 * views beneath it.
7015 *
7016 * @param tView The `TView' of the `LView` from which elements should be added or removed
7017 * @param lView The view from which elements should be added or removed
7018 */
7019function removeViewFromContainer(tView, lView) {
7020 const renderer = lView[RENDERER];
7021 applyView(tView, lView, renderer, 2 /* Detach */, null, null);
7022 lView[HOST] = null;
7023 lView[T_HOST] = null;
7024}
7025/**
7026 * Adds all DOM elements associated with a view.
7027 *
7028 * Because some root nodes of the view may be containers, we sometimes need
7029 * to propagate deeply into the nested containers to add all elements in the
7030 * views beneath it.
7031 *
7032 * @param tView The `TView' of the `LView` from which elements should be added or removed
7033 * @param parentTNode The `TNode` where the `LView` should be attached to.
7034 * @param renderer Current renderer to use for DOM manipulations.
7035 * @param lView The view from which elements should be added or removed
7036 * @param parentNativeNode The parent `RElement` where it should be inserted into.
7037 * @param beforeNode The node before which elements should be added, if insert mode
7038 */
7039function addViewToContainer(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
7040 lView[HOST] = parentNativeNode;
7041 lView[T_HOST] = parentTNode;
7042 applyView(tView, lView, renderer, 1 /* Insert */, parentNativeNode, beforeNode);
7043}
7044/**
7045 * Detach a `LView` from the DOM by detaching its nodes.
7046 *
7047 * @param tView The `TView' of the `LView` to be detached
7048 * @param lView the `LView` to be detached.
7049 */
7050function renderDetachView$1(tView, lView) {
7051 applyView(tView, lView, lView[RENDERER], 2 /* Detach */, null, null);
7052}
7053/**
7054 * Traverses down and up the tree of views and containers to remove listeners and
7055 * call onDestroy callbacks.
7056 *
7057 * Notes:
7058 * - Because it's used for onDestroy calls, it needs to be bottom-up.
7059 * - Must process containers instead of their views to avoid splicing
7060 * when views are destroyed and re-added.
7061 * - Using a while loop because it's faster than recursion
7062 * - Destroy only called on movement to sibling or movement to parent (laterally or up)
7063 *
7064 * @param rootView The view to destroy
7065 */
7066function destroyViewTree(rootView) {
7067 // If the view has no children, we can clean it up and return early.
7068 let lViewOrLContainer = rootView[CHILD_HEAD];
7069 if (!lViewOrLContainer) {
7070 return cleanUpView(rootView[TVIEW], rootView);
7071 }
7072 while (lViewOrLContainer) {
7073 let next = null;
7074 if (isLView(lViewOrLContainer)) {
7075 // If LView, traverse down to child.
7076 next = lViewOrLContainer[CHILD_HEAD];
7077 }
7078 else {
7079 ngDevMode && assertLContainer(lViewOrLContainer);
7080 // If container, traverse down to its first LView.
7081 const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
7082 if (firstView)
7083 next = firstView;
7084 }
7085 if (!next) {
7086 // Only clean up view when moving to the side or up, as destroy hooks
7087 // should be called in order from the bottom up.
7088 while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) {
7089 if (isLView(lViewOrLContainer)) {
7090 cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7091 }
7092 lViewOrLContainer = lViewOrLContainer[PARENT];
7093 }
7094 if (lViewOrLContainer === null)
7095 lViewOrLContainer = rootView;
7096 if (isLView(lViewOrLContainer)) {
7097 cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7098 }
7099 next = lViewOrLContainer && lViewOrLContainer[NEXT];
7100 }
7101 lViewOrLContainer = next;
7102 }
7103}
7104/**
7105 * Inserts a view into a container.
7106 *
7107 * This adds the view to the container's array of active views in the correct
7108 * position. It also adds the view's elements to the DOM if the container isn't a
7109 * root node of another view (in that case, the view's elements will be added when
7110 * the container's parent view is added later).
7111 *
7112 * @param tView The `TView' of the `LView` to insert
7113 * @param lView The view to insert
7114 * @param lContainer The container into which the view should be inserted
7115 * @param index Which index in the container to insert the child view into
7116 */
7117function insertView(tView, lView, lContainer, index) {
7118 ngDevMode && assertLView(lView);
7119 ngDevMode && assertLContainer(lContainer);
7120 const indexInContainer = CONTAINER_HEADER_OFFSET + index;
7121 const containerLength = lContainer.length;
7122 if (index > 0) {
7123 // This is a new view, we need to add it to the children.
7124 lContainer[indexInContainer - 1][NEXT] = lView;
7125 }
7126 if (index < containerLength - CONTAINER_HEADER_OFFSET) {
7127 lView[NEXT] = lContainer[indexInContainer];
7128 addToArray(lContainer, CONTAINER_HEADER_OFFSET + index, lView);
7129 }
7130 else {
7131 lContainer.push(lView);
7132 lView[NEXT] = null;
7133 }
7134 lView[PARENT] = lContainer;
7135 // track views where declaration and insertion points are different
7136 const declarationLContainer = lView[DECLARATION_LCONTAINER];
7137 if (declarationLContainer !== null && lContainer !== declarationLContainer) {
7138 trackMovedView(declarationLContainer, lView);
7139 }
7140 // notify query that a new view has been added
7141 const lQueries = lView[QUERIES];
7142 if (lQueries !== null) {
7143 lQueries.insertView(tView);
7144 }
7145 // Sets the attached flag
7146 lView[FLAGS] |= 128 /* Attached */;
7147}
7148/**
7149 * Track views created from the declaration container (TemplateRef) and inserted into a
7150 * different LContainer.
7151 */
7152function trackMovedView(declarationContainer, lView) {
7153 ngDevMode && assertDefined(lView, 'LView required');
7154 ngDevMode && assertLContainer(declarationContainer);
7155 const movedViews = declarationContainer[MOVED_VIEWS];
7156 const insertedLContainer = lView[PARENT];
7157 ngDevMode && assertLContainer(insertedLContainer);
7158 const insertedComponentLView = insertedLContainer[PARENT][DECLARATION_COMPONENT_VIEW];
7159 ngDevMode && assertDefined(insertedComponentLView, 'Missing insertedComponentLView');
7160 const declaredComponentLView = lView[DECLARATION_COMPONENT_VIEW];
7161 ngDevMode && assertDefined(declaredComponentLView, 'Missing declaredComponentLView');
7162 if (declaredComponentLView !== insertedComponentLView) {
7163 // At this point the declaration-component is not same as insertion-component; this means that
7164 // this is a transplanted view. Mark the declared lView as having transplanted views so that
7165 // those views can participate in CD.
7166 declarationContainer[HAS_TRANSPLANTED_VIEWS] = true;
7167 }
7168 if (movedViews === null) {
7169 declarationContainer[MOVED_VIEWS] = [lView];
7170 }
7171 else {
7172 movedViews.push(lView);
7173 }
7174}
7175function detachMovedView(declarationContainer, lView) {
7176 ngDevMode && assertLContainer(declarationContainer);
7177 ngDevMode &&
7178 assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');
7179 const movedViews = declarationContainer[MOVED_VIEWS];
7180 const declarationViewIndex = movedViews.indexOf(lView);
7181 const insertionLContainer = lView[PARENT];
7182 ngDevMode && assertLContainer(insertionLContainer);
7183 // If the view was marked for refresh but then detached before it was checked (where the flag
7184 // would be cleared and the counter decremented), we need to decrement the view counter here
7185 // instead.
7186 if (lView[FLAGS] & 1024 /* RefreshTransplantedView */) {
7187 lView[FLAGS] &= ~1024 /* RefreshTransplantedView */;
7188 updateTransplantedViewCount(insertionLContainer, -1);
7189 }
7190 movedViews.splice(declarationViewIndex, 1);
7191}
7192/**
7193 * Detaches a view from a container.
7194 *
7195 * This method removes the view from the container's array of active views. It also
7196 * removes the view's elements from the DOM.
7197 *
7198 * @param lContainer The container from which to detach a view
7199 * @param removeIndex The index of the view to detach
7200 * @returns Detached LView instance.
7201 */
7202function detachView(lContainer, removeIndex) {
7203 if (lContainer.length <= CONTAINER_HEADER_OFFSET)
7204 return;
7205 const indexInContainer = CONTAINER_HEADER_OFFSET + removeIndex;
7206 const viewToDetach = lContainer[indexInContainer];
7207 if (viewToDetach) {
7208 const declarationLContainer = viewToDetach[DECLARATION_LCONTAINER];
7209 if (declarationLContainer !== null && declarationLContainer !== lContainer) {
7210 detachMovedView(declarationLContainer, viewToDetach);
7211 }
7212 if (removeIndex > 0) {
7213 lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT];
7214 }
7215 const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);
7216 removeViewFromContainer(viewToDetach[TVIEW], viewToDetach);
7217 // notify query that a view has been removed
7218 const lQueries = removedLView[QUERIES];
7219 if (lQueries !== null) {
7220 lQueries.detachView(removedLView[TVIEW]);
7221 }
7222 viewToDetach[PARENT] = null;
7223 viewToDetach[NEXT] = null;
7224 // Unsets the attached flag
7225 viewToDetach[FLAGS] &= ~128 /* Attached */;
7226 }
7227 return viewToDetach;
7228}
7229/**
7230 * A standalone function which destroys an LView,
7231 * conducting clean up (e.g. removing listeners, calling onDestroys).
7232 *
7233 * @param tView The `TView' of the `LView` to be destroyed
7234 * @param lView The view to be destroyed.
7235 */
7236function destroyLView(tView, lView) {
7237 if (!(lView[FLAGS] & 256 /* Destroyed */)) {
7238 const renderer = lView[RENDERER];
7239 if (isProceduralRenderer(renderer) && renderer.destroyNode) {
7240 applyView(tView, lView, renderer, 3 /* Destroy */, null, null);
7241 }
7242 destroyViewTree(lView);
7243 }
7244}
7245/**
7246 * Calls onDestroys hooks for all directives and pipes in a given view and then removes all
7247 * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
7248 * can be propagated to @Output listeners.
7249 *
7250 * @param tView `TView` for the `LView` to clean up.
7251 * @param lView The LView to clean up
7252 */
7253function cleanUpView(tView, lView) {
7254 if (!(lView[FLAGS] & 256 /* Destroyed */)) {
7255 // Usually the Attached flag is removed when the view is detached from its parent, however
7256 // if it's a root view, the flag won't be unset hence why we're also removing on destroy.
7257 lView[FLAGS] &= ~128 /* Attached */;
7258 // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
7259 // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
7260 // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
7261 // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
7262 // really more of an "afterDestroy" hook if you think about it.
7263 lView[FLAGS] |= 256 /* Destroyed */;
7264 executeOnDestroys(tView, lView);
7265 processCleanups(tView, lView);
7266 // For component views only, the local renderer is destroyed at clean up time.
7267 if (lView[TVIEW].type === 1 /* Component */ && isProceduralRenderer(lView[RENDERER])) {
7268 ngDevMode && ngDevMode.rendererDestroy++;
7269 lView[RENDERER].destroy();
7270 }
7271 const declarationContainer = lView[DECLARATION_LCONTAINER];
7272 // we are dealing with an embedded view that is still inserted into a container
7273 if (declarationContainer !== null && isLContainer(lView[PARENT])) {
7274 // and this is a projected view
7275 if (declarationContainer !== lView[PARENT]) {
7276 detachMovedView(declarationContainer, lView);
7277 }
7278 // For embedded views still attached to a container: remove query result from this view.
7279 const lQueries = lView[QUERIES];
7280 if (lQueries !== null) {
7281 lQueries.detachView(tView);
7282 }
7283 }
7284 }
7285}
7286/** Removes listeners and unsubscribes from output subscriptions */
7287function processCleanups(tView, lView) {
7288 const tCleanup = tView.cleanup;
7289 const lCleanup = lView[CLEANUP];
7290 // `LCleanup` contains both share information with `TCleanup` as well as instance specific
7291 // information appended at the end. We need to know where the end of the `TCleanup` information
7292 // is, and we track this with `lastLCleanupIndex`.
7293 let lastLCleanupIndex = -1;
7294 if (tCleanup !== null) {
7295 for (let i = 0; i < tCleanup.length - 1; i += 2) {
7296 if (typeof tCleanup[i] === 'string') {
7297 // This is a native DOM listener
7298 const idxOrTargetGetter = tCleanup[i + 1];
7299 const target = typeof idxOrTargetGetter === 'function' ?
7300 idxOrTargetGetter(lView) :
7301 unwrapRNode(lView[idxOrTargetGetter]);
7302 const listener = lCleanup[lastLCleanupIndex = tCleanup[i + 2]];
7303 const useCaptureOrSubIdx = tCleanup[i + 3];
7304 if (typeof useCaptureOrSubIdx === 'boolean') {
7305 // native DOM listener registered with Renderer3
7306 target.removeEventListener(tCleanup[i], listener, useCaptureOrSubIdx);
7307 }
7308 else {
7309 if (useCaptureOrSubIdx >= 0) {
7310 // unregister
7311 lCleanup[lastLCleanupIndex = useCaptureOrSubIdx]();
7312 }
7313 else {
7314 // Subscription
7315 lCleanup[lastLCleanupIndex = -useCaptureOrSubIdx].unsubscribe();
7316 }
7317 }
7318 i += 2;
7319 }
7320 else {
7321 // This is a cleanup function that is grouped with the index of its context
7322 const context = lCleanup[lastLCleanupIndex = tCleanup[i + 1]];
7323 tCleanup[i].call(context);
7324 }
7325 }
7326 }
7327 if (lCleanup !== null) {
7328 for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
7329 const instanceCleanupFn = lCleanup[i];
7330 ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
7331 instanceCleanupFn();
7332 }
7333 lView[CLEANUP] = null;
7334 }
7335}
7336/** Calls onDestroy hooks for this view */
7337function executeOnDestroys(tView, lView) {
7338 let destroyHooks;
7339 if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
7340 for (let i = 0; i < destroyHooks.length; i += 2) {
7341 const context = lView[destroyHooks[i]];
7342 // Only call the destroy hook if the context has been requested.
7343 if (!(context instanceof NodeInjectorFactory)) {
7344 const toCall = destroyHooks[i + 1];
7345 if (Array.isArray(toCall)) {
7346 for (let j = 0; j < toCall.length; j += 2) {
7347 const callContext = context[toCall[j]];
7348 const hook = toCall[j + 1];
7349 profiler(4 /* LifecycleHookStart */, callContext, hook);
7350 try {
7351 hook.call(callContext);
7352 }
7353 finally {
7354 profiler(5 /* LifecycleHookEnd */, callContext, hook);
7355 }
7356 }
7357 }
7358 else {
7359 profiler(4 /* LifecycleHookStart */, context, toCall);
7360 try {
7361 toCall.call(context);
7362 }
7363 finally {
7364 profiler(5 /* LifecycleHookEnd */, context, toCall);
7365 }
7366 }
7367 }
7368 }
7369 }
7370}
7371/**
7372 * Returns a native element if a node can be inserted into the given parent.
7373 *
7374 * There are two reasons why we may not be able to insert a element immediately.
7375 * - Projection: When creating a child content element of a component, we have to skip the
7376 * insertion because the content of a component will be projected.
7377 * `<component><content>delayed due to projection</content></component>`
7378 * - Parent container is disconnected: This can happen when we are inserting a view into
7379 * parent container, which itself is disconnected. For example the parent container is part
7380 * of a View which has not be inserted or is made for projection but has not been inserted
7381 * into destination.
7382 *
7383 * @param tView: Current `TView`.
7384 * @param tNode: `TNode` for which we wish to retrieve render parent.
7385 * @param lView: Current `LView`.
7386 */
7387function getParentRElement(tView, tNode, lView) {
7388 return getClosestRElement(tView, tNode.parent, lView);
7389}
7390/**
7391 * Get closest `RElement` or `null` if it can't be found.
7392 *
7393 * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.
7394 * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).
7395 * If `TNode` is `null` then return host `RElement`:
7396 * - return `null` if projection
7397 * - return `null` if parent container is disconnected (we have no parent.)
7398 *
7399 * @param tView: Current `TView`.
7400 * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is
7401 * needed).
7402 * @param lView: Current `LView`.
7403 * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)
7404 */
7405function getClosestRElement(tView, tNode, lView) {
7406 let parentTNode = tNode;
7407 // Skip over element and ICU containers as those are represented by a comment node and
7408 // can't be used as a render parent.
7409 while (parentTNode !== null &&
7410 (parentTNode.type & (8 /* ElementContainer */ | 32 /* Icu */))) {
7411 tNode = parentTNode;
7412 parentTNode = tNode.parent;
7413 }
7414 // If the parent tNode is null, then we are inserting across views: either into an embedded view
7415 // or a component view.
7416 if (parentTNode === null) {
7417 // We are inserting a root element of the component view into the component host element and
7418 // it should always be eager.
7419 return lView[HOST];
7420 }
7421 else {
7422 ngDevMode && assertTNodeType(parentTNode, 3 /* AnyRNode */ | 4 /* Container */);
7423 if (parentTNode.flags & 2 /* isComponentHost */) {
7424 ngDevMode && assertTNodeForLView(parentTNode, lView);
7425 const encapsulation = tView.data[parentTNode.directiveStart].encapsulation;
7426 // We've got a parent which is an element in the current view. We just need to verify if the
7427 // parent element is not a component. Component's content nodes are not inserted immediately
7428 // because they will be projected, and so doing insert at this point would be wasteful.
7429 // Since the projection would then move it to its final destination. Note that we can't
7430 // make this assumption when using the Shadow DOM, because the native projection placeholders
7431 // (<content> or <slot>) have to be in place as elements are being inserted.
7432 if (encapsulation === ViewEncapsulation$1.None ||
7433 encapsulation === ViewEncapsulation$1.Emulated) {
7434 return null;
7435 }
7436 }
7437 return getNativeByTNode(parentTNode, lView);
7438 }
7439}
7440/**
7441 * Inserts a native node before another native node for a given parent using {@link Renderer3}.
7442 * This is a utility function that can be used when native nodes were determined - it abstracts an
7443 * actual renderer being used.
7444 */
7445function nativeInsertBefore(renderer, parent, child, beforeNode, isMove) {
7446 ngDevMode && ngDevMode.rendererInsertBefore++;
7447 if (isProceduralRenderer(renderer)) {
7448 renderer.insertBefore(parent, child, beforeNode, isMove);
7449 }
7450 else {
7451 parent.insertBefore(child, beforeNode, isMove);
7452 }
7453}
7454function nativeAppendChild(renderer, parent, child) {
7455 ngDevMode && ngDevMode.rendererAppendChild++;
7456 ngDevMode && assertDefined(parent, 'parent node must be defined');
7457 if (isProceduralRenderer(renderer)) {
7458 renderer.appendChild(parent, child);
7459 }
7460 else {
7461 parent.appendChild(child);
7462 }
7463}
7464function nativeAppendOrInsertBefore(renderer, parent, child, beforeNode, isMove) {
7465 if (beforeNode !== null) {
7466 nativeInsertBefore(renderer, parent, child, beforeNode, isMove);
7467 }
7468 else {
7469 nativeAppendChild(renderer, parent, child);
7470 }
7471}
7472/** Removes a node from the DOM given its native parent. */
7473function nativeRemoveChild(renderer, parent, child, isHostElement) {
7474 if (isProceduralRenderer(renderer)) {
7475 renderer.removeChild(parent, child, isHostElement);
7476 }
7477 else {
7478 parent.removeChild(child);
7479 }
7480}
7481/**
7482 * Returns a native parent of a given native node.
7483 */
7484function nativeParentNode(renderer, node) {
7485 return (isProceduralRenderer(renderer) ? renderer.parentNode(node) : node.parentNode);
7486}
7487/**
7488 * Returns a native sibling of a given native node.
7489 */
7490function nativeNextSibling(renderer, node) {
7491 return isProceduralRenderer(renderer) ? renderer.nextSibling(node) : node.nextSibling;
7492}
7493/**
7494 * Find a node in front of which `currentTNode` should be inserted.
7495 *
7496 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
7497 * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.
7498 *
7499 * @param parentTNode parent `TNode`
7500 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
7501 * @param lView current `LView`
7502 */
7503function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {
7504 return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);
7505}
7506/**
7507 * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into
7508 * account)
7509 *
7510 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
7511 * does not take `TNode.insertBeforeIndex` into account.
7512 *
7513 * @param parentTNode parent `TNode`
7514 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
7515 * @param lView current `LView`
7516 */
7517function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {
7518 if (parentTNode.type & (8 /* ElementContainer */ | 32 /* Icu */)) {
7519 return getNativeByTNode(parentTNode, lView);
7520 }
7521 return null;
7522}
7523/**
7524 * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.
7525 *
7526 * This function will only be set if i18n code runs.
7527 */
7528let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;
7529/**
7530 * Tree shakable boundary for `processI18nInsertBefore` function.
7531 *
7532 * This function will only be set if i18n code runs.
7533 */
7534let _processI18nInsertBefore;
7535function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {
7536 _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;
7537 _processI18nInsertBefore = processI18nInsertBefore;
7538}
7539/**
7540 * Appends the `child` native node (or a collection of nodes) to the `parent`.
7541 *
7542 * @param tView The `TView' to be appended
7543 * @param lView The current LView
7544 * @param childRNode The native child (or children) that should be appended
7545 * @param childTNode The TNode of the child element
7546 */
7547function appendChild(tView, lView, childRNode, childTNode) {
7548 const parentRNode = getParentRElement(tView, childTNode, lView);
7549 const renderer = lView[RENDERER];
7550 const parentTNode = childTNode.parent || lView[T_HOST];
7551 const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);
7552 if (parentRNode != null) {
7553 if (Array.isArray(childRNode)) {
7554 for (let i = 0; i < childRNode.length; i++) {
7555 nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);
7556 }
7557 }
7558 else {
7559 nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
7560 }
7561 }
7562 _processI18nInsertBefore !== undefined &&
7563 _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
7564}
7565/**
7566 * Returns the first native node for a given LView, starting from the provided TNode.
7567 *
7568 * Native nodes are returned in the order in which those appear in the native tree (DOM).
7569 */
7570function getFirstNativeNode(lView, tNode) {
7571 if (tNode !== null) {
7572 ngDevMode &&
7573 assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */ | 32 /* Icu */ | 16 /* Projection */);
7574 const tNodeType = tNode.type;
7575 if (tNodeType & 3 /* AnyRNode */) {
7576 return getNativeByTNode(tNode, lView);
7577 }
7578 else if (tNodeType & 4 /* Container */) {
7579 return getBeforeNodeForView(-1, lView[tNode.index]);
7580 }
7581 else if (tNodeType & 8 /* ElementContainer */) {
7582 const elIcuContainerChild = tNode.child;
7583 if (elIcuContainerChild !== null) {
7584 return getFirstNativeNode(lView, elIcuContainerChild);
7585 }
7586 else {
7587 const rNodeOrLContainer = lView[tNode.index];
7588 if (isLContainer(rNodeOrLContainer)) {
7589 return getBeforeNodeForView(-1, rNodeOrLContainer);
7590 }
7591 else {
7592 return unwrapRNode(rNodeOrLContainer);
7593 }
7594 }
7595 }
7596 else if (tNodeType & 32 /* Icu */) {
7597 let nextRNode = icuContainerIterate(tNode, lView);
7598 let rNode = nextRNode();
7599 // If the ICU container has no nodes, than we use the ICU anchor as the node.
7600 return rNode || unwrapRNode(lView[tNode.index]);
7601 }
7602 else {
7603 const projectionNodes = getProjectionNodes(lView, tNode);
7604 if (projectionNodes !== null) {
7605 if (Array.isArray(projectionNodes)) {
7606 return projectionNodes[0];
7607 }
7608 const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
7609 ngDevMode && assertParentView(parentView);
7610 return getFirstNativeNode(parentView, projectionNodes);
7611 }
7612 else {
7613 return getFirstNativeNode(lView, tNode.next);
7614 }
7615 }
7616 }
7617 return null;
7618}
7619function getProjectionNodes(lView, tNode) {
7620 if (tNode !== null) {
7621 const componentView = lView[DECLARATION_COMPONENT_VIEW];
7622 const componentHost = componentView[T_HOST];
7623 const slotIdx = tNode.projection;
7624 ngDevMode && assertProjectionSlots(lView);
7625 return componentHost.projection[slotIdx];
7626 }
7627 return null;
7628}
7629function getBeforeNodeForView(viewIndexInContainer, lContainer) {
7630 const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;
7631 if (nextViewIndex < lContainer.length) {
7632 const lView = lContainer[nextViewIndex];
7633 const firstTNodeOfView = lView[TVIEW].firstChild;
7634 if (firstTNodeOfView !== null) {
7635 return getFirstNativeNode(lView, firstTNodeOfView);
7636 }
7637 }
7638 return lContainer[NATIVE];
7639}
7640/**
7641 * Removes a native node itself using a given renderer. To remove the node we are looking up its
7642 * parent from the native tree as not all platforms / browsers support the equivalent of
7643 * node.remove().
7644 *
7645 * @param renderer A renderer to be used
7646 * @param rNode The native node that should be removed
7647 * @param isHostElement A flag indicating if a node to be removed is a host of a component.
7648 */
7649function nativeRemoveNode(renderer, rNode, isHostElement) {
7650 ngDevMode && ngDevMode.rendererRemoveNode++;
7651 const nativeParent = nativeParentNode(renderer, rNode);
7652 if (nativeParent) {
7653 nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);
7654 }
7655}
7656/**
7657 * Performs the operation of `action` on the node. Typically this involves inserting or removing
7658 * nodes on the LView or projection boundary.
7659 */
7660function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {
7661 while (tNode != null) {
7662 ngDevMode && assertTNodeForLView(tNode, lView);
7663 ngDevMode &&
7664 assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */ | 16 /* Projection */ | 32 /* Icu */);
7665 const rawSlotValue = lView[tNode.index];
7666 const tNodeType = tNode.type;
7667 if (isProjection) {
7668 if (action === 0 /* Create */) {
7669 rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
7670 tNode.flags |= 4 /* isProjected */;
7671 }
7672 }
7673 if ((tNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
7674 if (tNodeType & 8 /* ElementContainer */) {
7675 applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
7676 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7677 }
7678 else if (tNodeType & 32 /* Icu */) {
7679 const nextRNode = icuContainerIterate(tNode, lView);
7680 let rNode;
7681 while (rNode = nextRNode()) {
7682 applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
7683 }
7684 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7685 }
7686 else if (tNodeType & 16 /* Projection */) {
7687 applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);
7688 }
7689 else {
7690 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 4 /* Container */);
7691 applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7692 }
7693 }
7694 tNode = isProjection ? tNode.projectionNext : tNode.next;
7695 }
7696}
7697function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
7698 applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
7699}
7700/**
7701 * `applyProjection` performs operation on the projection.
7702 *
7703 * Inserting a projection requires us to locate the projected nodes from the parent component. The
7704 * complication is that those nodes themselves could be re-projected from their parent component.
7705 *
7706 * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
7707 * @param lView The `LView` which needs to be inserted, detached, destroyed.
7708 * @param tProjectionNode node to project
7709 */
7710function applyProjection(tView, lView, tProjectionNode) {
7711 const renderer = lView[RENDERER];
7712 const parentRNode = getParentRElement(tView, tProjectionNode, lView);
7713 const parentTNode = tProjectionNode.parent || lView[T_HOST];
7714 let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);
7715 applyProjectionRecursive(renderer, 0 /* Create */, lView, tProjectionNode, parentRNode, beforeNode);
7716}
7717/**
7718 * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,
7719 * detach, destroy)
7720 *
7721 * Inserting a projection requires us to locate the projected nodes from the parent component. The
7722 * complication is that those nodes themselves could be re-projected from their parent component.
7723 *
7724 * @param renderer Render to use
7725 * @param action action to perform (insert, detach, destroy)
7726 * @param lView The LView which needs to be inserted, detached, destroyed.
7727 * @param tProjectionNode node to project
7728 * @param parentRElement parent DOM element for insertion/removal.
7729 * @param beforeNode Before which node the insertions should happen.
7730 */
7731function applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) {
7732 const componentLView = lView[DECLARATION_COMPONENT_VIEW];
7733 const componentNode = componentLView[T_HOST];
7734 ngDevMode &&
7735 assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');
7736 const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection];
7737 if (Array.isArray(nodeToProjectOrRNodes)) {
7738 // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we
7739 // need to support passing projectable nodes, so we cheat and put them in the TNode
7740 // of the Host TView. (Yes we put instance info at the T Level). We can get away with it
7741 // because we know that that TView is not shared and therefore it will not be a problem.
7742 // This should be refactored and cleaned up.
7743 for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {
7744 const rNode = nodeToProjectOrRNodes[i];
7745 applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
7746 }
7747 }
7748 else {
7749 let nodeToProject = nodeToProjectOrRNodes;
7750 const projectedComponentLView = componentLView[PARENT];
7751 applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
7752 }
7753}
7754/**
7755 * `applyContainer` performs an operation on the container and its views as specified by
7756 * `action` (insert, detach, destroy)
7757 *
7758 * Inserting a Container is complicated by the fact that the container may have Views which
7759 * themselves have containers or projections.
7760 *
7761 * @param renderer Renderer to use
7762 * @param action action to perform (insert, detach, destroy)
7763 * @param lContainer The LContainer which needs to be inserted, detached, destroyed.
7764 * @param parentRElement parent DOM element for insertion/removal.
7765 * @param beforeNode Before which node the insertions should happen.
7766 */
7767function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {
7768 ngDevMode && assertLContainer(lContainer);
7769 const anchor = lContainer[NATIVE]; // LContainer has its own before node.
7770 const native = unwrapRNode(lContainer);
7771 // An LContainer can be created dynamically on any node by injecting ViewContainerRef.
7772 // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor
7773 // node (comment in the DOM) that will be different from the LContainer's host node. In this
7774 // particular case we need to execute action on 2 nodes:
7775 // - container's host node (this is done in the executeActionOnElementOrContainer)
7776 // - container's host node (this is done here)
7777 if (anchor !== native) {
7778 // This is very strange to me (Misko). I would expect that the native is same as anchor. I
7779 // don't see a reason why they should be different, but they are.
7780 //
7781 // If they are we need to process the second anchor as well.
7782 applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
7783 }
7784 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
7785 const lView = lContainer[i];
7786 applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);
7787 }
7788}
7789/**
7790 * Writes class/style to element.
7791 *
7792 * @param renderer Renderer to use.
7793 * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)
7794 * @param rNode The Node to write to.
7795 * @param prop Property to write to. This would be the class/style name.
7796 * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add
7797 * otherwise).
7798 */
7799function applyStyling(renderer, isClassBased, rNode, prop, value) {
7800 const isProcedural = isProceduralRenderer(renderer);
7801 if (isClassBased) {
7802 // We actually want JS true/false here because any truthy value should add the class
7803 if (!value) {
7804 ngDevMode && ngDevMode.rendererRemoveClass++;
7805 if (isProcedural) {
7806 renderer.removeClass(rNode, prop);
7807 }
7808 else {
7809 rNode.classList.remove(prop);
7810 }
7811 }
7812 else {
7813 ngDevMode && ngDevMode.rendererAddClass++;
7814 if (isProcedural) {
7815 renderer.addClass(rNode, prop);
7816 }
7817 else {
7818 ngDevMode && assertDefined(rNode.classList, 'HTMLElement expected');
7819 rNode.classList.add(prop);
7820 }
7821 }
7822 }
7823 else {
7824 let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;
7825 if (value == null /** || value === undefined */) {
7826 ngDevMode && ngDevMode.rendererRemoveStyle++;
7827 if (isProcedural) {
7828 renderer.removeStyle(rNode, prop, flags);
7829 }
7830 else {
7831 rNode.style.removeProperty(prop);
7832 }
7833 }
7834 else {
7835 // A value is important if it ends with `!important`. The style
7836 // parser strips any semicolons at the end of the value.
7837 const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;
7838 if (isImportant) {
7839 // !important has to be stripped from the value for it to be valid.
7840 value = value.slice(0, -10);
7841 flags |= RendererStyleFlags2.Important;
7842 }
7843 ngDevMode && ngDevMode.rendererSetStyle++;
7844 if (isProcedural) {
7845 renderer.setStyle(rNode, prop, value, flags);
7846 }
7847 else {
7848 ngDevMode && assertDefined(rNode.style, 'HTMLElement expected');
7849 rNode.style.setProperty(prop, value, isImportant ? 'important' : '');
7850 }
7851 }
7852 }
7853}
7854/**
7855 * Write `cssText` to `RElement`.
7856 *
7857 * This function does direct write without any reconciliation. Used for writing initial values, so
7858 * that static styling values do not pull in the style parser.
7859 *
7860 * @param renderer Renderer to use
7861 * @param element The element which needs to be updated.
7862 * @param newValue The new class list to write.
7863 */
7864function writeDirectStyle(renderer, element, newValue) {
7865 ngDevMode && assertString(newValue, '\'newValue\' should be a string');
7866 if (isProceduralRenderer(renderer)) {
7867 renderer.setAttribute(element, 'style', newValue);
7868 }
7869 else {
7870 element.style.cssText = newValue;
7871 }
7872 ngDevMode && ngDevMode.rendererSetStyle++;
7873}
7874/**
7875 * Write `className` to `RElement`.
7876 *
7877 * This function does direct write without any reconciliation. Used for writing initial values, so
7878 * that static styling values do not pull in the style parser.
7879 *
7880 * @param renderer Renderer to use
7881 * @param element The element which needs to be updated.
7882 * @param newValue The new class list to write.
7883 */
7884function writeDirectClass(renderer, element, newValue) {
7885 ngDevMode && assertString(newValue, '\'newValue\' should be a string');
7886 if (isProceduralRenderer(renderer)) {
7887 if (newValue === '') {
7888 // There are tests in `google3` which expect `element.getAttribute('class')` to be `null`.
7889 renderer.removeAttribute(element, 'class');
7890 }
7891 else {
7892 renderer.setAttribute(element, 'class', newValue);
7893 }
7894 }
7895 else {
7896 element.className = newValue;
7897 }
7898 ngDevMode && ngDevMode.rendererSetClassName++;
7899}
7900
7901/**
7902 * @license
7903 * Copyright Google LLC All Rights Reserved.
7904 *
7905 * Use of this source code is governed by an MIT-style license that can be
7906 * found in the LICENSE file at https://angular.io/license
7907 */
7908/**
7909 * Returns an index of `classToSearch` in `className` taking token boundaries into account.
7910 *
7911 * `classIndexOf('AB A', 'A', 0)` will be 3 (not 0 since `AB!==A`)
7912 *
7913 * @param className A string containing classes (whitespace separated)
7914 * @param classToSearch A class name to locate
7915 * @param startingIndex Starting location of search
7916 * @returns an index of the located class (or -1 if not found)
7917 */
7918function classIndexOf(className, classToSearch, startingIndex) {
7919 ngDevMode && assertNotEqual(classToSearch, '', 'can not look for "" string.');
7920 let end = className.length;
7921 while (true) {
7922 const foundIndex = className.indexOf(classToSearch, startingIndex);
7923 if (foundIndex === -1)
7924 return foundIndex;
7925 if (foundIndex === 0 || className.charCodeAt(foundIndex - 1) <= 32 /* SPACE */) {
7926 // Ensure that it has leading whitespace
7927 const length = classToSearch.length;
7928 if (foundIndex + length === end ||
7929 className.charCodeAt(foundIndex + length) <= 32 /* SPACE */) {
7930 // Ensure that it has trailing whitespace
7931 return foundIndex;
7932 }
7933 }
7934 // False positive, keep searching from where we left off.
7935 startingIndex = foundIndex + 1;
7936 }
7937}
7938
7939/**
7940 * @license
7941 * Copyright Google LLC All Rights Reserved.
7942 *
7943 * Use of this source code is governed by an MIT-style license that can be
7944 * found in the LICENSE file at https://angular.io/license
7945 */
7946const unusedValueToPlacateAjd$1 = unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd$3;
7947const NG_TEMPLATE_SELECTOR = 'ng-template';
7948/**
7949 * Search the `TAttributes` to see if it contains `cssClassToMatch` (case insensitive)
7950 *
7951 * @param attrs `TAttributes` to search through.
7952 * @param cssClassToMatch class to match (lowercase)
7953 * @param isProjectionMode Whether or not class matching should look into the attribute `class` in
7954 * addition to the `AttributeMarker.Classes`.
7955 */
7956function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
7957 // TODO(misko): The fact that this function needs to know about `isProjectionMode` seems suspect.
7958 // It is strange to me that sometimes the class information comes in form of `class` attribute
7959 // and sometimes in form of `AttributeMarker.Classes`. Some investigation is needed to determine
7960 // if that is the right behavior.
7961 ngDevMode &&
7962 assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
7963 let i = 0;
7964 while (i < attrs.length) {
7965 let item = attrs[i++];
7966 if (isProjectionMode && item === 'class') {
7967 item = attrs[i];
7968 if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
7969 return true;
7970 }
7971 }
7972 else if (item === 1 /* Classes */) {
7973 // We found the classes section. Start searching for the class.
7974 while (i < attrs.length && typeof (item = attrs[i++]) == 'string') {
7975 // while we have strings
7976 if (item.toLowerCase() === cssClassToMatch)
7977 return true;
7978 }
7979 return false;
7980 }
7981 }
7982 return false;
7983}
7984/**
7985 * Checks whether the `tNode` represents an inline template (e.g. `*ngFor`).
7986 *
7987 * @param tNode current TNode
7988 */
7989function isInlineTemplate(tNode) {
7990 return tNode.type === 4 /* Container */ && tNode.value !== NG_TEMPLATE_SELECTOR;
7991}
7992/**
7993 * Function that checks whether a given tNode matches tag-based selector and has a valid type.
7994 *
7995 * Matching can be performed in 2 modes: projection mode (when we project nodes) and regular
7996 * directive matching mode:
7997 * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is
7998 * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a
7999 * tag name was extracted from * syntax so we would match the same directive twice);
8000 * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing
8001 * (applicable to TNodeType.Container only).
8002 */
8003function hasTagAndTypeMatch(tNode, currentSelector, isProjectionMode) {
8004 const tagNameToCompare = tNode.type === 4 /* Container */ && !isProjectionMode ? NG_TEMPLATE_SELECTOR : tNode.value;
8005 return currentSelector === tagNameToCompare;
8006}
8007/**
8008 * A utility function to match an Ivy node static data against a simple CSS selector
8009 *
8010 * @param node static data of the node to match
8011 * @param selector The selector to try matching against the node.
8012 * @param isProjectionMode if `true` we are matching for content projection, otherwise we are doing
8013 * directive matching.
8014 * @returns true if node matches the selector.
8015 */
8016function isNodeMatchingSelector(tNode, selector, isProjectionMode) {
8017 ngDevMode && assertDefined(selector[0], 'Selector should have a tag name');
8018 let mode = 4 /* ELEMENT */;
8019 const nodeAttrs = tNode.attrs || [];
8020 // Find the index of first attribute that has no value, only a name.
8021 const nameOnlyMarkerIdx = getNameOnlyMarkerIndex(nodeAttrs);
8022 // When processing ":not" selectors, we skip to the next ":not" if the
8023 // current one doesn't match
8024 let skipToNextSelector = false;
8025 for (let i = 0; i < selector.length; i++) {
8026 const current = selector[i];
8027 if (typeof current === 'number') {
8028 // If we finish processing a :not selector and it hasn't failed, return false
8029 if (!skipToNextSelector && !isPositive(mode) && !isPositive(current)) {
8030 return false;
8031 }
8032 // If we are skipping to the next :not() and this mode flag is positive,
8033 // it's a part of the current :not() selector, and we should keep skipping
8034 if (skipToNextSelector && isPositive(current))
8035 continue;
8036 skipToNextSelector = false;
8037 mode = current | (mode & 1 /* NOT */);
8038 continue;
8039 }
8040 if (skipToNextSelector)
8041 continue;
8042 if (mode & 4 /* ELEMENT */) {
8043 mode = 2 /* ATTRIBUTE */ | mode & 1 /* NOT */;
8044 if (current !== '' && !hasTagAndTypeMatch(tNode, current, isProjectionMode) ||
8045 current === '' && selector.length === 1) {
8046 if (isPositive(mode))
8047 return false;
8048 skipToNextSelector = true;
8049 }
8050 }
8051 else {
8052 const selectorAttrValue = mode & 8 /* CLASS */ ? current : selector[++i];
8053 // special case for matching against classes when a tNode has been instantiated with
8054 // class and style values as separate attribute values (e.g. ['title', CLASS, 'foo'])
8055 if ((mode & 8 /* CLASS */) && tNode.attrs !== null) {
8056 if (!isCssClassMatching(tNode.attrs, selectorAttrValue, isProjectionMode)) {
8057 if (isPositive(mode))
8058 return false;
8059 skipToNextSelector = true;
8060 }
8061 continue;
8062 }
8063 const attrName = (mode & 8 /* CLASS */) ? 'class' : current;
8064 const attrIndexInNode = findAttrIndexInNode(attrName, nodeAttrs, isInlineTemplate(tNode), isProjectionMode);
8065 if (attrIndexInNode === -1) {
8066 if (isPositive(mode))
8067 return false;
8068 skipToNextSelector = true;
8069 continue;
8070 }
8071 if (selectorAttrValue !== '') {
8072 let nodeAttrValue;
8073 if (attrIndexInNode > nameOnlyMarkerIdx) {
8074 nodeAttrValue = '';
8075 }
8076 else {
8077 ngDevMode &&
8078 assertNotEqual(nodeAttrs[attrIndexInNode], 0 /* NamespaceURI */, 'We do not match directives on namespaced attributes');
8079 // we lowercase the attribute value to be able to match
8080 // selectors without case-sensitivity
8081 // (selectors are already in lowercase when generated)
8082 nodeAttrValue = nodeAttrs[attrIndexInNode + 1].toLowerCase();
8083 }
8084 const compareAgainstClassName = mode & 8 /* CLASS */ ? nodeAttrValue : null;
8085 if (compareAgainstClassName &&
8086 classIndexOf(compareAgainstClassName, selectorAttrValue, 0) !== -1 ||
8087 mode & 2 /* ATTRIBUTE */ && selectorAttrValue !== nodeAttrValue) {
8088 if (isPositive(mode))
8089 return false;
8090 skipToNextSelector = true;
8091 }
8092 }
8093 }
8094 }
8095 return isPositive(mode) || skipToNextSelector;
8096}
8097function isPositive(mode) {
8098 return (mode & 1 /* NOT */) === 0;
8099}
8100/**
8101 * Examines the attribute's definition array for a node to find the index of the
8102 * attribute that matches the given `name`.
8103 *
8104 * NOTE: This will not match namespaced attributes.
8105 *
8106 * Attribute matching depends upon `isInlineTemplate` and `isProjectionMode`.
8107 * The following table summarizes which types of attributes we attempt to match:
8108 *
8109 * ===========================================================================================================
8110 * Modes | Normal Attributes | Bindings Attributes | Template Attributes | I18n
8111 * Attributes
8112 * ===========================================================================================================
8113 * Inline + Projection | YES | YES | NO | YES
8114 * -----------------------------------------------------------------------------------------------------------
8115 * Inline + Directive | NO | NO | YES | NO
8116 * -----------------------------------------------------------------------------------------------------------
8117 * Non-inline + Projection | YES | YES | NO | YES
8118 * -----------------------------------------------------------------------------------------------------------
8119 * Non-inline + Directive | YES | YES | NO | YES
8120 * ===========================================================================================================
8121 *
8122 * @param name the name of the attribute to find
8123 * @param attrs the attribute array to examine
8124 * @param isInlineTemplate true if the node being matched is an inline template (e.g. `*ngFor`)
8125 * rather than a manually expanded template node (e.g `<ng-template>`).
8126 * @param isProjectionMode true if we are matching against content projection otherwise we are
8127 * matching against directives.
8128 */
8129function findAttrIndexInNode(name, attrs, isInlineTemplate, isProjectionMode) {
8130 if (attrs === null)
8131 return -1;
8132 let i = 0;
8133 if (isProjectionMode || !isInlineTemplate) {
8134 let bindingsMode = false;
8135 while (i < attrs.length) {
8136 const maybeAttrName = attrs[i];
8137 if (maybeAttrName === name) {
8138 return i;
8139 }
8140 else if (maybeAttrName === 3 /* Bindings */ || maybeAttrName === 6 /* I18n */) {
8141 bindingsMode = true;
8142 }
8143 else if (maybeAttrName === 1 /* Classes */ || maybeAttrName === 2 /* Styles */) {
8144 let value = attrs[++i];
8145 // We should skip classes here because we have a separate mechanism for
8146 // matching classes in projection mode.
8147 while (typeof value === 'string') {
8148 value = attrs[++i];
8149 }
8150 continue;
8151 }
8152 else if (maybeAttrName === 4 /* Template */) {
8153 // We do not care about Template attributes in this scenario.
8154 break;
8155 }
8156 else if (maybeAttrName === 0 /* NamespaceURI */) {
8157 // Skip the whole namespaced attribute and value. This is by design.
8158 i += 4;
8159 continue;
8160 }
8161 // In binding mode there are only names, rather than name-value pairs.
8162 i += bindingsMode ? 1 : 2;
8163 }
8164 // We did not match the attribute
8165 return -1;
8166 }
8167 else {
8168 return matchTemplateAttribute(attrs, name);
8169 }
8170}
8171function isNodeMatchingSelectorList(tNode, selector, isProjectionMode = false) {
8172 for (let i = 0; i < selector.length; i++) {
8173 if (isNodeMatchingSelector(tNode, selector[i], isProjectionMode)) {
8174 return true;
8175 }
8176 }
8177 return false;
8178}
8179function getProjectAsAttrValue(tNode) {
8180 const nodeAttrs = tNode.attrs;
8181 if (nodeAttrs != null) {
8182 const ngProjectAsAttrIdx = nodeAttrs.indexOf(5 /* ProjectAs */);
8183 // only check for ngProjectAs in attribute names, don't accidentally match attribute's value
8184 // (attribute names are stored at even indexes)
8185 if ((ngProjectAsAttrIdx & 1) === 0) {
8186 return nodeAttrs[ngProjectAsAttrIdx + 1];
8187 }
8188 }
8189 return null;
8190}
8191function getNameOnlyMarkerIndex(nodeAttrs) {
8192 for (let i = 0; i < nodeAttrs.length; i++) {
8193 const nodeAttr = nodeAttrs[i];
8194 if (isNameOnlyAttributeMarker(nodeAttr)) {
8195 return i;
8196 }
8197 }
8198 return nodeAttrs.length;
8199}
8200function matchTemplateAttribute(attrs, name) {
8201 let i = attrs.indexOf(4 /* Template */);
8202 if (i > -1) {
8203 i++;
8204 while (i < attrs.length) {
8205 const attr = attrs[i];
8206 // Return in case we checked all template attrs and are switching to the next section in the
8207 // attrs array (that starts with a number that represents an attribute marker).
8208 if (typeof attr === 'number')
8209 return -1;
8210 if (attr === name)
8211 return i;
8212 i++;
8213 }
8214 }
8215 return -1;
8216}
8217/**
8218 * Checks whether a selector is inside a CssSelectorList
8219 * @param selector Selector to be checked.
8220 * @param list List in which to look for the selector.
8221 */
8222function isSelectorInSelectorList(selector, list) {
8223 selectorListLoop: for (let i = 0; i < list.length; i++) {
8224 const currentSelectorInList = list[i];
8225 if (selector.length !== currentSelectorInList.length) {
8226 continue;
8227 }
8228 for (let j = 0; j < selector.length; j++) {
8229 if (selector[j] !== currentSelectorInList[j]) {
8230 continue selectorListLoop;
8231 }
8232 }
8233 return true;
8234 }
8235 return false;
8236}
8237function maybeWrapInNotSelector(isNegativeMode, chunk) {
8238 return isNegativeMode ? ':not(' + chunk.trim() + ')' : chunk;
8239}
8240function stringifyCSSSelector(selector) {
8241 let result = selector[0];
8242 let i = 1;
8243 let mode = 2 /* ATTRIBUTE */;
8244 let currentChunk = '';
8245 let isNegativeMode = false;
8246 while (i < selector.length) {
8247 let valueOrMarker = selector[i];
8248 if (typeof valueOrMarker === 'string') {
8249 if (mode & 2 /* ATTRIBUTE */) {
8250 const attrValue = selector[++i];
8251 currentChunk +=
8252 '[' + valueOrMarker + (attrValue.length > 0 ? '="' + attrValue + '"' : '') + ']';
8253 }
8254 else if (mode & 8 /* CLASS */) {
8255 currentChunk += '.' + valueOrMarker;
8256 }
8257 else if (mode & 4 /* ELEMENT */) {
8258 currentChunk += ' ' + valueOrMarker;
8259 }
8260 }
8261 else {
8262 //
8263 // Append current chunk to the final result in case we come across SelectorFlag, which
8264 // indicates that the previous section of a selector is over. We need to accumulate content
8265 // between flags to make sure we wrap the chunk later in :not() selector if needed, e.g.
8266 // ```
8267 // ['', Flags.CLASS, '.classA', Flags.CLASS | Flags.NOT, '.classB', '.classC']
8268 // ```
8269 // should be transformed to `.classA :not(.classB .classC)`.
8270 //
8271 // Note: for negative selector part, we accumulate content between flags until we find the
8272 // next negative flag. This is needed to support a case where `:not()` rule contains more than
8273 // one chunk, e.g. the following selector:
8274 // ```
8275 // ['', Flags.ELEMENT | Flags.NOT, 'p', Flags.CLASS, 'foo', Flags.CLASS | Flags.NOT, 'bar']
8276 // ```
8277 // should be stringified to `:not(p.foo) :not(.bar)`
8278 //
8279 if (currentChunk !== '' && !isPositive(valueOrMarker)) {
8280 result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
8281 currentChunk = '';
8282 }
8283 mode = valueOrMarker;
8284 // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
8285 // mode is maintained for remaining chunks of a selector.
8286 isNegativeMode = isNegativeMode || !isPositive(mode);
8287 }
8288 i++;
8289 }
8290 if (currentChunk !== '') {
8291 result += maybeWrapInNotSelector(isNegativeMode, currentChunk);
8292 }
8293 return result;
8294}
8295/**
8296 * Generates string representation of CSS selector in parsed form.
8297 *
8298 * ComponentDef and DirectiveDef are generated with the selector in parsed form to avoid doing
8299 * additional parsing at runtime (for example, for directive matching). However in some cases (for
8300 * example, while bootstrapping a component), a string version of the selector is required to query
8301 * for the host element on the page. This function takes the parsed form of a selector and returns
8302 * its string representation.
8303 *
8304 * @param selectorList selector in parsed form
8305 * @returns string representation of a given selector
8306 */
8307function stringifyCSSSelectorList(selectorList) {
8308 return selectorList.map(stringifyCSSSelector).join(',');
8309}
8310/**
8311 * Extracts attributes and classes information from a given CSS selector.
8312 *
8313 * This function is used while creating a component dynamically. In this case, the host element
8314 * (that is created dynamically) should contain attributes and classes specified in component's CSS
8315 * selector.
8316 *
8317 * @param selector CSS selector in parsed form (in a form of array)
8318 * @returns object with `attrs` and `classes` fields that contain extracted information
8319 */
8320function extractAttrsAndClassesFromSelector(selector) {
8321 const attrs = [];
8322 const classes = [];
8323 let i = 1;
8324 let mode = 2 /* ATTRIBUTE */;
8325 while (i < selector.length) {
8326 let valueOrMarker = selector[i];
8327 if (typeof valueOrMarker === 'string') {
8328 if (mode === 2 /* ATTRIBUTE */) {
8329 if (valueOrMarker !== '') {
8330 attrs.push(valueOrMarker, selector[++i]);
8331 }
8332 }
8333 else if (mode === 8 /* CLASS */) {
8334 classes.push(valueOrMarker);
8335 }
8336 }
8337 else {
8338 // According to CssSelector spec, once we come across `SelectorFlags.NOT` flag, the negative
8339 // mode is maintained for remaining chunks of a selector. Since attributes and classes are
8340 // extracted only for "positive" part of the selector, we can stop here.
8341 if (!isPositive(mode))
8342 break;
8343 mode = valueOrMarker;
8344 }
8345 i++;
8346 }
8347 return { attrs, classes };
8348}
8349
8350/**
8351 * @license
8352 * Copyright Google LLC All Rights Reserved.
8353 *
8354 * Use of this source code is governed by an MIT-style license that can be
8355 * found in the LICENSE file at https://angular.io/license
8356 */
8357/** A special value which designates that a value has not changed. */
8358const NO_CHANGE = (typeof ngDevMode === 'undefined' || ngDevMode) ? { __brand__: 'NO_CHANGE' } : {};
8359
8360/**
8361 * @license
8362 * Copyright Google LLC All Rights Reserved.
8363 *
8364 * Use of this source code is governed by an MIT-style license that can be
8365 * found in the LICENSE file at https://angular.io/license
8366 */
8367/**
8368 * Advances to an element for later binding instructions.
8369 *
8370 * Used in conjunction with instructions like {@link property} to act on elements with specified
8371 * indices, for example those created with {@link element} or {@link elementStart}.
8372 *
8373 * ```ts
8374 * (rf: RenderFlags, ctx: any) => {
8375 * if (rf & 1) {
8376 * text(0, 'Hello');
8377 * text(1, 'Goodbye')
8378 * element(2, 'div');
8379 * }
8380 * if (rf & 2) {
8381 * advance(2); // Advance twice to the <div>.
8382 * property('title', 'test');
8383 * }
8384 * }
8385 * ```
8386 * @param delta Number of elements to advance forwards by.
8387 *
8388 * @codeGenApi
8389 */
8390function ɵɵadvance(delta) {
8391 ngDevMode && assertGreaterThan(delta, 0, 'Can only advance forward');
8392 selectIndexInternal(getTView(), getLView(), getSelectedIndex() + delta, isInCheckNoChangesMode());
8393}
8394function selectIndexInternal(tView, lView, index, checkNoChangesMode) {
8395 ngDevMode && assertIndexInDeclRange(lView, index);
8396 // Flush the initial hooks for elements in the view that have been added up to this point.
8397 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
8398 if (!checkNoChangesMode) {
8399 const hooksInitPhaseCompleted = (lView[FLAGS] & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;
8400 if (hooksInitPhaseCompleted) {
8401 const preOrderCheckHooks = tView.preOrderCheckHooks;
8402 if (preOrderCheckHooks !== null) {
8403 executeCheckHooks(lView, preOrderCheckHooks, index);
8404 }
8405 }
8406 else {
8407 const preOrderHooks = tView.preOrderHooks;
8408 if (preOrderHooks !== null) {
8409 executeInitAndCheckHooks(lView, preOrderHooks, 0 /* OnInitHooksToBeRun */, index);
8410 }
8411 }
8412 }
8413 // We must set the selected index *after* running the hooks, because hooks may have side-effects
8414 // that cause other template functions to run, thus updating the selected index, which is global
8415 // state. If we run `setSelectedIndex` *before* we run the hooks, in some cases the selected index
8416 // will be altered by the time we leave the `ɵɵadvance` instruction.
8417 setSelectedIndex(index);
8418}
8419
8420/**
8421 * @license
8422 * Copyright Google LLC All Rights Reserved.
8423 *
8424 * Use of this source code is governed by an MIT-style license that can be
8425 * found in the LICENSE file at https://angular.io/license
8426 */
8427/**
8428 * THIS FILE CONTAINS CODE WHICH SHOULD BE TREE SHAKEN AND NEVER CALLED FROM PRODUCTION CODE!!!
8429 */
8430/**
8431 * Creates an `Array` construction with a given name. This is useful when
8432 * looking for memory consumption to see what time of array it is.
8433 *
8434 *
8435 * @param name Name to give to the constructor
8436 * @returns A subclass of `Array` if possible. This can only be done in
8437 * environments which support `class` construct.
8438 */
8439function createNamedArrayType(name) {
8440 // This should never be called in prod mode, so let's verify that is the case.
8441 if (ngDevMode) {
8442 try {
8443 // If this function were compromised the following could lead to arbitrary
8444 // script execution. We bless it with Trusted Types anyway since this
8445 // function is stripped out of production binaries.
8446 return (newTrustedFunctionForDev('Array', `return class ${name} extends Array{}`))(Array);
8447 }
8448 catch (e) {
8449 // If it does not work just give up and fall back to regular Array.
8450 return Array;
8451 }
8452 }
8453 else {
8454 throw new Error('Looks like we are in \'prod mode\', but we are creating a named Array type, which is wrong! Check your code');
8455 }
8456}
8457
8458/**
8459 * @license
8460 * Copyright Google LLC All Rights Reserved.
8461 *
8462 * Use of this source code is governed by an MIT-style license that can be
8463 * found in the LICENSE file at https://angular.io/license
8464 */
8465function toTStylingRange(prev, next) {
8466 ngDevMode && assertNumberInRange(prev, 0, 32767 /* UNSIGNED_MASK */);
8467 ngDevMode && assertNumberInRange(next, 0, 32767 /* UNSIGNED_MASK */);
8468 return (prev << 17 /* PREV_SHIFT */ | next << 2 /* NEXT_SHIFT */);
8469}
8470function getTStylingRangePrev(tStylingRange) {
8471 ngDevMode && assertNumber(tStylingRange, 'expected number');
8472 return (tStylingRange >> 17 /* PREV_SHIFT */) & 32767 /* UNSIGNED_MASK */;
8473}
8474function getTStylingRangePrevDuplicate(tStylingRange) {
8475 ngDevMode && assertNumber(tStylingRange, 'expected number');
8476 return (tStylingRange & 2 /* PREV_DUPLICATE */) ==
8477 2 /* PREV_DUPLICATE */;
8478}
8479function setTStylingRangePrev(tStylingRange, previous) {
8480 ngDevMode && assertNumber(tStylingRange, 'expected number');
8481 ngDevMode && assertNumberInRange(previous, 0, 32767 /* UNSIGNED_MASK */);
8482 return ((tStylingRange & ~4294836224 /* PREV_MASK */) |
8483 (previous << 17 /* PREV_SHIFT */));
8484}
8485function setTStylingRangePrevDuplicate(tStylingRange) {
8486 ngDevMode && assertNumber(tStylingRange, 'expected number');
8487 return (tStylingRange | 2 /* PREV_DUPLICATE */);
8488}
8489function getTStylingRangeNext(tStylingRange) {
8490 ngDevMode && assertNumber(tStylingRange, 'expected number');
8491 return (tStylingRange & 131068 /* NEXT_MASK */) >> 2 /* NEXT_SHIFT */;
8492}
8493function setTStylingRangeNext(tStylingRange, next) {
8494 ngDevMode && assertNumber(tStylingRange, 'expected number');
8495 ngDevMode && assertNumberInRange(next, 0, 32767 /* UNSIGNED_MASK */);
8496 return ((tStylingRange & ~131068 /* NEXT_MASK */) | //
8497 next << 2 /* NEXT_SHIFT */);
8498}
8499function getTStylingRangeNextDuplicate(tStylingRange) {
8500 ngDevMode && assertNumber(tStylingRange, 'expected number');
8501 return (tStylingRange & 1 /* NEXT_DUPLICATE */) ===
8502 1 /* NEXT_DUPLICATE */;
8503}
8504function setTStylingRangeNextDuplicate(tStylingRange) {
8505 ngDevMode && assertNumber(tStylingRange, 'expected number');
8506 return (tStylingRange | 1 /* NEXT_DUPLICATE */);
8507}
8508function getTStylingRangeTail(tStylingRange) {
8509 ngDevMode && assertNumber(tStylingRange, 'expected number');
8510 const next = getTStylingRangeNext(tStylingRange);
8511 return next === 0 ? getTStylingRangePrev(tStylingRange) : next;
8512}
8513
8514/**
8515 * @license
8516 * Copyright Google LLC All Rights Reserved.
8517 *
8518 * Use of this source code is governed by an MIT-style license that can be
8519 * found in the LICENSE file at https://angular.io/license
8520 */
8521/**
8522 * Patch a `debug` property on top of the existing object.
8523 *
8524 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`
8525 *
8526 * @param obj Object to patch
8527 * @param debug Value to patch
8528 */
8529function attachDebugObject(obj, debug) {
8530 if (ngDevMode) {
8531 Object.defineProperty(obj, 'debug', { value: debug, enumerable: false });
8532 }
8533 else {
8534 throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');
8535 }
8536}
8537/**
8538 * Patch a `debug` property getter on top of the existing object.
8539 *
8540 * NOTE: always call this method with `ngDevMode && attachDebugObject(...)`
8541 *
8542 * @param obj Object to patch
8543 * @param debugGetter Getter returning a value to patch
8544 */
8545function attachDebugGetter(obj, debugGetter) {
8546 if (ngDevMode) {
8547 Object.defineProperty(obj, 'debug', { get: debugGetter, enumerable: false });
8548 }
8549 else {
8550 throw new Error('This method should be guarded with `ngDevMode` so that it can be tree shaken in production!');
8551 }
8552}
8553
8554/**
8555 * @license
8556 * Copyright Google LLC All Rights Reserved.
8557 *
8558 * Use of this source code is governed by an MIT-style license that can be
8559 * found in the LICENSE file at https://angular.io/license
8560 */
8561/*
8562 * This file contains conditionally attached classes which provide human readable (debug) level
8563 * information for `LView`, `LContainer` and other internal data structures. These data structures
8564 * are stored internally as array which makes it very difficult during debugging to reason about the
8565 * current state of the system.
8566 *
8567 * Patching the array with extra property does change the array's hidden class' but it does not
8568 * change the cost of access, therefore this patching should not have significant if any impact in
8569 * `ngDevMode` mode. (see: https://jsperf.com/array-vs-monkey-patch-array)
8570 *
8571 * So instead of seeing:
8572 * ```
8573 * Array(30) [Object, 659, null, …]
8574 * ```
8575 *
8576 * You get to see:
8577 * ```
8578 * LViewDebug {
8579 * views: [...],
8580 * flags: {attached: true, ...}
8581 * nodes: [
8582 * {html: '<div id="123">', ..., nodes: [
8583 * {html: '<span>', ..., nodes: null}
8584 * ]}
8585 * ]
8586 * }
8587 * ```
8588 */
8589let LVIEW_COMPONENT_CACHE;
8590let LVIEW_EMBEDDED_CACHE;
8591let LVIEW_ROOT;
8592let LVIEW_COMPONENT;
8593let LVIEW_EMBEDDED;
8594/**
8595 * This function clones a blueprint and creates LView.
8596 *
8597 * Simple slice will keep the same type, and we need it to be LView
8598 */
8599function cloneToLViewFromTViewBlueprint(tView) {
8600 const debugTView = tView;
8601 const lView = getLViewToClone(debugTView.type, tView.template && tView.template.name);
8602 return lView.concat(tView.blueprint);
8603}
8604class LRootView extends Array {
8605}
8606class LComponentView extends Array {
8607}
8608class LEmbeddedView extends Array {
8609}
8610function getLViewToClone(type, name) {
8611 switch (type) {
8612 case 0 /* Root */:
8613 if (LVIEW_ROOT === undefined)
8614 LVIEW_ROOT = new LRootView();
8615 return LVIEW_ROOT;
8616 case 1 /* Component */:
8617 if (!ngDevMode || !ngDevMode.namedConstructors) {
8618 if (LVIEW_COMPONENT === undefined)
8619 LVIEW_COMPONENT = new LComponentView();
8620 return LVIEW_COMPONENT;
8621 }
8622 if (LVIEW_COMPONENT_CACHE === undefined)
8623 LVIEW_COMPONENT_CACHE = new Map();
8624 let componentArray = LVIEW_COMPONENT_CACHE.get(name);
8625 if (componentArray === undefined) {
8626 componentArray = new (createNamedArrayType('LComponentView' + nameSuffix(name)))();
8627 LVIEW_COMPONENT_CACHE.set(name, componentArray);
8628 }
8629 return componentArray;
8630 case 2 /* Embedded */:
8631 if (!ngDevMode || !ngDevMode.namedConstructors) {
8632 if (LVIEW_EMBEDDED === undefined)
8633 LVIEW_EMBEDDED = new LEmbeddedView();
8634 return LVIEW_EMBEDDED;
8635 }
8636 if (LVIEW_EMBEDDED_CACHE === undefined)
8637 LVIEW_EMBEDDED_CACHE = new Map();
8638 let embeddedArray = LVIEW_EMBEDDED_CACHE.get(name);
8639 if (embeddedArray === undefined) {
8640 embeddedArray = new (createNamedArrayType('LEmbeddedView' + nameSuffix(name)))();
8641 LVIEW_EMBEDDED_CACHE.set(name, embeddedArray);
8642 }
8643 return embeddedArray;
8644 }
8645}
8646function nameSuffix(text) {
8647 if (text == null)
8648 return '';
8649 const index = text.lastIndexOf('_Template');
8650 return '_' + (index === -1 ? text : text.substr(0, index));
8651}
8652/**
8653 * This class is a debug version of Object literal so that we can have constructor name show up
8654 * in
8655 * debug tools in ngDevMode.
8656 */
8657const TViewConstructor = class TView {
8658 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) {
8659 this.type = type;
8660 this.blueprint = blueprint;
8661 this.template = template;
8662 this.queries = queries;
8663 this.viewQuery = viewQuery;
8664 this.declTNode = declTNode;
8665 this.data = data;
8666 this.bindingStartIndex = bindingStartIndex;
8667 this.expandoStartIndex = expandoStartIndex;
8668 this.hostBindingOpCodes = hostBindingOpCodes;
8669 this.firstCreatePass = firstCreatePass;
8670 this.firstUpdatePass = firstUpdatePass;
8671 this.staticViewQueries = staticViewQueries;
8672 this.staticContentQueries = staticContentQueries;
8673 this.preOrderHooks = preOrderHooks;
8674 this.preOrderCheckHooks = preOrderCheckHooks;
8675 this.contentHooks = contentHooks;
8676 this.contentCheckHooks = contentCheckHooks;
8677 this.viewHooks = viewHooks;
8678 this.viewCheckHooks = viewCheckHooks;
8679 this.destroyHooks = destroyHooks;
8680 this.cleanup = cleanup;
8681 this.contentQueries = contentQueries;
8682 this.components = components;
8683 this.directiveRegistry = directiveRegistry;
8684 this.pipeRegistry = pipeRegistry;
8685 this.firstChild = firstChild;
8686 this.schemas = schemas;
8687 this.consts = consts;
8688 this.incompleteFirstPass = incompleteFirstPass;
8689 this._decls = _decls;
8690 this._vars = _vars;
8691 }
8692 get template_() {
8693 const buf = [];
8694 processTNodeChildren(this.firstChild, buf);
8695 return buf.join('');
8696 }
8697 get type_() {
8698 return TViewTypeAsString[this.type] || `TViewType.?${this.type}?`;
8699 }
8700};
8701class TNode {
8702 constructor(tView_, //
8703 type, //
8704 index, //
8705 insertBeforeIndex, //
8706 injectorIndex, //
8707 directiveStart, //
8708 directiveEnd, //
8709 directiveStylingLast, //
8710 propertyBindings, //
8711 flags, //
8712 providerIndexes, //
8713 value, //
8714 attrs, //
8715 mergedAttrs, //
8716 localNames, //
8717 initialInputs, //
8718 inputs, //
8719 outputs, //
8720 tViews, //
8721 next, //
8722 projectionNext, //
8723 child, //
8724 parent, //
8725 projection, //
8726 styles, //
8727 stylesWithoutHost, //
8728 residualStyles, //
8729 classes, //
8730 classesWithoutHost, //
8731 residualClasses, //
8732 classBindings, //
8733 styleBindings) {
8734 this.tView_ = tView_;
8735 this.type = type;
8736 this.index = index;
8737 this.insertBeforeIndex = insertBeforeIndex;
8738 this.injectorIndex = injectorIndex;
8739 this.directiveStart = directiveStart;
8740 this.directiveEnd = directiveEnd;
8741 this.directiveStylingLast = directiveStylingLast;
8742 this.propertyBindings = propertyBindings;
8743 this.flags = flags;
8744 this.providerIndexes = providerIndexes;
8745 this.value = value;
8746 this.attrs = attrs;
8747 this.mergedAttrs = mergedAttrs;
8748 this.localNames = localNames;
8749 this.initialInputs = initialInputs;
8750 this.inputs = inputs;
8751 this.outputs = outputs;
8752 this.tViews = tViews;
8753 this.next = next;
8754 this.projectionNext = projectionNext;
8755 this.child = child;
8756 this.parent = parent;
8757 this.projection = projection;
8758 this.styles = styles;
8759 this.stylesWithoutHost = stylesWithoutHost;
8760 this.residualStyles = residualStyles;
8761 this.classes = classes;
8762 this.classesWithoutHost = classesWithoutHost;
8763 this.residualClasses = residualClasses;
8764 this.classBindings = classBindings;
8765 this.styleBindings = styleBindings;
8766 }
8767 /**
8768 * Return a human debug version of the set of `NodeInjector`s which will be consulted when
8769 * resolving tokens from this `TNode`.
8770 *
8771 * When debugging applications, it is often difficult to determine which `NodeInjector`s will be
8772 * consulted. This method shows a list of `DebugNode`s representing the `TNode`s which will be
8773 * consulted in order when resolving a token starting at this `TNode`.
8774 *
8775 * The original data is stored in `LView` and `TView` with a lot of offset indexes, and so it is
8776 * difficult to reason about.
8777 *
8778 * @param lView The `LView` instance for this `TNode`.
8779 */
8780 debugNodeInjectorPath(lView) {
8781 const path = [];
8782 let injectorIndex = getInjectorIndex(this, lView);
8783 if (injectorIndex === -1) {
8784 // Looks like the current `TNode` does not have `NodeInjector` associated with it => look for
8785 // parent NodeInjector.
8786 const parentLocation = getParentInjectorLocation(this, lView);
8787 if (parentLocation !== NO_PARENT_INJECTOR) {
8788 // We found a parent, so start searching from the parent location.
8789 injectorIndex = getParentInjectorIndex(parentLocation);
8790 lView = getParentInjectorView(parentLocation, lView);
8791 }
8792 else {
8793 // No parents have been found, so there are no `NodeInjector`s to consult.
8794 }
8795 }
8796 while (injectorIndex !== -1) {
8797 ngDevMode && assertNodeInjector(lView, injectorIndex);
8798 const tNode = lView[TVIEW].data[injectorIndex + 8 /* TNODE */];
8799 path.push(buildDebugNode(tNode, lView));
8800 const parentLocation = lView[injectorIndex + 8 /* PARENT */];
8801 if (parentLocation === NO_PARENT_INJECTOR) {
8802 injectorIndex = -1;
8803 }
8804 else {
8805 injectorIndex = getParentInjectorIndex(parentLocation);
8806 lView = getParentInjectorView(parentLocation, lView);
8807 }
8808 }
8809 return path;
8810 }
8811 get type_() {
8812 return toTNodeTypeAsString(this.type) || `TNodeType.?${this.type}?`;
8813 }
8814 get flags_() {
8815 const flags = [];
8816 if (this.flags & 16 /* hasClassInput */)
8817 flags.push('TNodeFlags.hasClassInput');
8818 if (this.flags & 8 /* hasContentQuery */)
8819 flags.push('TNodeFlags.hasContentQuery');
8820 if (this.flags & 32 /* hasStyleInput */)
8821 flags.push('TNodeFlags.hasStyleInput');
8822 if (this.flags & 128 /* hasHostBindings */)
8823 flags.push('TNodeFlags.hasHostBindings');
8824 if (this.flags & 2 /* isComponentHost */)
8825 flags.push('TNodeFlags.isComponentHost');
8826 if (this.flags & 1 /* isDirectiveHost */)
8827 flags.push('TNodeFlags.isDirectiveHost');
8828 if (this.flags & 64 /* isDetached */)
8829 flags.push('TNodeFlags.isDetached');
8830 if (this.flags & 4 /* isProjected */)
8831 flags.push('TNodeFlags.isProjected');
8832 return flags.join('|');
8833 }
8834 get template_() {
8835 if (this.type & 1 /* Text */)
8836 return this.value;
8837 const buf = [];
8838 const tagName = typeof this.value === 'string' && this.value || this.type_;
8839 buf.push('<', tagName);
8840 if (this.flags) {
8841 buf.push(' ', this.flags_);
8842 }
8843 if (this.attrs) {
8844 for (let i = 0; i < this.attrs.length;) {
8845 const attrName = this.attrs[i++];
8846 if (typeof attrName == 'number') {
8847 break;
8848 }
8849 const attrValue = this.attrs[i++];
8850 buf.push(' ', attrName, '="', attrValue, '"');
8851 }
8852 }
8853 buf.push('>');
8854 processTNodeChildren(this.child, buf);
8855 buf.push('</', tagName, '>');
8856 return buf.join('');
8857 }
8858 get styleBindings_() {
8859 return toDebugStyleBinding(this, false);
8860 }
8861 get classBindings_() {
8862 return toDebugStyleBinding(this, true);
8863 }
8864 get providerIndexStart_() {
8865 return this.providerIndexes & 1048575 /* ProvidersStartIndexMask */;
8866 }
8867 get providerIndexEnd_() {
8868 return this.providerIndexStart_ +
8869 (this.providerIndexes >>> 20 /* CptViewProvidersCountShift */);
8870 }
8871}
8872const TNodeDebug = TNode;
8873function toDebugStyleBinding(tNode, isClassBased) {
8874 const tData = tNode.tView_.data;
8875 const bindings = [];
8876 const range = isClassBased ? tNode.classBindings : tNode.styleBindings;
8877 const prev = getTStylingRangePrev(range);
8878 const next = getTStylingRangeNext(range);
8879 let isTemplate = next !== 0;
8880 let cursor = isTemplate ? next : prev;
8881 while (cursor !== 0) {
8882 const itemKey = tData[cursor];
8883 const itemRange = tData[cursor + 1];
8884 bindings.unshift({
8885 key: itemKey,
8886 index: cursor,
8887 isTemplate: isTemplate,
8888 prevDuplicate: getTStylingRangePrevDuplicate(itemRange),
8889 nextDuplicate: getTStylingRangeNextDuplicate(itemRange),
8890 nextIndex: getTStylingRangeNext(itemRange),
8891 prevIndex: getTStylingRangePrev(itemRange),
8892 });
8893 if (cursor === prev)
8894 isTemplate = false;
8895 cursor = getTStylingRangePrev(itemRange);
8896 }
8897 bindings.push((isClassBased ? tNode.residualClasses : tNode.residualStyles) || null);
8898 return bindings;
8899}
8900function processTNodeChildren(tNode, buf) {
8901 while (tNode) {
8902 buf.push(tNode.template_);
8903 tNode = tNode.next;
8904 }
8905}
8906class TViewData extends Array {
8907}
8908let TVIEWDATA_EMPTY; // can't initialize here or it will not be tree shaken, because
8909// `LView` constructor could have side-effects.
8910/**
8911 * This function clones a blueprint and creates TData.
8912 *
8913 * Simple slice will keep the same type, and we need it to be TData
8914 */
8915function cloneToTViewData(list) {
8916 if (TVIEWDATA_EMPTY === undefined)
8917 TVIEWDATA_EMPTY = new TViewData();
8918 return TVIEWDATA_EMPTY.concat(list);
8919}
8920class LViewBlueprint extends Array {
8921}
8922class MatchesArray extends Array {
8923}
8924class TViewComponents extends Array {
8925}
8926class TNodeLocalNames extends Array {
8927}
8928class TNodeInitialInputs extends Array {
8929}
8930class LCleanup extends Array {
8931}
8932class TCleanup extends Array {
8933}
8934function attachLViewDebug(lView) {
8935 attachDebugObject(lView, new LViewDebug(lView));
8936}
8937function attachLContainerDebug(lContainer) {
8938 attachDebugObject(lContainer, new LContainerDebug(lContainer));
8939}
8940function toDebug(obj) {
8941 if (obj) {
8942 const debug = obj.debug;
8943 assertDefined(debug, 'Object does not have a debug representation.');
8944 return debug;
8945 }
8946 else {
8947 return obj;
8948 }
8949}
8950/**
8951 * Use this method to unwrap a native element in `LView` and convert it into HTML for easier
8952 * reading.
8953 *
8954 * @param value possibly wrapped native DOM node.
8955 * @param includeChildren If `true` then the serialized HTML form will include child elements
8956 * (same
8957 * as `outerHTML`). If `false` then the serialized HTML form will only contain the element
8958 * itself
8959 * (will not serialize child elements).
8960 */
8961function toHtml(value, includeChildren = false) {
8962 const node = unwrapRNode(value);
8963 if (node) {
8964 switch (node.nodeType) {
8965 case Node.TEXT_NODE:
8966 return node.textContent;
8967 case Node.COMMENT_NODE:
8968 return `<!--${node.textContent}-->`;
8969 case Node.ELEMENT_NODE:
8970 const outerHTML = node.outerHTML;
8971 if (includeChildren) {
8972 return outerHTML;
8973 }
8974 else {
8975 const innerHTML = '>' + node.innerHTML + '<';
8976 return (outerHTML.split(innerHTML)[0]) + '>';
8977 }
8978 }
8979 }
8980 return null;
8981}
8982class LViewDebug {
8983 constructor(_raw_lView) {
8984 this._raw_lView = _raw_lView;
8985 }
8986 /**
8987 * Flags associated with the `LView` unpacked into a more readable state.
8988 */
8989 get flags() {
8990 const flags = this._raw_lView[FLAGS];
8991 return {
8992 __raw__flags__: flags,
8993 initPhaseState: flags & 3 /* InitPhaseStateMask */,
8994 creationMode: !!(flags & 4 /* CreationMode */),
8995 firstViewPass: !!(flags & 8 /* FirstLViewPass */),
8996 checkAlways: !!(flags & 16 /* CheckAlways */),
8997 dirty: !!(flags & 64 /* Dirty */),
8998 attached: !!(flags & 128 /* Attached */),
8999 destroyed: !!(flags & 256 /* Destroyed */),
9000 isRoot: !!(flags & 512 /* IsRoot */),
9001 indexWithinInitPhase: flags >> 11 /* IndexWithinInitPhaseShift */,
9002 };
9003 }
9004 get parent() {
9005 return toDebug(this._raw_lView[PARENT]);
9006 }
9007 get hostHTML() {
9008 return toHtml(this._raw_lView[HOST], true);
9009 }
9010 get html() {
9011 return (this.nodes || []).map(mapToHTML).join('');
9012 }
9013 get context() {
9014 return this._raw_lView[CONTEXT];
9015 }
9016 /**
9017 * The tree of nodes associated with the current `LView`. The nodes have been normalized into
9018 * a tree structure with relevant details pulled out for readability.
9019 */
9020 get nodes() {
9021 const lView = this._raw_lView;
9022 const tNode = lView[TVIEW].firstChild;
9023 return toDebugNodes(tNode, lView);
9024 }
9025 get template() {
9026 return this.tView.template_;
9027 }
9028 get tView() {
9029 return this._raw_lView[TVIEW];
9030 }
9031 get cleanup() {
9032 return this._raw_lView[CLEANUP];
9033 }
9034 get injector() {
9035 return this._raw_lView[INJECTOR$1];
9036 }
9037 get rendererFactory() {
9038 return this._raw_lView[RENDERER_FACTORY];
9039 }
9040 get renderer() {
9041 return this._raw_lView[RENDERER];
9042 }
9043 get sanitizer() {
9044 return this._raw_lView[SANITIZER];
9045 }
9046 get childHead() {
9047 return toDebug(this._raw_lView[CHILD_HEAD]);
9048 }
9049 get next() {
9050 return toDebug(this._raw_lView[NEXT]);
9051 }
9052 get childTail() {
9053 return toDebug(this._raw_lView[CHILD_TAIL]);
9054 }
9055 get declarationView() {
9056 return toDebug(this._raw_lView[DECLARATION_VIEW]);
9057 }
9058 get queries() {
9059 return this._raw_lView[QUERIES];
9060 }
9061 get tHost() {
9062 return this._raw_lView[T_HOST];
9063 }
9064 get decls() {
9065 return toLViewRange(this.tView, this._raw_lView, HEADER_OFFSET, this.tView.bindingStartIndex);
9066 }
9067 get vars() {
9068 return toLViewRange(this.tView, this._raw_lView, this.tView.bindingStartIndex, this.tView.expandoStartIndex);
9069 }
9070 get expando() {
9071 return toLViewRange(this.tView, this._raw_lView, this.tView.expandoStartIndex, this._raw_lView.length);
9072 }
9073 /**
9074 * Normalized view of child views (and containers) attached at this location.
9075 */
9076 get childViews() {
9077 const childViews = [];
9078 let child = this.childHead;
9079 while (child) {
9080 childViews.push(child);
9081 child = child.next;
9082 }
9083 return childViews;
9084 }
9085}
9086function mapToHTML(node) {
9087 if (node.type === 'ElementContainer') {
9088 return (node.children || []).map(mapToHTML).join('');
9089 }
9090 else if (node.type === 'IcuContainer') {
9091 throw new Error('Not implemented');
9092 }
9093 else {
9094 return toHtml(node.native, true) || '';
9095 }
9096}
9097function toLViewRange(tView, lView, start, end) {
9098 let content = [];
9099 for (let index = start; index < end; index++) {
9100 content.push({ index: index, t: tView.data[index], l: lView[index] });
9101 }
9102 return { start: start, end: end, length: end - start, content: content };
9103}
9104/**
9105 * Turns a flat list of nodes into a tree by walking the associated `TNode` tree.
9106 *
9107 * @param tNode
9108 * @param lView
9109 */
9110function toDebugNodes(tNode, lView) {
9111 if (tNode) {
9112 const debugNodes = [];
9113 let tNodeCursor = tNode;
9114 while (tNodeCursor) {
9115 debugNodes.push(buildDebugNode(tNodeCursor, lView));
9116 tNodeCursor = tNodeCursor.next;
9117 }
9118 return debugNodes;
9119 }
9120 else {
9121 return [];
9122 }
9123}
9124function buildDebugNode(tNode, lView) {
9125 const rawValue = lView[tNode.index];
9126 const native = unwrapRNode(rawValue);
9127 const factories = [];
9128 const instances = [];
9129 const tView = lView[TVIEW];
9130 for (let i = tNode.directiveStart; i < tNode.directiveEnd; i++) {
9131 const def = tView.data[i];
9132 factories.push(def.type);
9133 instances.push(lView[i]);
9134 }
9135 return {
9136 html: toHtml(native),
9137 type: toTNodeTypeAsString(tNode.type),
9138 tNode,
9139 native: native,
9140 children: toDebugNodes(tNode.child, lView),
9141 factories,
9142 instances,
9143 injector: buildNodeInjectorDebug(tNode, tView, lView),
9144 get injectorResolutionPath() {
9145 return tNode.debugNodeInjectorPath(lView);
9146 },
9147 };
9148}
9149function buildNodeInjectorDebug(tNode, tView, lView) {
9150 const viewProviders = [];
9151 for (let i = tNode.providerIndexStart_; i < tNode.providerIndexEnd_; i++) {
9152 viewProviders.push(tView.data[i]);
9153 }
9154 const providers = [];
9155 for (let i = tNode.providerIndexEnd_; i < tNode.directiveEnd; i++) {
9156 providers.push(tView.data[i]);
9157 }
9158 const nodeInjectorDebug = {
9159 bloom: toBloom(lView, tNode.injectorIndex),
9160 cumulativeBloom: toBloom(tView.data, tNode.injectorIndex),
9161 providers,
9162 viewProviders,
9163 parentInjectorIndex: lView[tNode.providerIndexStart_ - 1],
9164 };
9165 return nodeInjectorDebug;
9166}
9167/**
9168 * Convert a number at `idx` location in `array` into binary representation.
9169 *
9170 * @param array
9171 * @param idx
9172 */
9173function binary(array, idx) {
9174 const value = array[idx];
9175 // If not a number we print 8 `?` to retain alignment but let user know that it was called on
9176 // wrong type.
9177 if (typeof value !== 'number')
9178 return '????????';
9179 // We prefix 0s so that we have constant length number
9180 const text = '00000000' + value.toString(2);
9181 return text.substring(text.length - 8);
9182}
9183/**
9184 * Convert a bloom filter at location `idx` in `array` into binary representation.
9185 *
9186 * @param array
9187 * @param idx
9188 */
9189function toBloom(array, idx) {
9190 if (idx < 0) {
9191 return 'NO_NODE_INJECTOR';
9192 }
9193 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)}`;
9194}
9195class LContainerDebug {
9196 constructor(_raw_lContainer) {
9197 this._raw_lContainer = _raw_lContainer;
9198 }
9199 get hasTransplantedViews() {
9200 return this._raw_lContainer[HAS_TRANSPLANTED_VIEWS];
9201 }
9202 get views() {
9203 return this._raw_lContainer.slice(CONTAINER_HEADER_OFFSET)
9204 .map(toDebug);
9205 }
9206 get parent() {
9207 return toDebug(this._raw_lContainer[PARENT]);
9208 }
9209 get movedViews() {
9210 return this._raw_lContainer[MOVED_VIEWS];
9211 }
9212 get host() {
9213 return this._raw_lContainer[HOST];
9214 }
9215 get native() {
9216 return this._raw_lContainer[NATIVE];
9217 }
9218 get next() {
9219 return toDebug(this._raw_lContainer[NEXT]);
9220 }
9221}
9222
9223/**
9224 * A permanent marker promise which signifies that the current CD tree is
9225 * clean.
9226 */
9227const _CLEAN_PROMISE = (() => Promise.resolve(null))();
9228/**
9229 * Invoke `HostBindingsFunction`s for view.
9230 *
9231 * This methods executes `TView.hostBindingOpCodes`. It is used to execute the
9232 * `HostBindingsFunction`s associated with the current `LView`.
9233 *
9234 * @param tView Current `TView`.
9235 * @param lView Current `LView`.
9236 */
9237function processHostBindingOpCodes(tView, lView) {
9238 const hostBindingOpCodes = tView.hostBindingOpCodes;
9239 if (hostBindingOpCodes === null)
9240 return;
9241 try {
9242 for (let i = 0; i < hostBindingOpCodes.length; i++) {
9243 const opCode = hostBindingOpCodes[i];
9244 if (opCode < 0) {
9245 // Negative numbers are element indexes.
9246 setSelectedIndex(~opCode);
9247 }
9248 else {
9249 // Positive numbers are NumberTuple which store bindingRootIndex and directiveIndex.
9250 const directiveIdx = opCode;
9251 const bindingRootIndx = hostBindingOpCodes[++i];
9252 const hostBindingFn = hostBindingOpCodes[++i];
9253 setBindingRootForHostBindings(bindingRootIndx, directiveIdx);
9254 const context = lView[directiveIdx];
9255 hostBindingFn(2 /* Update */, context);
9256 }
9257 }
9258 }
9259 finally {
9260 setSelectedIndex(-1);
9261 }
9262}
9263/** Refreshes all content queries declared by directives in a given view */
9264function refreshContentQueries(tView, lView) {
9265 const contentQueries = tView.contentQueries;
9266 if (contentQueries !== null) {
9267 for (let i = 0; i < contentQueries.length; i += 2) {
9268 const queryStartIdx = contentQueries[i];
9269 const directiveDefIdx = contentQueries[i + 1];
9270 if (directiveDefIdx !== -1) {
9271 const directiveDef = tView.data[directiveDefIdx];
9272 ngDevMode && assertDefined(directiveDef, 'DirectiveDef not found.');
9273 ngDevMode &&
9274 assertDefined(directiveDef.contentQueries, 'contentQueries function should be defined');
9275 setCurrentQueryIndex(queryStartIdx);
9276 directiveDef.contentQueries(2 /* Update */, lView[directiveDefIdx], directiveDefIdx);
9277 }
9278 }
9279 }
9280}
9281/** Refreshes child components in the current view (update mode). */
9282function refreshChildComponents(hostLView, components) {
9283 for (let i = 0; i < components.length; i++) {
9284 refreshComponent(hostLView, components[i]);
9285 }
9286}
9287/** Renders child components in the current view (creation mode). */
9288function renderChildComponents(hostLView, components) {
9289 for (let i = 0; i < components.length; i++) {
9290 renderComponent$1(hostLView, components[i]);
9291 }
9292}
9293function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector) {
9294 const lView = ngDevMode ? cloneToLViewFromTViewBlueprint(tView) : tView.blueprint.slice();
9295 lView[HOST] = host;
9296 lView[FLAGS] = flags | 4 /* CreationMode */ | 128 /* Attached */ | 8 /* FirstLViewPass */;
9297 resetPreOrderHookFlags(lView);
9298 ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView);
9299 lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;
9300 lView[CONTEXT] = context;
9301 lView[RENDERER_FACTORY] = (rendererFactory || parentLView && parentLView[RENDERER_FACTORY]);
9302 ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required');
9303 lView[RENDERER] = (renderer || parentLView && parentLView[RENDERER]);
9304 ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
9305 lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null;
9306 lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
9307 lView[T_HOST] = tHostNode;
9308 ngDevMode &&
9309 assertEqual(tView.type == 2 /* Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
9310 lView[DECLARATION_COMPONENT_VIEW] =
9311 tView.type == 2 /* Embedded */ ? parentLView[DECLARATION_COMPONENT_VIEW] : lView;
9312 ngDevMode && attachLViewDebug(lView);
9313 return lView;
9314}
9315function getOrCreateTNode(tView, index, type, name, attrs) {
9316 ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in
9317 // `view_engine_compatibility` for additional context.
9318 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.');
9319 // Keep this function short, so that the VM will inline it.
9320 ngDevMode && assertPureTNodeType(type);
9321 let tNode = tView.data[index];
9322 if (tNode === null) {
9323 tNode = createTNodeAtIndex(tView, index, type, name, attrs);
9324 if (isInI18nBlock()) {
9325 // If we are in i18n block then all elements should be pre declared through `Placeholder`
9326 // See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
9327 // If the `TNode` was not pre-declared than it means it was not mentioned which means it was
9328 // removed, so we mark it as detached.
9329 tNode.flags |= 64 /* isDetached */;
9330 }
9331 }
9332 else if (tNode.type & 64 /* Placeholder */) {
9333 tNode.type = type;
9334 tNode.value = name;
9335 tNode.attrs = attrs;
9336 const parent = getCurrentParentTNode();
9337 tNode.injectorIndex = parent === null ? -1 : parent.injectorIndex;
9338 ngDevMode && assertTNodeForTView(tNode, tView);
9339 ngDevMode && assertEqual(index, tNode.index, 'Expecting same index');
9340 }
9341 setCurrentTNode(tNode, true);
9342 return tNode;
9343}
9344function createTNodeAtIndex(tView, index, type, name, attrs) {
9345 const currentTNode = getCurrentTNodePlaceholderOk();
9346 const isParent = isCurrentTNodeParent();
9347 const parent = isParent ? currentTNode : currentTNode && currentTNode.parent;
9348 // Parents cannot cross component boundaries because components will be used in multiple places.
9349 const tNode = tView.data[index] =
9350 createTNode(tView, parent, type, index, name, attrs);
9351 // Assign a pointer to the first child node of a given view. The first node is not always the one
9352 // at index 0, in case of i18n, index 0 can be the instruction `i18nStart` and the first node has
9353 // the index 1 or more, so we can't just check node index.
9354 if (tView.firstChild === null) {
9355 tView.firstChild = tNode;
9356 }
9357 if (currentTNode !== null) {
9358 if (isParent) {
9359 // FIXME(misko): This logic looks unnecessarily complicated. Could we simplify?
9360 if (currentTNode.child == null && tNode.parent !== null) {
9361 // We are in the same view, which means we are adding content node to the parent view.
9362 currentTNode.child = tNode;
9363 }
9364 }
9365 else {
9366 if (currentTNode.next === null) {
9367 // In the case of i18n the `currentTNode` may already be linked, in which case we don't want
9368 // to break the links which i18n created.
9369 currentTNode.next = tNode;
9370 }
9371 }
9372 }
9373 return tNode;
9374}
9375/**
9376 * When elements are created dynamically after a view blueprint is created (e.g. through
9377 * i18nApply()), we need to adjust the blueprint for future
9378 * template passes.
9379 *
9380 * @param tView `TView` associated with `LView`
9381 * @param lView The `LView` containing the blueprint to adjust
9382 * @param numSlotsToAlloc The number of slots to alloc in the LView, should be >0
9383 * @param initialValue Initial value to store in blueprint
9384 */
9385function allocExpando(tView, lView, numSlotsToAlloc, initialValue) {
9386 if (numSlotsToAlloc === 0)
9387 return -1;
9388 if (ngDevMode) {
9389 assertFirstCreatePass(tView);
9390 assertSame(tView, lView[TVIEW], '`LView` must be associated with `TView`!');
9391 assertEqual(tView.data.length, lView.length, 'Expecting LView to be same size as TView');
9392 assertEqual(tView.data.length, tView.blueprint.length, 'Expecting Blueprint to be same size as TView');
9393 assertFirstUpdatePass(tView);
9394 }
9395 const allocIdx = lView.length;
9396 for (let i = 0; i < numSlotsToAlloc; i++) {
9397 lView.push(initialValue);
9398 tView.blueprint.push(initialValue);
9399 tView.data.push(null);
9400 }
9401 return allocIdx;
9402}
9403//////////////////////////
9404//// Render
9405//////////////////////////
9406/**
9407 * Processes a view in the creation mode. This includes a number of steps in a specific order:
9408 * - creating view query functions (if any);
9409 * - executing a template function in the creation mode;
9410 * - updating static queries (if any);
9411 * - creating child components defined in a given view.
9412 */
9413function renderView(tView, lView, context) {
9414 ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
9415 enterView(lView);
9416 try {
9417 const viewQuery = tView.viewQuery;
9418 if (viewQuery !== null) {
9419 executeViewQueryFn(1 /* Create */, viewQuery, context);
9420 }
9421 // Execute a template associated with this view, if it exists. A template function might not be
9422 // defined for the root component views.
9423 const templateFn = tView.template;
9424 if (templateFn !== null) {
9425 executeTemplate(tView, lView, templateFn, 1 /* Create */, context);
9426 }
9427 // This needs to be set before children are processed to support recursive components.
9428 // This must be set to false immediately after the first creation run because in an
9429 // ngFor loop, all the views will be created together before update mode runs and turns
9430 // off firstCreatePass. If we don't set it here, instances will perform directive
9431 // matching, etc again and again.
9432 if (tView.firstCreatePass) {
9433 tView.firstCreatePass = false;
9434 }
9435 // We resolve content queries specifically marked as `static` in creation mode. Dynamic
9436 // content queries are resolved during change detection (i.e. update mode), after embedded
9437 // views are refreshed (see block above).
9438 if (tView.staticContentQueries) {
9439 refreshContentQueries(tView, lView);
9440 }
9441 // We must materialize query results before child components are processed
9442 // in case a child component has projected a container. The LContainer needs
9443 // to exist so the embedded views are properly attached by the container.
9444 if (tView.staticViewQueries) {
9445 executeViewQueryFn(2 /* Update */, tView.viewQuery, context);
9446 }
9447 // Render child component views.
9448 const components = tView.components;
9449 if (components !== null) {
9450 renderChildComponents(lView, components);
9451 }
9452 }
9453 catch (error) {
9454 // If we didn't manage to get past the first template pass due to
9455 // an error, mark the view as corrupted so we can try to recover.
9456 if (tView.firstCreatePass) {
9457 tView.incompleteFirstPass = true;
9458 tView.firstCreatePass = false;
9459 }
9460 throw error;
9461 }
9462 finally {
9463 lView[FLAGS] &= ~4 /* CreationMode */;
9464 leaveView();
9465 }
9466}
9467/**
9468 * Processes a view in update mode. This includes a number of steps in a specific order:
9469 * - executing a template function in update mode;
9470 * - executing hooks;
9471 * - refreshing queries;
9472 * - setting host bindings;
9473 * - refreshing child (embedded and component) views.
9474 */
9475function refreshView(tView, lView, templateFn, context) {
9476 ngDevMode && assertEqual(isCreationMode(lView), false, 'Should be run in update mode');
9477 const flags = lView[FLAGS];
9478 if ((flags & 256 /* Destroyed */) === 256 /* Destroyed */)
9479 return;
9480 enterView(lView);
9481 // Check no changes mode is a dev only mode used to verify that bindings have not changed
9482 // since they were assigned. We do not want to execute lifecycle hooks in that mode.
9483 const isInCheckNoChangesPass = isInCheckNoChangesMode();
9484 try {
9485 resetPreOrderHookFlags(lView);
9486 setBindingIndex(tView.bindingStartIndex);
9487 if (templateFn !== null) {
9488 executeTemplate(tView, lView, templateFn, 2 /* Update */, context);
9489 }
9490 const hooksInitPhaseCompleted = (flags & 3 /* InitPhaseStateMask */) === 3 /* InitPhaseCompleted */;
9491 // execute pre-order hooks (OnInit, OnChanges, DoCheck)
9492 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
9493 if (!isInCheckNoChangesPass) {
9494 if (hooksInitPhaseCompleted) {
9495 const preOrderCheckHooks = tView.preOrderCheckHooks;
9496 if (preOrderCheckHooks !== null) {
9497 executeCheckHooks(lView, preOrderCheckHooks, null);
9498 }
9499 }
9500 else {
9501 const preOrderHooks = tView.preOrderHooks;
9502 if (preOrderHooks !== null) {
9503 executeInitAndCheckHooks(lView, preOrderHooks, 0 /* OnInitHooksToBeRun */, null);
9504 }
9505 incrementInitPhaseFlags(lView, 0 /* OnInitHooksToBeRun */);
9506 }
9507 }
9508 // First mark transplanted views that are declared in this lView as needing a refresh at their
9509 // insertion points. This is needed to avoid the situation where the template is defined in this
9510 // `LView` but its declaration appears after the insertion component.
9511 markTransplantedViewsForRefresh(lView);
9512 refreshEmbeddedViews(lView);
9513 // Content query results must be refreshed before content hooks are called.
9514 if (tView.contentQueries !== null) {
9515 refreshContentQueries(tView, lView);
9516 }
9517 // execute content hooks (AfterContentInit, AfterContentChecked)
9518 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
9519 if (!isInCheckNoChangesPass) {
9520 if (hooksInitPhaseCompleted) {
9521 const contentCheckHooks = tView.contentCheckHooks;
9522 if (contentCheckHooks !== null) {
9523 executeCheckHooks(lView, contentCheckHooks);
9524 }
9525 }
9526 else {
9527 const contentHooks = tView.contentHooks;
9528 if (contentHooks !== null) {
9529 executeInitAndCheckHooks(lView, contentHooks, 1 /* AfterContentInitHooksToBeRun */);
9530 }
9531 incrementInitPhaseFlags(lView, 1 /* AfterContentInitHooksToBeRun */);
9532 }
9533 }
9534 processHostBindingOpCodes(tView, lView);
9535 // Refresh child component views.
9536 const components = tView.components;
9537 if (components !== null) {
9538 refreshChildComponents(lView, components);
9539 }
9540 // View queries must execute after refreshing child components because a template in this view
9541 // could be inserted in a child component. If the view query executes before child component
9542 // refresh, the template might not yet be inserted.
9543 const viewQuery = tView.viewQuery;
9544 if (viewQuery !== null) {
9545 executeViewQueryFn(2 /* Update */, viewQuery, context);
9546 }
9547 // execute view hooks (AfterViewInit, AfterViewChecked)
9548 // PERF WARNING: do NOT extract this to a separate function without running benchmarks
9549 if (!isInCheckNoChangesPass) {
9550 if (hooksInitPhaseCompleted) {
9551 const viewCheckHooks = tView.viewCheckHooks;
9552 if (viewCheckHooks !== null) {
9553 executeCheckHooks(lView, viewCheckHooks);
9554 }
9555 }
9556 else {
9557 const viewHooks = tView.viewHooks;
9558 if (viewHooks !== null) {
9559 executeInitAndCheckHooks(lView, viewHooks, 2 /* AfterViewInitHooksToBeRun */);
9560 }
9561 incrementInitPhaseFlags(lView, 2 /* AfterViewInitHooksToBeRun */);
9562 }
9563 }
9564 if (tView.firstUpdatePass === true) {
9565 // We need to make sure that we only flip the flag on successful `refreshView` only
9566 // Don't do this in `finally` block.
9567 // If we did this in `finally` block then an exception could block the execution of styling
9568 // instructions which in turn would be unable to insert themselves into the styling linked
9569 // list. The result of this would be that if the exception would not be throw on subsequent CD
9570 // the styling would be unable to process it data and reflect to the DOM.
9571 tView.firstUpdatePass = false;
9572 }
9573 // Do not reset the dirty state when running in check no changes mode. We don't want components
9574 // to behave differently depending on whether check no changes is enabled or not. For example:
9575 // Marking an OnPush component as dirty from within the `ngAfterViewInit` hook in order to
9576 // refresh a `NgClass` binding should work. If we would reset the dirty state in the check
9577 // no changes cycle, the component would be not be dirty for the next update pass. This would
9578 // be different in production mode where the component dirty state is not reset.
9579 if (!isInCheckNoChangesPass) {
9580 lView[FLAGS] &= ~(64 /* Dirty */ | 8 /* FirstLViewPass */);
9581 }
9582 if (lView[FLAGS] & 1024 /* RefreshTransplantedView */) {
9583 lView[FLAGS] &= ~1024 /* RefreshTransplantedView */;
9584 updateTransplantedViewCount(lView[PARENT], -1);
9585 }
9586 }
9587 finally {
9588 leaveView();
9589 }
9590}
9591function renderComponentOrTemplate(tView, lView, templateFn, context) {
9592 const rendererFactory = lView[RENDERER_FACTORY];
9593 const normalExecutionPath = !isInCheckNoChangesMode();
9594 const creationModeIsActive = isCreationMode(lView);
9595 try {
9596 if (normalExecutionPath && !creationModeIsActive && rendererFactory.begin) {
9597 rendererFactory.begin();
9598 }
9599 if (creationModeIsActive) {
9600 renderView(tView, lView, context);
9601 }
9602 refreshView(tView, lView, templateFn, context);
9603 }
9604 finally {
9605 if (normalExecutionPath && !creationModeIsActive && rendererFactory.end) {
9606 rendererFactory.end();
9607 }
9608 }
9609}
9610function executeTemplate(tView, lView, templateFn, rf, context) {
9611 const prevSelectedIndex = getSelectedIndex();
9612 const isUpdatePhase = rf & 2 /* Update */;
9613 try {
9614 setSelectedIndex(-1);
9615 if (isUpdatePhase && lView.length > HEADER_OFFSET) {
9616 // When we're updating, inherently select 0 so we don't
9617 // have to generate that instruction for most update blocks.
9618 selectIndexInternal(tView, lView, HEADER_OFFSET, isInCheckNoChangesMode());
9619 }
9620 const preHookType = isUpdatePhase ? 2 /* TemplateUpdateStart */ : 0 /* TemplateCreateStart */;
9621 profiler(preHookType, context);
9622 templateFn(rf, context);
9623 }
9624 finally {
9625 setSelectedIndex(prevSelectedIndex);
9626 const postHookType = isUpdatePhase ? 3 /* TemplateUpdateEnd */ : 1 /* TemplateCreateEnd */;
9627 profiler(postHookType, context);
9628 }
9629}
9630//////////////////////////
9631//// Element
9632//////////////////////////
9633function executeContentQueries(tView, tNode, lView) {
9634 if (isContentQueryHost(tNode)) {
9635 const start = tNode.directiveStart;
9636 const end = tNode.directiveEnd;
9637 for (let directiveIndex = start; directiveIndex < end; directiveIndex++) {
9638 const def = tView.data[directiveIndex];
9639 if (def.contentQueries) {
9640 def.contentQueries(1 /* Create */, lView[directiveIndex], directiveIndex);
9641 }
9642 }
9643 }
9644}
9645/**
9646 * Creates directive instances.
9647 */
9648function createDirectivesInstances(tView, lView, tNode) {
9649 if (!getBindingsEnabled())
9650 return;
9651 instantiateAllDirectives(tView, lView, tNode, getNativeByTNode(tNode, lView));
9652 if ((tNode.flags & 128 /* hasHostBindings */) === 128 /* hasHostBindings */) {
9653 invokeDirectivesHostBindings(tView, lView, tNode);
9654 }
9655}
9656/**
9657 * Takes a list of local names and indices and pushes the resolved local variable values
9658 * to LView in the same order as they are loaded in the template with load().
9659 */
9660function saveResolvedLocalsInData(viewData, tNode, localRefExtractor = getNativeByTNode) {
9661 const localNames = tNode.localNames;
9662 if (localNames !== null) {
9663 let localIndex = tNode.index + 1;
9664 for (let i = 0; i < localNames.length; i += 2) {
9665 const index = localNames[i + 1];
9666 const value = index === -1 ?
9667 localRefExtractor(tNode, viewData) :
9668 viewData[index];
9669 viewData[localIndex++] = value;
9670 }
9671 }
9672}
9673/**
9674 * Gets TView from a template function or creates a new TView
9675 * if it doesn't already exist.
9676 *
9677 * @param def ComponentDef
9678 * @returns TView
9679 */
9680function getOrCreateTComponentView(def) {
9681 const tView = def.tView;
9682 // Create a TView if there isn't one, or recreate it if the first create pass didn't
9683 // complete successfully since we can't know for sure whether it's in a usable shape.
9684 if (tView === null || tView.incompleteFirstPass) {
9685 // Declaration node here is null since this function is called when we dynamically create a
9686 // component and hence there is no declaration.
9687 const declTNode = null;
9688 return def.tView = createTView(1 /* Component */, declTNode, def.template, def.decls, def.vars, def.directiveDefs, def.pipeDefs, def.viewQuery, def.schemas, def.consts);
9689 }
9690 return tView;
9691}
9692/**
9693 * Creates a TView instance
9694 *
9695 * @param type Type of `TView`.
9696 * @param declTNode Declaration location of this `TView`.
9697 * @param templateFn Template function
9698 * @param decls The number of nodes, local refs, and pipes in this template
9699 * @param directives Registry of directives for this view
9700 * @param pipes Registry of pipes for this view
9701 * @param viewQuery View queries for this view
9702 * @param schemas Schemas for this view
9703 * @param consts Constants for this view
9704 */
9705function createTView(type, declTNode, templateFn, decls, vars, directives, pipes, viewQuery, schemas, constsOrFactory) {
9706 ngDevMode && ngDevMode.tView++;
9707 const bindingStartIndex = HEADER_OFFSET + decls;
9708 // This length does not yet contain host bindings from child directives because at this point,
9709 // we don't know which directives are active on this template. As soon as a directive is matched
9710 // that has a host binding, we will update the blueprint with that def's hostVars count.
9711 const initialViewLength = bindingStartIndex + vars;
9712 const blueprint = createViewBlueprint(bindingStartIndex, initialViewLength);
9713 const consts = typeof constsOrFactory === 'function' ? constsOrFactory() : constsOrFactory;
9714 const tView = blueprint[TVIEW] = ngDevMode ?
9715 new TViewConstructor(type, // type: TViewType,
9716 blueprint, // blueprint: LView,
9717 templateFn, // template: ComponentTemplate<{}>|null,
9718 null, // queries: TQueries|null
9719 viewQuery, // viewQuery: ViewQueriesFunction<{}>|null,
9720 declTNode, // declTNode: TNode|null,
9721 cloneToTViewData(blueprint).fill(null, bindingStartIndex), // data: TData,
9722 bindingStartIndex, // bindingStartIndex: number,
9723 initialViewLength, // expandoStartIndex: number,
9724 null, // hostBindingOpCodes: HostBindingOpCodes,
9725 true, // firstCreatePass: boolean,
9726 true, // firstUpdatePass: boolean,
9727 false, // staticViewQueries: boolean,
9728 false, // staticContentQueries: boolean,
9729 null, // preOrderHooks: HookData|null,
9730 null, // preOrderCheckHooks: HookData|null,
9731 null, // contentHooks: HookData|null,
9732 null, // contentCheckHooks: HookData|null,
9733 null, // viewHooks: HookData|null,
9734 null, // viewCheckHooks: HookData|null,
9735 null, // destroyHooks: DestroyHookData|null,
9736 null, // cleanup: any[]|null,
9737 null, // contentQueries: number[]|null,
9738 null, // components: number[]|null,
9739 typeof directives === 'function' ? //
9740 directives() : //
9741 directives, // directiveRegistry: DirectiveDefList|null,
9742 typeof pipes === 'function' ? pipes() : pipes, // pipeRegistry: PipeDefList|null,
9743 null, // firstChild: TNode|null,
9744 schemas, // schemas: SchemaMetadata[]|null,
9745 consts, // consts: TConstants|null
9746 false, // incompleteFirstPass: boolean
9747 decls, // ngDevMode only: decls
9748 vars) :
9749 {
9750 type: type,
9751 blueprint: blueprint,
9752 template: templateFn,
9753 queries: null,
9754 viewQuery: viewQuery,
9755 declTNode: declTNode,
9756 data: blueprint.slice().fill(null, bindingStartIndex),
9757 bindingStartIndex: bindingStartIndex,
9758 expandoStartIndex: initialViewLength,
9759 hostBindingOpCodes: null,
9760 firstCreatePass: true,
9761 firstUpdatePass: true,
9762 staticViewQueries: false,
9763 staticContentQueries: false,
9764 preOrderHooks: null,
9765 preOrderCheckHooks: null,
9766 contentHooks: null,
9767 contentCheckHooks: null,
9768 viewHooks: null,
9769 viewCheckHooks: null,
9770 destroyHooks: null,
9771 cleanup: null,
9772 contentQueries: null,
9773 components: null,
9774 directiveRegistry: typeof directives === 'function' ? directives() : directives,
9775 pipeRegistry: typeof pipes === 'function' ? pipes() : pipes,
9776 firstChild: null,
9777 schemas: schemas,
9778 consts: consts,
9779 incompleteFirstPass: false
9780 };
9781 if (ngDevMode) {
9782 // For performance reasons it is important that the tView retains the same shape during runtime.
9783 // (To make sure that all of the code is monomorphic.) For this reason we seal the object to
9784 // prevent class transitions.
9785 Object.seal(tView);
9786 }
9787 return tView;
9788}
9789function createViewBlueprint(bindingStartIndex, initialViewLength) {
9790 const blueprint = ngDevMode ? new LViewBlueprint() : [];
9791 for (let i = 0; i < initialViewLength; i++) {
9792 blueprint.push(i < bindingStartIndex ? null : NO_CHANGE);
9793 }
9794 return blueprint;
9795}
9796function createError(text, token) {
9797 return new Error(`Renderer: ${text} [${stringifyForError(token)}]`);
9798}
9799function assertHostNodeExists(rElement, elementOrSelector) {
9800 if (!rElement) {
9801 if (typeof elementOrSelector === 'string') {
9802 throw createError('Host node with selector not found:', elementOrSelector);
9803 }
9804 else {
9805 throw createError('Host node is required:', elementOrSelector);
9806 }
9807 }
9808}
9809/**
9810 * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
9811 *
9812 * @param rendererFactory Factory function to create renderer instance.
9813 * @param elementOrSelector Render element or CSS selector to locate the element.
9814 * @param encapsulation View Encapsulation defined for component that requests host element.
9815 */
9816function locateHostElement(renderer, elementOrSelector, encapsulation) {
9817 if (isProceduralRenderer(renderer)) {
9818 // When using native Shadow DOM, do not clear host element to allow native slot projection
9819 const preserveContent = encapsulation === ViewEncapsulation$1.ShadowDom;
9820 return renderer.selectRootElement(elementOrSelector, preserveContent);
9821 }
9822 let rElement = typeof elementOrSelector === 'string' ?
9823 renderer.querySelector(elementOrSelector) :
9824 elementOrSelector;
9825 ngDevMode && assertHostNodeExists(rElement, elementOrSelector);
9826 // Always clear host element's content when Renderer3 is in use. For procedural renderer case we
9827 // make it depend on whether ShadowDom encapsulation is used (in which case the content should be
9828 // preserved to allow native slot projection). ShadowDom encapsulation requires procedural
9829 // renderer, and procedural renderer case is handled above.
9830 rElement.textContent = '';
9831 return rElement;
9832}
9833/**
9834 * Saves context for this cleanup function in LView.cleanupInstances.
9835 *
9836 * On the first template pass, saves in TView:
9837 * - Cleanup function
9838 * - Index of context we just saved in LView.cleanupInstances
9839 *
9840 * This function can also be used to store instance specific cleanup fns. In that case the `context`
9841 * is `null` and the function is store in `LView` (rather than it `TView`).
9842 */
9843function storeCleanupWithContext(tView, lView, context, cleanupFn) {
9844 const lCleanup = getOrCreateLViewCleanup(lView);
9845 if (context === null) {
9846 // If context is null that this is instance specific callback. These callbacks can only be
9847 // inserted after template shared instances. For this reason in ngDevMode we freeze the TView.
9848 if (ngDevMode) {
9849 Object.freeze(getOrCreateTViewCleanup(tView));
9850 }
9851 lCleanup.push(cleanupFn);
9852 }
9853 else {
9854 lCleanup.push(context);
9855 if (tView.firstCreatePass) {
9856 getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
9857 }
9858 }
9859}
9860function createTNode(tView, tParent, type, index, value, attrs) {
9861 ngDevMode && index !== 0 && // 0 are bogus nodes and they are OK. See `createContainerRef` in
9862 // `view_engine_compatibility` for additional context.
9863 assertGreaterThanOrEqual(index, HEADER_OFFSET, 'TNodes can\'t be in the LView header.');
9864 ngDevMode && assertNotSame(attrs, undefined, '\'undefined\' is not valid value for \'attrs\'');
9865 ngDevMode && ngDevMode.tNode++;
9866 ngDevMode && tParent && assertTNodeForTView(tParent, tView);
9867 let injectorIndex = tParent ? tParent.injectorIndex : -1;
9868 const tNode = ngDevMode ?
9869 new TNodeDebug(tView, // tView_: TView
9870 type, // type: TNodeType
9871 index, // index: number
9872 null, // insertBeforeIndex: null|-1|number|number[]
9873 injectorIndex, // injectorIndex: number
9874 -1, // directiveStart: number
9875 -1, // directiveEnd: number
9876 -1, // directiveStylingLast: number
9877 null, // propertyBindings: number[]|null
9878 0, // flags: TNodeFlags
9879 0, // providerIndexes: TNodeProviderIndexes
9880 value, // value: string|null
9881 attrs, // attrs: (string|AttributeMarker|(string|SelectorFlags)[])[]|null
9882 null, // mergedAttrs
9883 null, // localNames: (string|number)[]|null
9884 undefined, // initialInputs: (string[]|null)[]|null|undefined
9885 null, // inputs: PropertyAliases|null
9886 null, // outputs: PropertyAliases|null
9887 null, // tViews: ITView|ITView[]|null
9888 null, // next: ITNode|null
9889 null, // projectionNext: ITNode|null
9890 null, // child: ITNode|null
9891 tParent, // parent: TElementNode|TContainerNode|null
9892 null, // projection: number|(ITNode|RNode[])[]|null
9893 null, // styles: string|null
9894 null, // stylesWithoutHost: string|null
9895 undefined, // residualStyles: string|null
9896 null, // classes: string|null
9897 null, // classesWithoutHost: string|null
9898 undefined, // residualClasses: string|null
9899 0, // classBindings: TStylingRange;
9900 0) :
9901 {
9902 type,
9903 index,
9904 insertBeforeIndex: null,
9905 injectorIndex,
9906 directiveStart: -1,
9907 directiveEnd: -1,
9908 directiveStylingLast: -1,
9909 propertyBindings: null,
9910 flags: 0,
9911 providerIndexes: 0,
9912 value: value,
9913 attrs: attrs,
9914 mergedAttrs: null,
9915 localNames: null,
9916 initialInputs: undefined,
9917 inputs: null,
9918 outputs: null,
9919 tViews: null,
9920 next: null,
9921 projectionNext: null,
9922 child: null,
9923 parent: tParent,
9924 projection: null,
9925 styles: null,
9926 stylesWithoutHost: null,
9927 residualStyles: undefined,
9928 classes: null,
9929 classesWithoutHost: null,
9930 residualClasses: undefined,
9931 classBindings: 0,
9932 styleBindings: 0,
9933 };
9934 if (ngDevMode) {
9935 // For performance reasons it is important that the tNode retains the same shape during runtime.
9936 // (To make sure that all of the code is monomorphic.) For this reason we seal the object to
9937 // prevent class transitions.
9938 Object.seal(tNode);
9939 }
9940 return tNode;
9941}
9942function generatePropertyAliases(inputAliasMap, directiveDefIdx, propStore) {
9943 for (let publicName in inputAliasMap) {
9944 if (inputAliasMap.hasOwnProperty(publicName)) {
9945 propStore = propStore === null ? {} : propStore;
9946 const internalName = inputAliasMap[publicName];
9947 if (propStore.hasOwnProperty(publicName)) {
9948 propStore[publicName].push(directiveDefIdx, internalName);
9949 }
9950 else {
9951 (propStore[publicName] = [directiveDefIdx, internalName]);
9952 }
9953 }
9954 }
9955 return propStore;
9956}
9957/**
9958 * Initializes data structures required to work with directive inputs and outputs.
9959 * Initialization is done for all directives matched on a given TNode.
9960 */
9961function initializeInputAndOutputAliases(tView, tNode) {
9962 ngDevMode && assertFirstCreatePass(tView);
9963 const start = tNode.directiveStart;
9964 const end = tNode.directiveEnd;
9965 const tViewData = tView.data;
9966 const tNodeAttrs = tNode.attrs;
9967 const inputsFromAttrs = ngDevMode ? new TNodeInitialInputs() : [];
9968 let inputsStore = null;
9969 let outputsStore = null;
9970 for (let i = start; i < end; i++) {
9971 const directiveDef = tViewData[i];
9972 const directiveInputs = directiveDef.inputs;
9973 // Do not use unbound attributes as inputs to structural directives, since structural
9974 // directive inputs can only be set using microsyntax (e.g. `<div *dir="exp">`).
9975 // TODO(FW-1930): microsyntax expressions may also contain unbound/static attributes, which
9976 // should be set for inline templates.
9977 const initialInputs = (tNodeAttrs !== null && !isInlineTemplate(tNode)) ?
9978 generateInitialInputs(directiveInputs, tNodeAttrs) :
9979 null;
9980 inputsFromAttrs.push(initialInputs);
9981 inputsStore = generatePropertyAliases(directiveInputs, i, inputsStore);
9982 outputsStore = generatePropertyAliases(directiveDef.outputs, i, outputsStore);
9983 }
9984 if (inputsStore !== null) {
9985 if (inputsStore.hasOwnProperty('class')) {
9986 tNode.flags |= 16 /* hasClassInput */;
9987 }
9988 if (inputsStore.hasOwnProperty('style')) {
9989 tNode.flags |= 32 /* hasStyleInput */;
9990 }
9991 }
9992 tNode.initialInputs = inputsFromAttrs;
9993 tNode.inputs = inputsStore;
9994 tNode.outputs = outputsStore;
9995}
9996/**
9997 * Mapping between attributes names that don't correspond to their element property names.
9998 *
9999 * Performance note: this function is written as a series of if checks (instead of, say, a property
10000 * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of
10001 * mapping property names. Do NOT change without benchmarking.
10002 *
10003 * Note: this mapping has to be kept in sync with the equally named mapping in the template
10004 * type-checking machinery of ngtsc.
10005 */
10006function mapPropName(name) {
10007 if (name === 'class')
10008 return 'className';
10009 if (name === 'for')
10010 return 'htmlFor';
10011 if (name === 'formaction')
10012 return 'formAction';
10013 if (name === 'innerHtml')
10014 return 'innerHTML';
10015 if (name === 'readonly')
10016 return 'readOnly';
10017 if (name === 'tabindex')
10018 return 'tabIndex';
10019 return name;
10020}
10021function elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, nativeOnly) {
10022 ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
10023 const element = getNativeByTNode(tNode, lView);
10024 let inputData = tNode.inputs;
10025 let dataValue;
10026 if (!nativeOnly && inputData != null && (dataValue = inputData[propName])) {
10027 setInputsForProperty(tView, lView, dataValue, propName, value);
10028 if (isComponentHost(tNode))
10029 markDirtyIfOnPush(lView, tNode.index);
10030 if (ngDevMode) {
10031 setNgReflectProperties(lView, element, tNode.type, dataValue, value);
10032 }
10033 }
10034 else if (tNode.type & 3 /* AnyRNode */) {
10035 propName = mapPropName(propName);
10036 if (ngDevMode) {
10037 validateAgainstEventProperties(propName);
10038 if (!validateProperty(tView, element, propName, tNode)) {
10039 // Return here since we only log warnings for unknown properties.
10040 logUnknownPropertyError(propName, tNode);
10041 return;
10042 }
10043 ngDevMode.rendererSetProperty++;
10044 }
10045 // It is assumed that the sanitizer is only added when the compiler determines that the
10046 // property is risky, so sanitization can be done without further checks.
10047 value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value;
10048 if (isProceduralRenderer(renderer)) {
10049 renderer.setProperty(element, propName, value);
10050 }
10051 else if (!isAnimationProp(propName)) {
10052 element.setProperty ? element.setProperty(propName, value) :
10053 element[propName] = value;
10054 }
10055 }
10056 else if (tNode.type & 12 /* AnyContainer */) {
10057 // If the node is a container and the property didn't
10058 // match any of the inputs or schemas we should throw.
10059 if (ngDevMode && !matchingSchemas(tView, tNode.value)) {
10060 logUnknownPropertyError(propName, tNode);
10061 }
10062 }
10063}
10064/** If node is an OnPush component, marks its LView dirty. */
10065function markDirtyIfOnPush(lView, viewIndex) {
10066 ngDevMode && assertLView(lView);
10067 const childComponentLView = getComponentLViewByIndex(viewIndex, lView);
10068 if (!(childComponentLView[FLAGS] & 16 /* CheckAlways */)) {
10069 childComponentLView[FLAGS] |= 64 /* Dirty */;
10070 }
10071}
10072function setNgReflectProperty(lView, element, type, attrName, value) {
10073 const renderer = lView[RENDERER];
10074 attrName = normalizeDebugBindingName(attrName);
10075 const debugValue = normalizeDebugBindingValue(value);
10076 if (type & 3 /* AnyRNode */) {
10077 if (value == null) {
10078 isProceduralRenderer(renderer) ? renderer.removeAttribute(element, attrName) :
10079 element.removeAttribute(attrName);
10080 }
10081 else {
10082 isProceduralRenderer(renderer) ?
10083 renderer.setAttribute(element, attrName, debugValue) :
10084 element.setAttribute(attrName, debugValue);
10085 }
10086 }
10087 else {
10088 const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
10089 if (isProceduralRenderer(renderer)) {
10090 renderer.setValue(element, textContent);
10091 }
10092 else {
10093 element.textContent = textContent;
10094 }
10095 }
10096}
10097function setNgReflectProperties(lView, element, type, dataValue, value) {
10098 if (type & (3 /* AnyRNode */ | 4 /* Container */)) {
10099 /**
10100 * dataValue is an array containing runtime input or output names for the directives:
10101 * i+0: directive instance index
10102 * i+1: privateName
10103 *
10104 * e.g. [0, 'change', 'change-minified']
10105 * we want to set the reflected property with the privateName: dataValue[i+1]
10106 */
10107 for (let i = 0; i < dataValue.length; i += 2) {
10108 setNgReflectProperty(lView, element, type, dataValue[i + 1], value);
10109 }
10110 }
10111}
10112function validateProperty(tView, element, propName, tNode) {
10113 // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
10114 // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
10115 // defined as an array (as an empty array in case `schemas` field is not defined) and we should
10116 // execute the check below.
10117 if (tView.schemas === null)
10118 return true;
10119 // The property is considered valid if the element matches the schema, it exists on the element
10120 // or it is synthetic, and we are in a browser context (web worker nodes should be skipped).
10121 if (matchingSchemas(tView, tNode.value) || propName in element || isAnimationProp(propName)) {
10122 return true;
10123 }
10124 // Note: `typeof Node` returns 'function' in most browsers, but on IE it is 'object' so we
10125 // need to account for both here, while being careful for `typeof null` also returning 'object'.
10126 return typeof Node === 'undefined' || Node === null || !(element instanceof Node);
10127}
10128function matchingSchemas(tView, tagName) {
10129 const schemas = tView.schemas;
10130 if (schemas !== null) {
10131 for (let i = 0; i < schemas.length; i++) {
10132 const schema = schemas[i];
10133 if (schema === NO_ERRORS_SCHEMA ||
10134 schema === CUSTOM_ELEMENTS_SCHEMA && tagName && tagName.indexOf('-') > -1) {
10135 return true;
10136 }
10137 }
10138 }
10139 return false;
10140}
10141/**
10142 * Logs an error that a property is not supported on an element.
10143 * @param propName Name of the invalid property.
10144 * @param tNode Node on which we encountered the property.
10145 */
10146function logUnknownPropertyError(propName, tNode) {
10147 let message = `Can't bind to '${propName}' since it isn't a known property of '${tNode.value}'.`;
10148 console.error(formatRuntimeError("303" /* UNKNOWN_BINDING */, message));
10149}
10150/**
10151 * Instantiate a root component.
10152 */
10153function instantiateRootComponent(tView, lView, def) {
10154 const rootTNode = getCurrentTNode();
10155 if (tView.firstCreatePass) {
10156 if (def.providersResolver)
10157 def.providersResolver(def);
10158 const directiveIndex = allocExpando(tView, lView, 1, null);
10159 ngDevMode &&
10160 assertEqual(directiveIndex, rootTNode.directiveStart, 'Because this is a root component the allocated expando should match the TNode component.');
10161 configureViewWithDirective(tView, rootTNode, lView, directiveIndex, def);
10162 }
10163 const directive = getNodeInjectable(lView, tView, rootTNode.directiveStart, rootTNode);
10164 attachPatchData(directive, lView);
10165 const native = getNativeByTNode(rootTNode, lView);
10166 if (native) {
10167 attachPatchData(native, lView);
10168 }
10169 return directive;
10170}
10171/**
10172 * Resolve the matched directives on a node.
10173 */
10174function resolveDirectives(tView, lView, tNode, localRefs) {
10175 // Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in
10176 // tsickle.
10177 ngDevMode && assertFirstCreatePass(tView);
10178 let hasDirectives = false;
10179 if (getBindingsEnabled()) {
10180 const directiveDefs = findDirectiveDefMatches(tView, lView, tNode);
10181 const exportsMap = localRefs === null ? null : { '': -1 };
10182 if (directiveDefs !== null) {
10183 hasDirectives = true;
10184 initTNodeFlags(tNode, tView.data.length, directiveDefs.length);
10185 // When the same token is provided by several directives on the same node, some rules apply in
10186 // the viewEngine:
10187 // - viewProviders have priority over providers
10188 // - the last directive in NgModule.declarations has priority over the previous one
10189 // So to match these rules, the order in which providers are added in the arrays is very
10190 // important.
10191 for (let i = 0; i < directiveDefs.length; i++) {
10192 const def = directiveDefs[i];
10193 if (def.providersResolver)
10194 def.providersResolver(def);
10195 }
10196 let preOrderHooksFound = false;
10197 let preOrderCheckHooksFound = false;
10198 let directiveIdx = allocExpando(tView, lView, directiveDefs.length, null);
10199 ngDevMode &&
10200 assertSame(directiveIdx, tNode.directiveStart, 'TNode.directiveStart should point to just allocated space');
10201 for (let i = 0; i < directiveDefs.length; i++) {
10202 const def = directiveDefs[i];
10203 // Merge the attrs in the order of matches. This assumes that the first directive is the
10204 // component itself, so that the component has the least priority.
10205 tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, def.hostAttrs);
10206 configureViewWithDirective(tView, tNode, lView, directiveIdx, def);
10207 saveNameToExportMap(directiveIdx, def, exportsMap);
10208 if (def.contentQueries !== null)
10209 tNode.flags |= 8 /* hasContentQuery */;
10210 if (def.hostBindings !== null || def.hostAttrs !== null || def.hostVars !== 0)
10211 tNode.flags |= 128 /* hasHostBindings */;
10212 const lifeCycleHooks = def.type.prototype;
10213 // Only push a node index into the preOrderHooks array if this is the first
10214 // pre-order hook found on this node.
10215 if (!preOrderHooksFound &&
10216 (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngOnInit || lifeCycleHooks.ngDoCheck)) {
10217 // We will push the actual hook function into this array later during dir instantiation.
10218 // We cannot do it now because we must ensure hooks are registered in the same
10219 // order that directives are created (i.e. injection order).
10220 (tView.preOrderHooks || (tView.preOrderHooks = [])).push(tNode.index);
10221 preOrderHooksFound = true;
10222 }
10223 if (!preOrderCheckHooksFound && (lifeCycleHooks.ngOnChanges || lifeCycleHooks.ngDoCheck)) {
10224 (tView.preOrderCheckHooks || (tView.preOrderCheckHooks = [])).push(tNode.index);
10225 preOrderCheckHooksFound = true;
10226 }
10227 directiveIdx++;
10228 }
10229 initializeInputAndOutputAliases(tView, tNode);
10230 }
10231 if (exportsMap)
10232 cacheMatchingLocalNames(tNode, localRefs, exportsMap);
10233 }
10234 // Merge the template attrs last so that they have the highest priority.
10235 tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
10236 return hasDirectives;
10237}
10238/**
10239 * Add `hostBindings` to the `TView.hostBindingOpCodes`.
10240 *
10241 * @param tView `TView` to which the `hostBindings` should be added.
10242 * @param tNode `TNode` the element which contains the directive
10243 * @param lView `LView` current `LView`
10244 * @param directiveIdx Directive index in view.
10245 * @param directiveVarsIdx Where will the directive's vars be stored
10246 * @param def `ComponentDef`/`DirectiveDef`, which contains the `hostVars`/`hostBindings` to add.
10247 */
10248function registerHostBindingOpCodes(tView, tNode, lView, directiveIdx, directiveVarsIdx, def) {
10249 ngDevMode && assertFirstCreatePass(tView);
10250 const hostBindings = def.hostBindings;
10251 if (hostBindings) {
10252 let hostBindingOpCodes = tView.hostBindingOpCodes;
10253 if (hostBindingOpCodes === null) {
10254 hostBindingOpCodes = tView.hostBindingOpCodes = [];
10255 }
10256 const elementIndx = ~tNode.index;
10257 if (lastSelectedElementIdx(hostBindingOpCodes) != elementIndx) {
10258 // Conditionally add select element so that we are more efficient in execution.
10259 // NOTE: this is strictly not necessary and it trades code size for runtime perf.
10260 // (We could just always add it.)
10261 hostBindingOpCodes.push(elementIndx);
10262 }
10263 hostBindingOpCodes.push(directiveIdx, directiveVarsIdx, hostBindings);
10264 }
10265}
10266/**
10267 * Returns the last selected element index in the `HostBindingOpCodes`
10268 *
10269 * For perf reasons we don't need to update the selected element index in `HostBindingOpCodes` only
10270 * if it changes. This method returns the last index (or '0' if not found.)
10271 *
10272 * Selected element index are only the ones which are negative.
10273 */
10274function lastSelectedElementIdx(hostBindingOpCodes) {
10275 let i = hostBindingOpCodes.length;
10276 while (i > 0) {
10277 const value = hostBindingOpCodes[--i];
10278 if (typeof value === 'number' && value < 0) {
10279 return value;
10280 }
10281 }
10282 return 0;
10283}
10284/**
10285 * Instantiate all the directives that were previously resolved on the current node.
10286 */
10287function instantiateAllDirectives(tView, lView, tNode, native) {
10288 const start = tNode.directiveStart;
10289 const end = tNode.directiveEnd;
10290 if (!tView.firstCreatePass) {
10291 getOrCreateNodeInjectorForNode(tNode, lView);
10292 }
10293 attachPatchData(native, lView);
10294 const initialInputs = tNode.initialInputs;
10295 for (let i = start; i < end; i++) {
10296 const def = tView.data[i];
10297 const isComponent = isComponentDef(def);
10298 if (isComponent) {
10299 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */);
10300 addComponentLogic(lView, tNode, def);
10301 }
10302 const directive = getNodeInjectable(lView, tView, i, tNode);
10303 attachPatchData(directive, lView);
10304 if (initialInputs !== null) {
10305 setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs);
10306 }
10307 if (isComponent) {
10308 const componentView = getComponentLViewByIndex(tNode.index, lView);
10309 componentView[CONTEXT] = directive;
10310 }
10311 }
10312}
10313function invokeDirectivesHostBindings(tView, lView, tNode) {
10314 const start = tNode.directiveStart;
10315 const end = tNode.directiveEnd;
10316 const firstCreatePass = tView.firstCreatePass;
10317 const elementIndex = tNode.index;
10318 const currentDirectiveIndex = getCurrentDirectiveIndex();
10319 try {
10320 setSelectedIndex(elementIndex);
10321 for (let dirIndex = start; dirIndex < end; dirIndex++) {
10322 const def = tView.data[dirIndex];
10323 const directive = lView[dirIndex];
10324 setCurrentDirectiveIndex(dirIndex);
10325 if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
10326 invokeHostBindingsInCreationMode(def, directive);
10327 }
10328 }
10329 }
10330 finally {
10331 setSelectedIndex(-1);
10332 setCurrentDirectiveIndex(currentDirectiveIndex);
10333 }
10334}
10335/**
10336 * Invoke the host bindings in creation mode.
10337 *
10338 * @param def `DirectiveDef` which may contain the `hostBindings` function.
10339 * @param directive Instance of directive.
10340 */
10341function invokeHostBindingsInCreationMode(def, directive) {
10342 if (def.hostBindings !== null) {
10343 def.hostBindings(1 /* Create */, directive);
10344 }
10345}
10346/**
10347 * Matches the current node against all available selectors.
10348 * If a component is matched (at most one), it is returned in first position in the array.
10349 */
10350function findDirectiveDefMatches(tView, viewData, tNode) {
10351 ngDevMode && assertFirstCreatePass(tView);
10352 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
10353 const registry = tView.directiveRegistry;
10354 let matches = null;
10355 if (registry) {
10356 for (let i = 0; i < registry.length; i++) {
10357 const def = registry[i];
10358 if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) {
10359 matches || (matches = ngDevMode ? new MatchesArray() : []);
10360 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, viewData), tView, def.type);
10361 if (isComponentDef(def)) {
10362 if (ngDevMode) {
10363 assertTNodeType(tNode, 2 /* Element */, `"${tNode.value}" tags cannot be used as component hosts. ` +
10364 `Please use a different tag to activate the ${stringify(def.type)} component.`);
10365 if (tNode.flags & 2 /* isComponentHost */)
10366 throwMultipleComponentError(tNode);
10367 }
10368 markAsComponentHost(tView, tNode);
10369 // The component is always stored first with directives after.
10370 matches.unshift(def);
10371 }
10372 else {
10373 matches.push(def);
10374 }
10375 }
10376 }
10377 }
10378 return matches;
10379}
10380/**
10381 * Marks a given TNode as a component's host. This consists of:
10382 * - setting appropriate TNode flags;
10383 * - storing index of component's host element so it will be queued for view refresh during CD.
10384 */
10385function markAsComponentHost(tView, hostTNode) {
10386 ngDevMode && assertFirstCreatePass(tView);
10387 hostTNode.flags |= 2 /* isComponentHost */;
10388 (tView.components || (tView.components = ngDevMode ? new TViewComponents() : []))
10389 .push(hostTNode.index);
10390}
10391/** Caches local names and their matching directive indices for query and template lookups. */
10392function cacheMatchingLocalNames(tNode, localRefs, exportsMap) {
10393 if (localRefs) {
10394 const localNames = tNode.localNames = ngDevMode ? new TNodeLocalNames() : [];
10395 // Local names must be stored in tNode in the same order that localRefs are defined
10396 // in the template to ensure the data is loaded in the same slots as their refs
10397 // in the template (for template queries).
10398 for (let i = 0; i < localRefs.length; i += 2) {
10399 const index = exportsMap[localRefs[i + 1]];
10400 if (index == null)
10401 throw new RuntimeError("301" /* EXPORT_NOT_FOUND */, `Export of name '${localRefs[i + 1]}' not found!`);
10402 localNames.push(localRefs[i], index);
10403 }
10404 }
10405}
10406/**
10407 * Builds up an export map as directives are created, so local refs can be quickly mapped
10408 * to their directive instances.
10409 */
10410function saveNameToExportMap(directiveIdx, def, exportsMap) {
10411 if (exportsMap) {
10412 if (def.exportAs) {
10413 for (let i = 0; i < def.exportAs.length; i++) {
10414 exportsMap[def.exportAs[i]] = directiveIdx;
10415 }
10416 }
10417 if (isComponentDef(def))
10418 exportsMap[''] = directiveIdx;
10419 }
10420}
10421/**
10422 * Initializes the flags on the current node, setting all indices to the initial index,
10423 * the directive count to 0, and adding the isComponent flag.
10424 * @param index the initial index
10425 */
10426function initTNodeFlags(tNode, index, numberOfDirectives) {
10427 ngDevMode &&
10428 assertNotEqual(numberOfDirectives, tNode.directiveEnd - tNode.directiveStart, 'Reached the max number of directives');
10429 tNode.flags |= 1 /* isDirectiveHost */;
10430 // When the first directive is created on a node, save the index
10431 tNode.directiveStart = index;
10432 tNode.directiveEnd = index + numberOfDirectives;
10433 tNode.providerIndexes = index;
10434}
10435/**
10436 * Setup directive for instantiation.
10437 *
10438 * We need to create a `NodeInjectorFactory` which is then inserted in both the `Blueprint` as well
10439 * as `LView`. `TView` gets the `DirectiveDef`.
10440 *
10441 * @param tView `TView`
10442 * @param tNode `TNode`
10443 * @param lView `LView`
10444 * @param directiveIndex Index where the directive will be stored in the Expando.
10445 * @param def `DirectiveDef`
10446 */
10447function configureViewWithDirective(tView, tNode, lView, directiveIndex, def) {
10448 ngDevMode &&
10449 assertGreaterThanOrEqual(directiveIndex, HEADER_OFFSET, 'Must be in Expando section');
10450 tView.data[directiveIndex] = def;
10451 const directiveFactory = def.factory || (def.factory = getFactoryDef(def.type, true));
10452 const nodeInjectorFactory = new NodeInjectorFactory(directiveFactory, isComponentDef(def), null);
10453 tView.blueprint[directiveIndex] = nodeInjectorFactory;
10454 lView[directiveIndex] = nodeInjectorFactory;
10455 registerHostBindingOpCodes(tView, tNode, lView, directiveIndex, allocExpando(tView, lView, def.hostVars, NO_CHANGE), def);
10456}
10457function addComponentLogic(lView, hostTNode, def) {
10458 const native = getNativeByTNode(hostTNode, lView);
10459 const tView = getOrCreateTComponentView(def);
10460 // Only component views should be added to the view tree directly. Embedded views are
10461 // accessed through their containers because they may be removed / re-added later.
10462 const rendererFactory = lView[RENDERER_FACTORY];
10463 const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 64 /* Dirty */ : 16 /* CheckAlways */, native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null));
10464 // Component view will always be created before any injected LContainers,
10465 // so this is a regular element, wrap it with the component view
10466 lView[hostTNode.index] = componentView;
10467}
10468function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) {
10469 if (ngDevMode) {
10470 assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
10471 validateAgainstEventAttributes(name);
10472 assertTNodeType(tNode, 2 /* Element */, `Attempted to set attribute \`${name}\` on a container node. ` +
10473 `Host bindings are not valid on ng-container or ng-template.`);
10474 }
10475 const element = getNativeByTNode(tNode, lView);
10476 setElementAttribute$1(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
10477}
10478function setElementAttribute$1(renderer, element, namespace, tagName, name, value, sanitizer) {
10479 if (value == null) {
10480 ngDevMode && ngDevMode.rendererRemoveAttribute++;
10481 isProceduralRenderer(renderer) ? renderer.removeAttribute(element, name, namespace) :
10482 element.removeAttribute(name);
10483 }
10484 else {
10485 ngDevMode && ngDevMode.rendererSetAttribute++;
10486 const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
10487 if (isProceduralRenderer(renderer)) {
10488 renderer.setAttribute(element, name, strValue, namespace);
10489 }
10490 else {
10491 namespace ? element.setAttributeNS(namespace, name, strValue) :
10492 element.setAttribute(name, strValue);
10493 }
10494 }
10495}
10496/**
10497 * Sets initial input properties on directive instances from attribute data
10498 *
10499 * @param lView Current LView that is being processed.
10500 * @param directiveIndex Index of the directive in directives array
10501 * @param instance Instance of the directive on which to set the initial inputs
10502 * @param def The directive def that contains the list of inputs
10503 * @param tNode The static data for this node
10504 */
10505function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
10506 const initialInputs = initialInputData[directiveIndex];
10507 if (initialInputs !== null) {
10508 const setInput = def.setInput;
10509 for (let i = 0; i < initialInputs.length;) {
10510 const publicName = initialInputs[i++];
10511 const privateName = initialInputs[i++];
10512 const value = initialInputs[i++];
10513 if (setInput !== null) {
10514 def.setInput(instance, value, publicName, privateName);
10515 }
10516 else {
10517 instance[privateName] = value;
10518 }
10519 if (ngDevMode) {
10520 const nativeElement = getNativeByTNode(tNode, lView);
10521 setNgReflectProperty(lView, nativeElement, tNode.type, privateName, value);
10522 }
10523 }
10524 }
10525}
10526/**
10527 * Generates initialInputData for a node and stores it in the template's static storage
10528 * so subsequent template invocations don't have to recalculate it.
10529 *
10530 * initialInputData is an array containing values that need to be set as input properties
10531 * for directives on this node, but only once on creation. We need this array to support
10532 * the case where you set an @Input property of a directive using attribute-like syntax.
10533 * e.g. if you have a `name` @Input, you can set it once like this:
10534 *
10535 * <my-component name="Bess"></my-component>
10536 *
10537 * @param inputs The list of inputs from the directive def
10538 * @param attrs The static attrs on this node
10539 */
10540function generateInitialInputs(inputs, attrs) {
10541 let inputsToStore = null;
10542 let i = 0;
10543 while (i < attrs.length) {
10544 const attrName = attrs[i];
10545 if (attrName === 0 /* NamespaceURI */) {
10546 // We do not allow inputs on namespaced attributes.
10547 i += 4;
10548 continue;
10549 }
10550 else if (attrName === 5 /* ProjectAs */) {
10551 // Skip over the `ngProjectAs` value.
10552 i += 2;
10553 continue;
10554 }
10555 // If we hit any other attribute markers, we're done anyway. None of those are valid inputs.
10556 if (typeof attrName === 'number')
10557 break;
10558 if (inputs.hasOwnProperty(attrName)) {
10559 if (inputsToStore === null)
10560 inputsToStore = [];
10561 inputsToStore.push(attrName, inputs[attrName], attrs[i + 1]);
10562 }
10563 i += 2;
10564 }
10565 return inputsToStore;
10566}
10567//////////////////////////
10568//// ViewContainer & View
10569//////////////////////////
10570// Not sure why I need to do `any` here but TS complains later.
10571const LContainerArray = class LContainer extends Array {
10572};
10573/**
10574 * Creates a LContainer, either from a container instruction, or for a ViewContainerRef.
10575 *
10576 * @param hostNative The host element for the LContainer
10577 * @param hostTNode The host TNode for the LContainer
10578 * @param currentView The parent view of the LContainer
10579 * @param native The native comment element
10580 * @param isForViewContainerRef Optional a flag indicating the ViewContainerRef case
10581 * @returns LContainer
10582 */
10583function createLContainer(hostNative, currentView, native, tNode) {
10584 ngDevMode && assertLView(currentView);
10585 ngDevMode && !isProceduralRenderer(currentView[RENDERER]) && assertDomNode(native);
10586 // https://jsperf.com/array-literal-vs-new-array-really
10587 const lContainer = new (ngDevMode ? LContainerArray : Array)(hostNative, // host native
10588 true, // Boolean `true` in this position signifies that this is an `LContainer`
10589 false, // has transplanted views
10590 currentView, // parent
10591 null, // next
10592 0, // transplanted views to refresh count
10593 tNode, // t_host
10594 native, // native,
10595 null, // view refs
10596 null);
10597 ngDevMode &&
10598 assertEqual(lContainer.length, CONTAINER_HEADER_OFFSET, 'Should allocate correct number of slots for LContainer header.');
10599 ngDevMode && attachLContainerDebug(lContainer);
10600 return lContainer;
10601}
10602/**
10603 * Goes over embedded views (ones created through ViewContainerRef APIs) and refreshes
10604 * them by executing an associated template function.
10605 */
10606function refreshEmbeddedViews(lView) {
10607 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
10608 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
10609 const embeddedLView = lContainer[i];
10610 const embeddedTView = embeddedLView[TVIEW];
10611 ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
10612 if (viewAttachedToChangeDetector(embeddedLView)) {
10613 refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
10614 }
10615 }
10616 }
10617}
10618/**
10619 * Mark transplanted views as needing to be refreshed at their insertion points.
10620 *
10621 * @param lView The `LView` that may have transplanted views.
10622 */
10623function markTransplantedViewsForRefresh(lView) {
10624 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
10625 if (!lContainer[HAS_TRANSPLANTED_VIEWS])
10626 continue;
10627 const movedViews = lContainer[MOVED_VIEWS];
10628 ngDevMode && assertDefined(movedViews, 'Transplanted View flags set but missing MOVED_VIEWS');
10629 for (let i = 0; i < movedViews.length; i++) {
10630 const movedLView = movedViews[i];
10631 const insertionLContainer = movedLView[PARENT];
10632 ngDevMode && assertLContainer(insertionLContainer);
10633 // We don't want to increment the counter if the moved LView was already marked for
10634 // refresh.
10635 if ((movedLView[FLAGS] & 1024 /* RefreshTransplantedView */) === 0) {
10636 updateTransplantedViewCount(insertionLContainer, 1);
10637 }
10638 // Note, it is possible that the `movedViews` is tracking views that are transplanted *and*
10639 // those that aren't (declaration component === insertion component). In the latter case,
10640 // it's fine to add the flag, as we will clear it immediately in
10641 // `refreshEmbeddedViews` for the view currently being refreshed.
10642 movedLView[FLAGS] |= 1024 /* RefreshTransplantedView */;
10643 }
10644 }
10645}
10646/////////////
10647/**
10648 * Refreshes components by entering the component view and processing its bindings, queries, etc.
10649 *
10650 * @param componentHostIdx Element index in LView[] (adjusted for HEADER_OFFSET)
10651 */
10652function refreshComponent(hostLView, componentHostIdx) {
10653 ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');
10654 const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
10655 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
10656 if (viewAttachedToChangeDetector(componentView)) {
10657 const tView = componentView[TVIEW];
10658 if (componentView[FLAGS] & (16 /* CheckAlways */ | 64 /* Dirty */)) {
10659 refreshView(tView, componentView, tView.template, componentView[CONTEXT]);
10660 }
10661 else if (componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
10662 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
10663 refreshContainsDirtyView(componentView);
10664 }
10665 }
10666}
10667/**
10668 * Refreshes all transplanted views marked with `LViewFlags.RefreshTransplantedView` that are
10669 * children or descendants of the given lView.
10670 *
10671 * @param lView The lView which contains descendant transplanted views that need to be refreshed.
10672 */
10673function refreshContainsDirtyView(lView) {
10674 for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
10675 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
10676 const embeddedLView = lContainer[i];
10677 if (embeddedLView[FLAGS] & 1024 /* RefreshTransplantedView */) {
10678 const embeddedTView = embeddedLView[TVIEW];
10679 ngDevMode && assertDefined(embeddedTView, 'TView must be allocated');
10680 refreshView(embeddedTView, embeddedLView, embeddedTView.template, embeddedLView[CONTEXT]);
10681 }
10682 else if (embeddedLView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
10683 refreshContainsDirtyView(embeddedLView);
10684 }
10685 }
10686 }
10687 const tView = lView[TVIEW];
10688 // Refresh child component views.
10689 const components = tView.components;
10690 if (components !== null) {
10691 for (let i = 0; i < components.length; i++) {
10692 const componentView = getComponentLViewByIndex(components[i], lView);
10693 // Only attached components that are CheckAlways or OnPush and dirty should be refreshed
10694 if (viewAttachedToChangeDetector(componentView) &&
10695 componentView[TRANSPLANTED_VIEWS_TO_REFRESH] > 0) {
10696 refreshContainsDirtyView(componentView);
10697 }
10698 }
10699 }
10700}
10701function renderComponent$1(hostLView, componentHostIdx) {
10702 ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
10703 const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
10704 const componentTView = componentView[TVIEW];
10705 syncViewWithBlueprint(componentTView, componentView);
10706 renderView(componentTView, componentView, componentView[CONTEXT]);
10707}
10708/**
10709 * Syncs an LView instance with its blueprint if they have gotten out of sync.
10710 *
10711 * Typically, blueprints and their view instances should always be in sync, so the loop here
10712 * will be skipped. However, consider this case of two components side-by-side:
10713 *
10714 * App template:
10715 * ```
10716 * <comp></comp>
10717 * <comp></comp>
10718 * ```
10719 *
10720 * The following will happen:
10721 * 1. App template begins processing.
10722 * 2. First <comp> is matched as a component and its LView is created.
10723 * 3. Second <comp> is matched as a component and its LView is created.
10724 * 4. App template completes processing, so it's time to check child templates.
10725 * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.
10726 * 6. Second <comp> template is checked. Its blueprint has been updated by the first
10727 * <comp> template, but its LView was created before this update, so it is out of sync.
10728 *
10729 * Note that embedded views inside ngFor loops will never be out of sync because these views
10730 * are processed as soon as they are created.
10731 *
10732 * @param tView The `TView` that contains the blueprint for syncing
10733 * @param lView The view to sync
10734 */
10735function syncViewWithBlueprint(tView, lView) {
10736 for (let i = lView.length; i < tView.blueprint.length; i++) {
10737 lView.push(tView.blueprint[i]);
10738 }
10739}
10740/**
10741 * Adds LView or LContainer to the end of the current view tree.
10742 *
10743 * This structure will be used to traverse through nested views to remove listeners
10744 * and call onDestroy callbacks.
10745 *
10746 * @param lView The view where LView or LContainer should be added
10747 * @param adjustedHostIndex Index of the view's host node in LView[], adjusted for header
10748 * @param lViewOrLContainer The LView or LContainer to add to the view tree
10749 * @returns The state passed in
10750 */
10751function addToViewTree(lView, lViewOrLContainer) {
10752 // TODO(benlesh/misko): This implementation is incorrect, because it always adds the LContainer
10753 // to the end of the queue, which means if the developer retrieves the LContainers from RNodes out
10754 // of order, the change detection will run out of order, as the act of retrieving the the
10755 // LContainer from the RNode is what adds it to the queue.
10756 if (lView[CHILD_HEAD]) {
10757 lView[CHILD_TAIL][NEXT] = lViewOrLContainer;
10758 }
10759 else {
10760 lView[CHILD_HEAD] = lViewOrLContainer;
10761 }
10762 lView[CHILD_TAIL] = lViewOrLContainer;
10763 return lViewOrLContainer;
10764}
10765///////////////////////////////
10766//// Change detection
10767///////////////////////////////
10768/**
10769 * Marks current view and all ancestors dirty.
10770 *
10771 * Returns the root view because it is found as a byproduct of marking the view tree
10772 * dirty, and can be used by methods that consume markViewDirty() to easily schedule
10773 * change detection. Otherwise, such methods would need to traverse up the view tree
10774 * an additional time to get the root view and schedule a tick on it.
10775 *
10776 * @param lView The starting LView to mark dirty
10777 * @returns the root LView
10778 */
10779function markViewDirty(lView) {
10780 while (lView) {
10781 lView[FLAGS] |= 64 /* Dirty */;
10782 const parent = getLViewParent(lView);
10783 // Stop traversing up as soon as you find a root view that wasn't attached to any container
10784 if (isRootView(lView) && !parent) {
10785 return lView;
10786 }
10787 // continue otherwise
10788 lView = parent;
10789 }
10790 return null;
10791}
10792/**
10793 * Used to schedule change detection on the whole application.
10794 *
10795 * Unlike `tick`, `scheduleTick` coalesces multiple calls into one change detection run.
10796 * It is usually called indirectly by calling `markDirty` when the view needs to be
10797 * re-rendered.
10798 *
10799 * Typically `scheduleTick` uses `requestAnimationFrame` to coalesce multiple
10800 * `scheduleTick` requests. The scheduling function can be overridden in
10801 * `renderComponent`'s `scheduler` option.
10802 */
10803function scheduleTick(rootContext, flags) {
10804 const nothingScheduled = rootContext.flags === 0 /* Empty */;
10805 if (nothingScheduled && rootContext.clean == _CLEAN_PROMISE) {
10806 // https://github.com/angular/angular/issues/39296
10807 // should only attach the flags when really scheduling a tick
10808 rootContext.flags |= flags;
10809 let res;
10810 rootContext.clean = new Promise((r) => res = r);
10811 rootContext.scheduler(() => {
10812 if (rootContext.flags & 1 /* DetectChanges */) {
10813 rootContext.flags &= ~1 /* DetectChanges */;
10814 tickRootContext(rootContext);
10815 }
10816 if (rootContext.flags & 2 /* FlushPlayers */) {
10817 rootContext.flags &= ~2 /* FlushPlayers */;
10818 const playerHandler = rootContext.playerHandler;
10819 if (playerHandler) {
10820 playerHandler.flushPlayers();
10821 }
10822 }
10823 rootContext.clean = _CLEAN_PROMISE;
10824 res(null);
10825 });
10826 }
10827}
10828function tickRootContext(rootContext) {
10829 for (let i = 0; i < rootContext.components.length; i++) {
10830 const rootComponent = rootContext.components[i];
10831 const lView = readPatchedLView(rootComponent);
10832 const tView = lView[TVIEW];
10833 renderComponentOrTemplate(tView, lView, tView.template, rootComponent);
10834 }
10835}
10836function detectChangesInternal(tView, lView, context) {
10837 const rendererFactory = lView[RENDERER_FACTORY];
10838 if (rendererFactory.begin)
10839 rendererFactory.begin();
10840 try {
10841 refreshView(tView, lView, tView.template, context);
10842 }
10843 catch (error) {
10844 handleError(lView, error);
10845 throw error;
10846 }
10847 finally {
10848 if (rendererFactory.end)
10849 rendererFactory.end();
10850 }
10851}
10852/**
10853 * Synchronously perform change detection on a root view and its components.
10854 *
10855 * @param lView The view which the change detection should be performed on.
10856 */
10857function detectChangesInRootView(lView) {
10858 tickRootContext(lView[CONTEXT]);
10859}
10860function checkNoChangesInternal(tView, view, context) {
10861 setIsInCheckNoChangesMode(true);
10862 try {
10863 detectChangesInternal(tView, view, context);
10864 }
10865 finally {
10866 setIsInCheckNoChangesMode(false);
10867 }
10868}
10869/**
10870 * Checks the change detector on a root view and its components, and throws if any changes are
10871 * detected.
10872 *
10873 * This is used in development mode to verify that running change detection doesn't
10874 * introduce other changes.
10875 *
10876 * @param lView The view which the change detection should be checked on.
10877 */
10878function checkNoChangesInRootView(lView) {
10879 setIsInCheckNoChangesMode(true);
10880 try {
10881 detectChangesInRootView(lView);
10882 }
10883 finally {
10884 setIsInCheckNoChangesMode(false);
10885 }
10886}
10887function executeViewQueryFn(flags, viewQueryFn, component) {
10888 ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
10889 setCurrentQueryIndex(0);
10890 viewQueryFn(flags, component);
10891}
10892///////////////////////////////
10893//// Bindings & interpolations
10894///////////////////////////////
10895/**
10896 * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
10897 *
10898 * In order to support TestBed's `DebugElement.properties` we need to save, for each binding:
10899 * - a bound property name;
10900 * - a static parts of interpolated strings;
10901 *
10902 * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a
10903 * property binding metadata will be stored in `TView.data` at the same index as a bound value in
10904 * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
10905 * following format:
10906 * - `propertyName` for bound properties;
10907 * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for
10908 * interpolated properties.
10909 *
10910 * @param tData `TData` where meta-data will be saved;
10911 * @param tNode `TNode` that is a target of the binding;
10912 * @param propertyName bound property name;
10913 * @param bindingIndex binding index in `LView`
10914 * @param interpolationParts static interpolation parts (for property interpolations)
10915 */
10916function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) {
10917 // Binding meta-data are stored only the first time a given property instruction is processed.
10918 // Since we don't have a concept of the "first update pass" we need to check for presence of the
10919 // binding meta-data to decide if one should be stored (or if was stored already).
10920 if (tData[bindingIndex] === null) {
10921 if (tNode.inputs == null || !tNode.inputs[propertyName]) {
10922 const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
10923 propBindingIdxs.push(bindingIndex);
10924 let bindingMetadata = propertyName;
10925 if (interpolationParts.length > 0) {
10926 bindingMetadata +=
10927 INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
10928 }
10929 tData[bindingIndex] = bindingMetadata;
10930 }
10931 }
10932}
10933const CLEAN_PROMISE = _CLEAN_PROMISE;
10934function getOrCreateLViewCleanup(view) {
10935 // top level variables should not be exported for performance reasons (PERF_NOTES.md)
10936 return view[CLEANUP] || (view[CLEANUP] = ngDevMode ? new LCleanup() : []);
10937}
10938function getOrCreateTViewCleanup(tView) {
10939 return tView.cleanup || (tView.cleanup = ngDevMode ? new TCleanup() : []);
10940}
10941/**
10942 * There are cases where the sub component's renderer needs to be included
10943 * instead of the current renderer (see the componentSyntheticHost* instructions).
10944 */
10945function loadComponentRenderer(currentDef, tNode, lView) {
10946 // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root
10947 // component (see packages/core/src/render3/component.ts). This is not consistent with the process
10948 // of creating inner components, when current directive index is available in the state. In order
10949 // to avoid relying on current def being `null` (thus special-casing root component creation), the
10950 // process of creating root component should be unified with the process of creating inner
10951 // components.
10952 if (currentDef === null || isComponentDef(currentDef)) {
10953 lView = unwrapLView(lView[tNode.index]);
10954 }
10955 return lView[RENDERER];
10956}
10957/** Handles an error thrown in an LView. */
10958function handleError(lView, error) {
10959 const injector = lView[INJECTOR$1];
10960 const errorHandler = injector ? injector.get(ErrorHandler, null) : null;
10961 errorHandler && errorHandler.handleError(error);
10962}
10963/**
10964 * Set the inputs of directives at the current node to corresponding value.
10965 *
10966 * @param tView The current TView
10967 * @param lView the `LView` which contains the directives.
10968 * @param inputs mapping between the public "input" name and privately-known,
10969 * possibly minified, property names to write to.
10970 * @param value Value to set.
10971 */
10972function setInputsForProperty(tView, lView, inputs, publicName, value) {
10973 for (let i = 0; i < inputs.length;) {
10974 const index = inputs[i++];
10975 const privateName = inputs[i++];
10976 const instance = lView[index];
10977 ngDevMode && assertIndexInRange(lView, index);
10978 const def = tView.data[index];
10979 if (def.setInput !== null) {
10980 def.setInput(instance, value, publicName, privateName);
10981 }
10982 else {
10983 instance[privateName] = value;
10984 }
10985 }
10986}
10987/**
10988 * Updates a text binding at a given index in a given LView.
10989 */
10990function textBindingInternal(lView, index, value) {
10991 ngDevMode && assertString(value, 'Value should be a string');
10992 ngDevMode && assertNotSame(value, NO_CHANGE, 'value should not be NO_CHANGE');
10993 ngDevMode && assertIndexInRange(lView, index);
10994 const element = getNativeByIndex(index, lView);
10995 ngDevMode && assertDefined(element, 'native element should exist');
10996 updateTextNode(lView[RENDERER], element, value);
10997}
10998
10999/**
11000 * @license
11001 * Copyright Google LLC All Rights Reserved.
11002 *
11003 * Use of this source code is governed by an MIT-style license that can be
11004 * found in the LICENSE file at https://angular.io/license
11005 */
11006/**
11007 * Compute the static styling (class/style) from `TAttributes`.
11008 *
11009 * This function should be called during `firstCreatePass` only.
11010 *
11011 * @param tNode The `TNode` into which the styling information should be loaded.
11012 * @param attrs `TAttributes` containing the styling information.
11013 * @param writeToHost Where should the resulting static styles be written?
11014 * - `false` Write to `TNode.stylesWithoutHost` / `TNode.classesWithoutHost`
11015 * - `true` Write to `TNode.styles` / `TNode.classes`
11016 */
11017function computeStaticStyling(tNode, attrs, writeToHost) {
11018 ngDevMode &&
11019 assertFirstCreatePass(getTView(), 'Expecting to be called in first template pass only');
11020 let styles = writeToHost ? tNode.styles : null;
11021 let classes = writeToHost ? tNode.classes : null;
11022 let mode = 0;
11023 if (attrs !== null) {
11024 for (let i = 0; i < attrs.length; i++) {
11025 const value = attrs[i];
11026 if (typeof value === 'number') {
11027 mode = value;
11028 }
11029 else if (mode == 1 /* Classes */) {
11030 classes = concatStringsWithSpace(classes, value);
11031 }
11032 else if (mode == 2 /* Styles */) {
11033 const style = value;
11034 const styleValue = attrs[++i];
11035 styles = concatStringsWithSpace(styles, style + ': ' + styleValue + ';');
11036 }
11037 }
11038 }
11039 writeToHost ? tNode.styles = styles : tNode.stylesWithoutHost = styles;
11040 writeToHost ? tNode.classes = classes : tNode.classesWithoutHost = classes;
11041}
11042
11043/**
11044 * @license
11045 * Copyright Google LLC All Rights Reserved.
11046 *
11047 * Use of this source code is governed by an MIT-style license that can be
11048 * found in the LICENSE file at https://angular.io/license
11049 */
11050/**
11051 * Synchronously perform change detection on a component (and possibly its sub-components).
11052 *
11053 * This function triggers change detection in a synchronous way on a component.
11054 *
11055 * @param component The component which the change detection should be performed on.
11056 */
11057function detectChanges(component) {
11058 const view = getComponentViewByInstance(component);
11059 detectChangesInternal(view[TVIEW], view, component);
11060}
11061/**
11062 * Marks the component as dirty (needing change detection). Marking a component dirty will
11063 * schedule a change detection on it at some point in the future.
11064 *
11065 * Marking an already dirty component as dirty won't do anything. Only one outstanding change
11066 * detection can be scheduled per component tree.
11067 *
11068 * @param component Component to mark as dirty.
11069 */
11070function markDirty(component) {
11071 ngDevMode && assertDefined(component, 'component');
11072 const rootView = markViewDirty(getComponentViewByInstance(component));
11073 ngDevMode && assertDefined(rootView[CONTEXT], 'rootContext should be defined');
11074 scheduleTick(rootView[CONTEXT], 1 /* DetectChanges */);
11075}
11076/**
11077 * Used to perform change detection on the whole application.
11078 *
11079 * This is equivalent to `detectChanges`, but invoked on root component. Additionally, `tick`
11080 * executes lifecycle hooks and conditionally checks components based on their
11081 * `ChangeDetectionStrategy` and dirtiness.
11082 *
11083 * The preferred way to trigger change detection is to call `markDirty`. `markDirty` internally
11084 * schedules `tick` using a scheduler in order to coalesce multiple `markDirty` calls into a
11085 * single change detection run. By default, the scheduler is `requestAnimationFrame`, but can
11086 * be changed when calling `renderComponent` and providing the `scheduler` option.
11087 */
11088function tick(component) {
11089 const rootView = getRootView(component);
11090 const rootContext = rootView[CONTEXT];
11091 tickRootContext(rootContext);
11092}
11093
11094/**
11095 * @license
11096 * Copyright Google LLC All Rights Reserved.
11097 *
11098 * Use of this source code is governed by an MIT-style license that can be
11099 * found in the LICENSE file at https://angular.io/license
11100 */
11101/**
11102 * An InjectionToken that gets the current `Injector` for `createInjector()`-style injectors.
11103 *
11104 * Requesting this token instead of `Injector` allows `StaticInjector` to be tree-shaken from a
11105 * project.
11106 *
11107 * @publicApi
11108 */
11109const INJECTOR = new InjectionToken('INJECTOR',
11110// Dissable tslint because this is const enum which gets inlined not top level prop access.
11111// tslint:disable-next-line: no-toplevel-property-access
11112-1 /* Injector */);
11113
11114/**
11115 * @license
11116 * Copyright Google LLC All Rights Reserved.
11117 *
11118 * Use of this source code is governed by an MIT-style license that can be
11119 * found in the LICENSE file at https://angular.io/license
11120 */
11121class NullInjector {
11122 get(token, notFoundValue = THROW_IF_NOT_FOUND) {
11123 if (notFoundValue === THROW_IF_NOT_FOUND) {
11124 const error = new Error(`NullInjectorError: No provider for ${stringify(token)}!`);
11125 error.name = 'NullInjectorError';
11126 throw error;
11127 }
11128 return notFoundValue;
11129 }
11130}
11131
11132/**
11133 * @license
11134 * Copyright Google LLC All Rights Reserved.
11135 *
11136 * Use of this source code is governed by an MIT-style license that can be
11137 * found in the LICENSE file at https://angular.io/license
11138 */
11139/**
11140 * An internal token whose presence in an injector indicates that the injector should treat itself
11141 * as a root scoped injector when processing requests for unknown tokens which may indicate
11142 * they are provided in the root scope.
11143 */
11144const INJECTOR_SCOPE = new InjectionToken('Set Injector scope.');
11145
11146/**
11147 * @license
11148 * Copyright Google LLC All Rights Reserved.
11149 *
11150 * Use of this source code is governed by an MIT-style license that can be
11151 * found in the LICENSE file at https://angular.io/license
11152 */
11153/**
11154 * Marker which indicates that a value has not yet been created from the factory function.
11155 */
11156const NOT_YET = {};
11157/**
11158 * Marker which indicates that the factory function for a token is in the process of being called.
11159 *
11160 * If the injector is asked to inject a token with its value set to CIRCULAR, that indicates
11161 * injection of a dependency has recursively attempted to inject the original token, and there is
11162 * a circular dependency among the providers.
11163 */
11164const CIRCULAR$1 = {};
11165/**
11166 * A lazily initialized NullInjector.
11167 */
11168let NULL_INJECTOR$1 = undefined;
11169function getNullInjector() {
11170 if (NULL_INJECTOR$1 === undefined) {
11171 NULL_INJECTOR$1 = new NullInjector();
11172 }
11173 return NULL_INJECTOR$1;
11174}
11175/**
11176 * Create a new `Injector` which is configured using a `defType` of `InjectorType<any>`s.
11177 *
11178 * @publicApi
11179 */
11180function createInjector$1(defType, parent = null, additionalProviders = null, name) {
11181 const injector = createInjectorWithoutInjectorInstances(defType, parent, additionalProviders, name);
11182 injector._resolveInjectorDefTypes();
11183 return injector;
11184}
11185/**
11186 * Creates a new injector without eagerly resolving its injector types. Can be used in places
11187 * where resolving the injector types immediately can lead to an infinite loop. The injector types
11188 * should be resolved at a later point by calling `_resolveInjectorDefTypes`.
11189 */
11190function createInjectorWithoutInjectorInstances(defType, parent = null, additionalProviders = null, name) {
11191 return new R3Injector(defType, additionalProviders, parent || getNullInjector(), name);
11192}
11193class R3Injector {
11194 constructor(def, additionalProviders, parent, source = null) {
11195 this.parent = parent;
11196 /**
11197 * Map of tokens to records which contain the instances of those tokens.
11198 * - `null` value implies that we don't have the record. Used by tree-shakable injectors
11199 * to prevent further searches.
11200 */
11201 this.records = new Map();
11202 /**
11203 * The transitive set of `InjectorType`s which define this injector.
11204 */
11205 this.injectorDefTypes = new Set();
11206 /**
11207 * Set of values instantiated by this injector which contain `ngOnDestroy` lifecycle hooks.
11208 */
11209 this.onDestroy = new Set();
11210 this._destroyed = false;
11211 const dedupStack = [];
11212 // Start off by creating Records for every provider declared in every InjectorType
11213 // included transitively in additional providers then do the same for `def`. This order is
11214 // important because `def` may include providers that override ones in additionalProviders.
11215 additionalProviders &&
11216 deepForEach(additionalProviders, provider => this.processProvider(provider, def, additionalProviders));
11217 deepForEach([def], injectorDef => this.processInjectorType(injectorDef, [], dedupStack));
11218 // Make sure the INJECTOR token provides this injector.
11219 this.records.set(INJECTOR, makeRecord(undefined, this));
11220 // Detect whether this injector has the APP_ROOT_SCOPE token and thus should provide
11221 // any injectable scoped to APP_ROOT_SCOPE.
11222 const record = this.records.get(INJECTOR_SCOPE);
11223 this.scope = record != null ? record.value : null;
11224 // Source name, used for debugging
11225 this.source = source || (typeof def === 'object' ? null : stringify(def));
11226 }
11227 /**
11228 * Flag indicating that this injector was previously destroyed.
11229 */
11230 get destroyed() {
11231 return this._destroyed;
11232 }
11233 /**
11234 * Destroy the injector and release references to every instance or provider associated with it.
11235 *
11236 * Also calls the `OnDestroy` lifecycle hooks of every instance that was created for which a
11237 * hook was found.
11238 */
11239 destroy() {
11240 this.assertNotDestroyed();
11241 // Set destroyed = true first, in case lifecycle hooks re-enter destroy().
11242 this._destroyed = true;
11243 try {
11244 // Call all the lifecycle hooks.
11245 this.onDestroy.forEach(service => service.ngOnDestroy());
11246 }
11247 finally {
11248 // Release all references.
11249 this.records.clear();
11250 this.onDestroy.clear();
11251 this.injectorDefTypes.clear();
11252 }
11253 }
11254 get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
11255 this.assertNotDestroyed();
11256 // Set the injection context.
11257 const previousInjector = setCurrentInjector(this);
11258 const previousInjectImplementation = setInjectImplementation(undefined);
11259 try {
11260 // Check for the SkipSelf flag.
11261 if (!(flags & InjectFlags.SkipSelf)) {
11262 // SkipSelf isn't set, check if the record belongs to this injector.
11263 let record = this.records.get(token);
11264 if (record === undefined) {
11265 // No record, but maybe the token is scoped to this injector. Look for an injectable
11266 // def with a scope matching this injector.
11267 const def = couldBeInjectableType(token) && getInjectableDef(token);
11268 if (def && this.injectableDefInScope(def)) {
11269 // Found an injectable def and it's scoped to this injector. Pretend as if it was here
11270 // all along.
11271 record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);
11272 }
11273 else {
11274 record = null;
11275 }
11276 this.records.set(token, record);
11277 }
11278 // If a record was found, get the instance for it and return it.
11279 if (record != null /* NOT null || undefined */) {
11280 return this.hydrate(token, record);
11281 }
11282 }
11283 // Select the next injector based on the Self flag - if self is set, the next injector is
11284 // the NullInjector, otherwise it's the parent.
11285 const nextInjector = !(flags & InjectFlags.Self) ? this.parent : getNullInjector();
11286 // Set the notFoundValue based on the Optional flag - if optional is set and notFoundValue
11287 // is undefined, the value is null, otherwise it's the notFoundValue.
11288 notFoundValue = (flags & InjectFlags.Optional) && notFoundValue === THROW_IF_NOT_FOUND ?
11289 null :
11290 notFoundValue;
11291 return nextInjector.get(token, notFoundValue);
11292 }
11293 catch (e) {
11294 if (e.name === 'NullInjectorError') {
11295 const path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
11296 path.unshift(stringify(token));
11297 if (previousInjector) {
11298 // We still have a parent injector, keep throwing
11299 throw e;
11300 }
11301 else {
11302 // Format & throw the final error message when we don't have any previous injector
11303 return catchInjectorError(e, token, 'R3InjectorError', this.source);
11304 }
11305 }
11306 else {
11307 throw e;
11308 }
11309 }
11310 finally {
11311 // Lastly, restore the previous injection context.
11312 setInjectImplementation(previousInjectImplementation);
11313 setCurrentInjector(previousInjector);
11314 }
11315 }
11316 /** @internal */
11317 _resolveInjectorDefTypes() {
11318 this.injectorDefTypes.forEach(defType => this.get(defType));
11319 }
11320 toString() {
11321 const tokens = [], records = this.records;
11322 records.forEach((v, token) => tokens.push(stringify(token)));
11323 return `R3Injector[${tokens.join(', ')}]`;
11324 }
11325 assertNotDestroyed() {
11326 if (this._destroyed) {
11327 throw new Error('Injector has already been destroyed.');
11328 }
11329 }
11330 /**
11331 * Add an `InjectorType` or `InjectorTypeWithProviders` and all of its transitive providers
11332 * to this injector.
11333 *
11334 * If an `InjectorTypeWithProviders` that declares providers besides the type is specified,
11335 * the function will return "true" to indicate that the providers of the type definition need
11336 * to be processed. This allows us to process providers of injector types after all imports of
11337 * an injector definition are processed. (following View Engine semantics: see FW-1349)
11338 */
11339 processInjectorType(defOrWrappedDef, parents, dedupStack) {
11340 defOrWrappedDef = resolveForwardRef(defOrWrappedDef);
11341 if (!defOrWrappedDef)
11342 return false;
11343 // Either the defOrWrappedDef is an InjectorType (with injector def) or an
11344 // InjectorDefTypeWithProviders (aka ModuleWithProviders). Detecting either is a megamorphic
11345 // read, so care is taken to only do the read once.
11346 // First attempt to read the injector def (`ɵinj`).
11347 let def = getInjectorDef(defOrWrappedDef);
11348 // If that's not present, then attempt to read ngModule from the InjectorDefTypeWithProviders.
11349 const ngModule = (def == null) && defOrWrappedDef.ngModule || undefined;
11350 // Determine the InjectorType. In the case where `defOrWrappedDef` is an `InjectorType`,
11351 // then this is easy. In the case of an InjectorDefTypeWithProviders, then the definition type
11352 // is the `ngModule`.
11353 const defType = (ngModule === undefined) ? defOrWrappedDef : ngModule;
11354 // Check for circular dependencies.
11355 if (ngDevMode && parents.indexOf(defType) !== -1) {
11356 const defName = stringify(defType);
11357 const path = parents.map(stringify);
11358 throwCyclicDependencyError(defName, path);
11359 }
11360 // Check for multiple imports of the same module
11361 const isDuplicate = dedupStack.indexOf(defType) !== -1;
11362 // Finally, if defOrWrappedType was an `InjectorDefTypeWithProviders`, then the actual
11363 // `InjectorDef` is on its `ngModule`.
11364 if (ngModule !== undefined) {
11365 def = getInjectorDef(ngModule);
11366 }
11367 // If no definition was found, it might be from exports. Remove it.
11368 if (def == null) {
11369 return false;
11370 }
11371 // Add providers in the same way that @NgModule resolution did:
11372 // First, include providers from any imports.
11373 if (def.imports != null && !isDuplicate) {
11374 // Before processing defType's imports, add it to the set of parents. This way, if it ends
11375 // up deeply importing itself, this can be detected.
11376 ngDevMode && parents.push(defType);
11377 // Add it to the set of dedups. This way we can detect multiple imports of the same module
11378 dedupStack.push(defType);
11379 let importTypesWithProviders;
11380 try {
11381 deepForEach(def.imports, imported => {
11382 if (this.processInjectorType(imported, parents, dedupStack)) {
11383 if (importTypesWithProviders === undefined)
11384 importTypesWithProviders = [];
11385 // If the processed import is an injector type with providers, we store it in the
11386 // list of import types with providers, so that we can process those afterwards.
11387 importTypesWithProviders.push(imported);
11388 }
11389 });
11390 }
11391 finally {
11392 // Remove it from the parents set when finished.
11393 ngDevMode && parents.pop();
11394 }
11395 // Imports which are declared with providers (TypeWithProviders) need to be processed
11396 // after all imported modules are processed. This is similar to how View Engine
11397 // processes/merges module imports in the metadata resolver. See: FW-1349.
11398 if (importTypesWithProviders !== undefined) {
11399 for (let i = 0; i < importTypesWithProviders.length; i++) {
11400 const { ngModule, providers } = importTypesWithProviders[i];
11401 deepForEach(providers, provider => this.processProvider(provider, ngModule, providers || EMPTY_ARRAY));
11402 }
11403 }
11404 }
11405 // Track the InjectorType and add a provider for it. It's important that this is done after the
11406 // def's imports.
11407 this.injectorDefTypes.add(defType);
11408 const factory = getFactoryDef(defType) || (() => new defType());
11409 this.records.set(defType, makeRecord(factory, NOT_YET));
11410 // Next, include providers listed on the definition itself.
11411 const defProviders = def.providers;
11412 if (defProviders != null && !isDuplicate) {
11413 const injectorType = defOrWrappedDef;
11414 deepForEach(defProviders, provider => this.processProvider(provider, injectorType, defProviders));
11415 }
11416 return (ngModule !== undefined &&
11417 defOrWrappedDef.providers !== undefined);
11418 }
11419 /**
11420 * Process a `SingleProvider` and add it.
11421 */
11422 processProvider(provider, ngModuleType, providers) {
11423 // Determine the token from the provider. Either it's its own token, or has a {provide: ...}
11424 // property.
11425 provider = resolveForwardRef(provider);
11426 let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider && provider.provide);
11427 // Construct a `Record` for the provider.
11428 const record = providerToRecord(provider, ngModuleType, providers);
11429 if (!isTypeProvider(provider) && provider.multi === true) {
11430 // If the provider indicates that it's a multi-provider, process it specially.
11431 // First check whether it's been defined already.
11432 let multiRecord = this.records.get(token);
11433 if (multiRecord) {
11434 // It has. Throw a nice error if
11435 if (ngDevMode && multiRecord.multi === undefined) {
11436 throwMixedMultiProviderError();
11437 }
11438 }
11439 else {
11440 multiRecord = makeRecord(undefined, NOT_YET, true);
11441 multiRecord.factory = () => injectArgs(multiRecord.multi);
11442 this.records.set(token, multiRecord);
11443 }
11444 token = provider;
11445 multiRecord.multi.push(provider);
11446 }
11447 else {
11448 const existing = this.records.get(token);
11449 if (ngDevMode && existing && existing.multi !== undefined) {
11450 throwMixedMultiProviderError();
11451 }
11452 }
11453 this.records.set(token, record);
11454 }
11455 hydrate(token, record) {
11456 if (ngDevMode && record.value === CIRCULAR$1) {
11457 throwCyclicDependencyError(stringify(token));
11458 }
11459 else if (record.value === NOT_YET) {
11460 record.value = CIRCULAR$1;
11461 record.value = record.factory();
11462 }
11463 if (typeof record.value === 'object' && record.value && hasOnDestroy(record.value)) {
11464 this.onDestroy.add(record.value);
11465 }
11466 return record.value;
11467 }
11468 injectableDefInScope(def) {
11469 if (!def.providedIn) {
11470 return false;
11471 }
11472 const providedIn = resolveForwardRef(def.providedIn);
11473 if (typeof providedIn === 'string') {
11474 return providedIn === 'any' || (providedIn === this.scope);
11475 }
11476 else {
11477 return this.injectorDefTypes.has(providedIn);
11478 }
11479 }
11480}
11481function injectableDefOrInjectorDefFactory(token) {
11482 // Most tokens will have an injectable def directly on them, which specifies a factory directly.
11483 const injectableDef = getInjectableDef(token);
11484 const factory = injectableDef !== null ? injectableDef.factory : getFactoryDef(token);
11485 if (factory !== null) {
11486 return factory;
11487 }
11488 // InjectionTokens should have an injectable def (ɵprov) and thus should be handled above.
11489 // If it's missing that, it's an error.
11490 if (token instanceof InjectionToken) {
11491 throw new Error(`Token ${stringify(token)} is missing a ɵprov definition.`);
11492 }
11493 // Undecorated types can sometimes be created if they have no constructor arguments.
11494 if (token instanceof Function) {
11495 return getUndecoratedInjectableFactory(token);
11496 }
11497 // There was no way to resolve a factory for this token.
11498 throw new Error('unreachable');
11499}
11500function getUndecoratedInjectableFactory(token) {
11501 // If the token has parameters then it has dependencies that we cannot resolve implicitly.
11502 const paramLength = token.length;
11503 if (paramLength > 0) {
11504 const args = newArray(paramLength, '?');
11505 throw new Error(`Can't resolve all parameters for ${stringify(token)}: (${args.join(', ')}).`);
11506 }
11507 // The constructor function appears to have no parameters.
11508 // This might be because it inherits from a super-class. In which case, use an injectable
11509 // def from an ancestor if there is one.
11510 // Otherwise this really is a simple class with no dependencies, so return a factory that
11511 // just instantiates the zero-arg constructor.
11512 const inheritedInjectableDef = getInheritedInjectableDef(token);
11513 if (inheritedInjectableDef !== null) {
11514 return () => inheritedInjectableDef.factory(token);
11515 }
11516 else {
11517 return () => new token();
11518 }
11519}
11520function providerToRecord(provider, ngModuleType, providers) {
11521 if (isValueProvider(provider)) {
11522 return makeRecord(undefined, provider.useValue);
11523 }
11524 else {
11525 const factory = providerToFactory(provider, ngModuleType, providers);
11526 return makeRecord(factory, NOT_YET);
11527 }
11528}
11529/**
11530 * Converts a `SingleProvider` into a factory function.
11531 *
11532 * @param provider provider to convert to factory
11533 */
11534function providerToFactory(provider, ngModuleType, providers) {
11535 let factory = undefined;
11536 if (isTypeProvider(provider)) {
11537 const unwrappedProvider = resolveForwardRef(provider);
11538 return getFactoryDef(unwrappedProvider) || injectableDefOrInjectorDefFactory(unwrappedProvider);
11539 }
11540 else {
11541 if (isValueProvider(provider)) {
11542 factory = () => resolveForwardRef(provider.useValue);
11543 }
11544 else if (isFactoryProvider(provider)) {
11545 factory = () => provider.useFactory(...injectArgs(provider.deps || []));
11546 }
11547 else if (isExistingProvider(provider)) {
11548 factory = () => ɵɵinject(resolveForwardRef(provider.useExisting));
11549 }
11550 else {
11551 const classRef = resolveForwardRef(provider &&
11552 (provider.useClass || provider.provide));
11553 if (ngDevMode && !classRef) {
11554 throwInvalidProviderError(ngModuleType, providers, provider);
11555 }
11556 if (hasDeps(provider)) {
11557 factory = () => new (classRef)(...injectArgs(provider.deps));
11558 }
11559 else {
11560 return getFactoryDef(classRef) || injectableDefOrInjectorDefFactory(classRef);
11561 }
11562 }
11563 }
11564 return factory;
11565}
11566function makeRecord(factory, value, multi = false) {
11567 return {
11568 factory: factory,
11569 value: value,
11570 multi: multi ? [] : undefined,
11571 };
11572}
11573function isValueProvider(value) {
11574 return value !== null && typeof value == 'object' && USE_VALUE$2 in value;
11575}
11576function isExistingProvider(value) {
11577 return !!(value && value.useExisting);
11578}
11579function isFactoryProvider(value) {
11580 return !!(value && value.useFactory);
11581}
11582function isTypeProvider(value) {
11583 return typeof value === 'function';
11584}
11585function isClassProvider(value) {
11586 return !!value.useClass;
11587}
11588function hasDeps(value) {
11589 return !!value.deps;
11590}
11591function hasOnDestroy(value) {
11592 return value !== null && typeof value === 'object' &&
11593 typeof value.ngOnDestroy === 'function';
11594}
11595function couldBeInjectableType(value) {
11596 return (typeof value === 'function') ||
11597 (typeof value === 'object' && value instanceof InjectionToken);
11598}
11599
11600/**
11601 * @license
11602 * Copyright Google LLC All Rights Reserved.
11603 *
11604 * Use of this source code is governed by an MIT-style license that can be
11605 * found in the LICENSE file at https://angular.io/license
11606 */
11607function INJECTOR_IMPL__PRE_R3__(providers, parent, name) {
11608 return new StaticInjector(providers, parent, name);
11609}
11610function INJECTOR_IMPL__POST_R3__(providers, parent, name) {
11611 return createInjector$1({ name: name }, parent, providers, name);
11612}
11613const INJECTOR_IMPL = INJECTOR_IMPL__POST_R3__;
11614/**
11615 * Concrete injectors implement this interface. Injectors are configured
11616 * with [providers](guide/glossary#provider) that associate
11617 * dependencies of various types with [injection tokens](guide/glossary#di-token).
11618 *
11619 * @see ["DI Providers"](guide/dependency-injection-providers).
11620 * @see `StaticProvider`
11621 *
11622 * @usageNotes
11623 *
11624 * The following example creates a service injector instance.
11625 *
11626 * {@example core/di/ts/provider_spec.ts region='ConstructorProvider'}
11627 *
11628 * ### Usage example
11629 *
11630 * {@example core/di/ts/injector_spec.ts region='Injector'}
11631 *
11632 * `Injector` returns itself when given `Injector` as a token:
11633 *
11634 * {@example core/di/ts/injector_spec.ts region='injectInjector'}
11635 *
11636 * @publicApi
11637 */
11638class Injector {
11639 static create(options, parent) {
11640 if (Array.isArray(options)) {
11641 return INJECTOR_IMPL(options, parent, '');
11642 }
11643 else {
11644 return INJECTOR_IMPL(options.providers, options.parent, options.name || '');
11645 }
11646 }
11647}
11648Injector.THROW_IF_NOT_FOUND = THROW_IF_NOT_FOUND;
11649Injector.NULL = ( /* @__PURE__ */new NullInjector());
11650/** @nocollapse */
11651Injector.ɵprov = ɵɵdefineInjectable({
11652 token: Injector,
11653 providedIn: 'any',
11654 factory: () => ɵɵinject(INJECTOR),
11655});
11656/**
11657 * @internal
11658 * @nocollapse
11659 */
11660Injector.__NG_ELEMENT_ID__ = -1 /* Injector */;
11661const IDENT = function (value) {
11662 return value;
11663};
11664const EMPTY = [];
11665const CIRCULAR = IDENT;
11666const MULTI_PROVIDER_FN = function () {
11667 return Array.prototype.slice.call(arguments);
11668};
11669const NO_NEW_LINE = 'ɵ';
11670class StaticInjector {
11671 constructor(providers, parent = Injector.NULL, source = null) {
11672 this.parent = parent;
11673 this.source = source;
11674 const records = this._records = new Map();
11675 records.set(Injector, { token: Injector, fn: IDENT, deps: EMPTY, value: this, useNew: false });
11676 records.set(INJECTOR, { token: INJECTOR, fn: IDENT, deps: EMPTY, value: this, useNew: false });
11677 this.scope = recursivelyProcessProviders(records, providers);
11678 }
11679 get(token, notFoundValue, flags = InjectFlags.Default) {
11680 const records = this._records;
11681 let record = records.get(token);
11682 if (record === undefined) {
11683 // This means we have never seen this record, see if it is tree shakable provider.
11684 const injectableDef = getInjectableDef(token);
11685 if (injectableDef) {
11686 const providedIn = injectableDef && resolveForwardRef(injectableDef.providedIn);
11687 if (providedIn === 'any' || providedIn != null && providedIn === this.scope) {
11688 records.set(token, record = resolveProvider$1({ provide: token, useFactory: injectableDef.factory, deps: EMPTY }));
11689 }
11690 }
11691 if (record === undefined) {
11692 // Set record to null to make sure that we don't go through expensive lookup above again.
11693 records.set(token, null);
11694 }
11695 }
11696 let lastInjector = setCurrentInjector(this);
11697 try {
11698 return tryResolveToken(token, record, records, this.parent, notFoundValue, flags);
11699 }
11700 catch (e) {
11701 return catchInjectorError(e, token, 'StaticInjectorError', this.source);
11702 }
11703 finally {
11704 setCurrentInjector(lastInjector);
11705 }
11706 }
11707 toString() {
11708 const tokens = [], records = this._records;
11709 records.forEach((v, token) => tokens.push(stringify(token)));
11710 return `StaticInjector[${tokens.join(', ')}]`;
11711 }
11712}
11713function resolveProvider$1(provider) {
11714 const deps = computeDeps(provider);
11715 let fn = IDENT;
11716 let value = EMPTY;
11717 let useNew = false;
11718 let provide = resolveForwardRef(provider.provide);
11719 if (USE_VALUE$2 in provider) {
11720 // We need to use USE_VALUE in provider since provider.useValue could be defined as undefined.
11721 value = provider.useValue;
11722 }
11723 else if (provider.useFactory) {
11724 fn = provider.useFactory;
11725 }
11726 else if (provider.useExisting) {
11727 // Just use IDENT
11728 }
11729 else if (provider.useClass) {
11730 useNew = true;
11731 fn = resolveForwardRef(provider.useClass);
11732 }
11733 else if (typeof provide == 'function') {
11734 useNew = true;
11735 fn = provide;
11736 }
11737 else {
11738 throw staticError('StaticProvider does not have [useValue|useFactory|useExisting|useClass] or [provide] is not newable', provider);
11739 }
11740 return { deps, fn, useNew, value };
11741}
11742function multiProviderMixError(token) {
11743 return staticError('Cannot mix multi providers and regular providers', token);
11744}
11745function recursivelyProcessProviders(records, provider) {
11746 let scope = null;
11747 if (provider) {
11748 provider = resolveForwardRef(provider);
11749 if (Array.isArray(provider)) {
11750 // if we have an array recurse into the array
11751 for (let i = 0; i < provider.length; i++) {
11752 scope = recursivelyProcessProviders(records, provider[i]) || scope;
11753 }
11754 }
11755 else if (typeof provider === 'function') {
11756 // Functions were supported in ReflectiveInjector, but are not here. For safety give useful
11757 // error messages
11758 throw staticError('Function/Class not supported', provider);
11759 }
11760 else if (provider && typeof provider === 'object' && provider.provide) {
11761 // At this point we have what looks like a provider: {provide: ?, ....}
11762 let token = resolveForwardRef(provider.provide);
11763 const resolvedProvider = resolveProvider$1(provider);
11764 if (provider.multi === true) {
11765 // This is a multi provider.
11766 let multiProvider = records.get(token);
11767 if (multiProvider) {
11768 if (multiProvider.fn !== MULTI_PROVIDER_FN) {
11769 throw multiProviderMixError(token);
11770 }
11771 }
11772 else {
11773 // Create a placeholder factory which will look up the constituents of the multi provider.
11774 records.set(token, multiProvider = {
11775 token: provider.provide,
11776 deps: [],
11777 useNew: false,
11778 fn: MULTI_PROVIDER_FN,
11779 value: EMPTY
11780 });
11781 }
11782 // Treat the provider as the token.
11783 token = provider;
11784 multiProvider.deps.push({ token, options: 6 /* Default */ });
11785 }
11786 const record = records.get(token);
11787 if (record && record.fn == MULTI_PROVIDER_FN) {
11788 throw multiProviderMixError(token);
11789 }
11790 if (token === INJECTOR_SCOPE) {
11791 scope = resolvedProvider.value;
11792 }
11793 records.set(token, resolvedProvider);
11794 }
11795 else {
11796 throw staticError('Unexpected provider', provider);
11797 }
11798 }
11799 return scope;
11800}
11801function tryResolveToken(token, record, records, parent, notFoundValue, flags) {
11802 try {
11803 return resolveToken(token, record, records, parent, notFoundValue, flags);
11804 }
11805 catch (e) {
11806 // ensure that 'e' is of type Error.
11807 if (!(e instanceof Error)) {
11808 e = new Error(e);
11809 }
11810 const path = e[NG_TEMP_TOKEN_PATH] = e[NG_TEMP_TOKEN_PATH] || [];
11811 path.unshift(token);
11812 if (record && record.value == CIRCULAR) {
11813 // Reset the Circular flag.
11814 record.value = EMPTY;
11815 }
11816 throw e;
11817 }
11818}
11819function resolveToken(token, record, records, parent, notFoundValue, flags) {
11820 let value;
11821 if (record && !(flags & InjectFlags.SkipSelf)) {
11822 // If we don't have a record, this implies that we don't own the provider hence don't know how
11823 // to resolve it.
11824 value = record.value;
11825 if (value == CIRCULAR) {
11826 throw Error(NO_NEW_LINE + 'Circular dependency');
11827 }
11828 else if (value === EMPTY) {
11829 record.value = CIRCULAR;
11830 let obj = undefined;
11831 let useNew = record.useNew;
11832 let fn = record.fn;
11833 let depRecords = record.deps;
11834 let deps = EMPTY;
11835 if (depRecords.length) {
11836 deps = [];
11837 for (let i = 0; i < depRecords.length; i++) {
11838 const depRecord = depRecords[i];
11839 const options = depRecord.options;
11840 const childRecord = options & 2 /* CheckSelf */ ? records.get(depRecord.token) : undefined;
11841 deps.push(tryResolveToken(
11842 // Current Token to resolve
11843 depRecord.token,
11844 // A record which describes how to resolve the token.
11845 // If undefined, this means we don't have such a record
11846 childRecord,
11847 // Other records we know about.
11848 records,
11849 // If we don't know how to resolve dependency and we should not check parent for it,
11850 // than pass in Null injector.
11851 !childRecord && !(options & 4 /* CheckParent */) ? Injector.NULL : parent, options & 1 /* Optional */ ? null : Injector.THROW_IF_NOT_FOUND, InjectFlags.Default));
11852 }
11853 }
11854 record.value = value = useNew ? new fn(...deps) : fn.apply(obj, deps);
11855 }
11856 }
11857 else if (!(flags & InjectFlags.Self)) {
11858 value = parent.get(token, notFoundValue, InjectFlags.Default);
11859 }
11860 else if (!(flags & InjectFlags.Optional)) {
11861 value = Injector.NULL.get(token, notFoundValue);
11862 }
11863 else {
11864 value = Injector.NULL.get(token, typeof notFoundValue !== 'undefined' ? notFoundValue : null);
11865 }
11866 return value;
11867}
11868function computeDeps(provider) {
11869 let deps = EMPTY;
11870 const providerDeps = provider.deps;
11871 if (providerDeps && providerDeps.length) {
11872 deps = [];
11873 for (let i = 0; i < providerDeps.length; i++) {
11874 let options = 6 /* Default */;
11875 let token = resolveForwardRef(providerDeps[i]);
11876 if (Array.isArray(token)) {
11877 for (let j = 0, annotations = token; j < annotations.length; j++) {
11878 const annotation = annotations[j];
11879 if (annotation instanceof Optional || annotation == Optional) {
11880 options = options | 1 /* Optional */;
11881 }
11882 else if (annotation instanceof SkipSelf || annotation == SkipSelf) {
11883 options = options & ~2 /* CheckSelf */;
11884 }
11885 else if (annotation instanceof Self || annotation == Self) {
11886 options = options & ~4 /* CheckParent */;
11887 }
11888 else if (annotation instanceof Inject) {
11889 token = annotation.token;
11890 }
11891 else {
11892 token = resolveForwardRef(annotation);
11893 }
11894 }
11895 }
11896 deps.push({ token, options });
11897 }
11898 }
11899 else if (provider.useExisting) {
11900 const token = resolveForwardRef(provider.useExisting);
11901 deps = [{ token, options: 6 /* Default */ }];
11902 }
11903 else if (!providerDeps && !(USE_VALUE$2 in provider)) {
11904 // useValue & useExisting are the only ones which are exempt from deps all others need it.
11905 throw staticError('\'deps\' required', provider);
11906 }
11907 return deps;
11908}
11909function staticError(text, obj) {
11910 return new Error(formatError(text, obj, 'StaticInjectorError'));
11911}
11912
11913/**
11914 * @license
11915 * Copyright Google LLC All Rights Reserved.
11916 *
11917 * Use of this source code is governed by an MIT-style license that can be
11918 * found in the LICENSE file at https://angular.io/license
11919 */
11920/**
11921 * Retrieves the component instance associated with a given DOM element.
11922 *
11923 * @usageNotes
11924 * Given the following DOM structure:
11925 *
11926 * ```html
11927 * <app-root>
11928 * <div>
11929 * <child-comp></child-comp>
11930 * </div>
11931 * </app-root>
11932 * ```
11933 *
11934 * Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
11935 * associated with this DOM element.
11936 *
11937 * Calling the function on `<app-root>` will return the `MyApp` instance.
11938 *
11939 *
11940 * @param element DOM element from which the component should be retrieved.
11941 * @returns Component instance associated with the element or `null` if there
11942 * is no component associated with it.
11943 *
11944 * @publicApi
11945 * @globalApi ng
11946 */
11947function getComponent$1(element) {
11948 assertDomElement(element);
11949 const context = getLContext(element);
11950 if (context === null)
11951 return null;
11952 if (context.component === undefined) {
11953 context.component = getComponentAtNodeIndex(context.nodeIndex, context.lView);
11954 }
11955 return context.component;
11956}
11957/**
11958 * If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded
11959 * view that the element is part of. Otherwise retrieves the instance of the component whose view
11960 * owns the element (in this case, the result is the same as calling `getOwningComponent`).
11961 *
11962 * @param element Element for which to get the surrounding component instance.
11963 * @returns Instance of the component that is around the element or null if the element isn't
11964 * inside any component.
11965 *
11966 * @publicApi
11967 * @globalApi ng
11968 */
11969function getContext(element) {
11970 assertDomElement(element);
11971 const context = getLContext(element);
11972 return context === null ? null : context.lView[CONTEXT];
11973}
11974/**
11975 * Retrieves the component instance whose view contains the DOM element.
11976 *
11977 * For example, if `<child-comp>` is used in the template of `<app-comp>`
11978 * (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>`
11979 * would return `<app-comp>`.
11980 *
11981 * @param elementOrDir DOM element, component or directive instance
11982 * for which to retrieve the root components.
11983 * @returns Component instance whose view owns the DOM element or null if the element is not
11984 * part of a component view.
11985 *
11986 * @publicApi
11987 * @globalApi ng
11988 */
11989function getOwningComponent(elementOrDir) {
11990 const context = getLContext(elementOrDir);
11991 if (context === null)
11992 return null;
11993 let lView = context.lView;
11994 let parent;
11995 ngDevMode && assertLView(lView);
11996 while (lView[TVIEW].type === 2 /* Embedded */ && (parent = getLViewParent(lView))) {
11997 lView = parent;
11998 }
11999 return lView[FLAGS] & 512 /* IsRoot */ ? null : lView[CONTEXT];
12000}
12001/**
12002 * Retrieves all root components associated with a DOM element, directive or component instance.
12003 * Root components are those which have been bootstrapped by Angular.
12004 *
12005 * @param elementOrDir DOM element, component or directive instance
12006 * for which to retrieve the root components.
12007 * @returns Root components associated with the target object.
12008 *
12009 * @publicApi
12010 * @globalApi ng
12011 */
12012function getRootComponents(elementOrDir) {
12013 return [...getRootContext(elementOrDir).components];
12014}
12015/**
12016 * Retrieves an `Injector` associated with an element, component or directive instance.
12017 *
12018 * @param elementOrDir DOM element, component or directive instance for which to
12019 * retrieve the injector.
12020 * @returns Injector associated with the element, component or directive instance.
12021 *
12022 * @publicApi
12023 * @globalApi ng
12024 */
12025function getInjector(elementOrDir) {
12026 const context = getLContext(elementOrDir);
12027 if (context === null)
12028 return Injector.NULL;
12029 const tNode = context.lView[TVIEW].data[context.nodeIndex];
12030 return new NodeInjector(tNode, context.lView);
12031}
12032/**
12033 * Retrieve a set of injection tokens at a given DOM node.
12034 *
12035 * @param element Element for which the injection tokens should be retrieved.
12036 */
12037function getInjectionTokens(element) {
12038 const context = getLContext(element);
12039 if (context === null)
12040 return [];
12041 const lView = context.lView;
12042 const tView = lView[TVIEW];
12043 const tNode = tView.data[context.nodeIndex];
12044 const providerTokens = [];
12045 const startIndex = tNode.providerIndexes & 1048575 /* ProvidersStartIndexMask */;
12046 const endIndex = tNode.directiveEnd;
12047 for (let i = startIndex; i < endIndex; i++) {
12048 let value = tView.data[i];
12049 if (isDirectiveDefHack(value)) {
12050 // The fact that we sometimes store Type and sometimes DirectiveDef in this location is a
12051 // design flaw. We should always store same type so that we can be monomorphic. The issue
12052 // is that for Components/Directives we store the def instead the type. The correct behavior
12053 // is that we should always be storing injectable type in this location.
12054 value = value.type;
12055 }
12056 providerTokens.push(value);
12057 }
12058 return providerTokens;
12059}
12060/**
12061 * Retrieves directive instances associated with a given DOM node. Does not include
12062 * component instances.
12063 *
12064 * @usageNotes
12065 * Given the following DOM structure:
12066 *
12067 * ```html
12068 * <app-root>
12069 * <button my-button></button>
12070 * <my-comp></my-comp>
12071 * </app-root>
12072 * ```
12073 *
12074 * Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
12075 * directive that is associated with the DOM node.
12076 *
12077 * Calling `getDirectives` on `<my-comp>` will return an empty array.
12078 *
12079 * @param node DOM node for which to get the directives.
12080 * @returns Array of directives associated with the node.
12081 *
12082 * @publicApi
12083 * @globalApi ng
12084 */
12085function getDirectives(node) {
12086 // Skip text nodes because we can't have directives associated with them.
12087 if (node instanceof Text) {
12088 return [];
12089 }
12090 const context = getLContext(node);
12091 if (context === null) {
12092 return [];
12093 }
12094 const lView = context.lView;
12095 const tView = lView[TVIEW];
12096 const nodeIndex = context.nodeIndex;
12097 if (!(tView === null || tView === void 0 ? void 0 : tView.data[nodeIndex])) {
12098 return [];
12099 }
12100 if (context.directives === undefined) {
12101 context.directives = getDirectivesAtNodeIndex(nodeIndex, lView, false);
12102 }
12103 // The `directives` in this case are a named array called `LComponentView`. Clone the
12104 // result so we don't expose an internal data structure in the user's console.
12105 return context.directives === null ? [] : [...context.directives];
12106}
12107/**
12108 * Returns the debug (partial) metadata for a particular directive or component instance.
12109 * The function accepts an instance of a directive or component and returns the corresponding
12110 * metadata.
12111 *
12112 * @param directiveOrComponentInstance Instance of a directive or component
12113 * @returns metadata of the passed directive or component
12114 *
12115 * @publicApi
12116 * @globalApi ng
12117 */
12118function getDirectiveMetadata$1(directiveOrComponentInstance) {
12119 const { constructor } = directiveOrComponentInstance;
12120 if (!constructor) {
12121 throw new Error('Unable to find the instance constructor');
12122 }
12123 // In case a component inherits from a directive, we may have component and directive metadata
12124 // To ensure we don't get the metadata of the directive, we want to call `getComponentDef` first.
12125 const componentDef = getComponentDef(constructor);
12126 if (componentDef) {
12127 return {
12128 inputs: componentDef.inputs,
12129 outputs: componentDef.outputs,
12130 encapsulation: componentDef.encapsulation,
12131 changeDetection: componentDef.onPush ? ChangeDetectionStrategy.OnPush :
12132 ChangeDetectionStrategy.Default
12133 };
12134 }
12135 const directiveDef = getDirectiveDef(constructor);
12136 if (directiveDef) {
12137 return { inputs: directiveDef.inputs, outputs: directiveDef.outputs };
12138 }
12139 return null;
12140}
12141/**
12142 * Retrieve map of local references.
12143 *
12144 * The references are retrieved as a map of local reference name to element or directive instance.
12145 *
12146 * @param target DOM element, component or directive instance for which to retrieve
12147 * the local references.
12148 */
12149function getLocalRefs(target) {
12150 const context = getLContext(target);
12151 if (context === null)
12152 return {};
12153 if (context.localRefs === undefined) {
12154 context.localRefs = discoverLocalRefs(context.lView, context.nodeIndex);
12155 }
12156 return context.localRefs || {};
12157}
12158/**
12159 * Retrieves the host element of a component or directive instance.
12160 * The host element is the DOM element that matched the selector of the directive.
12161 *
12162 * @param componentOrDirective Component or directive instance for which the host
12163 * element should be retrieved.
12164 * @returns Host element of the target.
12165 *
12166 * @publicApi
12167 * @globalApi ng
12168 */
12169function getHostElement(componentOrDirective) {
12170 return getLContext(componentOrDirective).native;
12171}
12172/**
12173 * Retrieves the rendered text for a given component.
12174 *
12175 * This function retrieves the host element of a component and
12176 * and then returns the `textContent` for that element. This implies
12177 * that the text returned will include re-projected content of
12178 * the component as well.
12179 *
12180 * @param component The component to return the content text for.
12181 */
12182function getRenderedText(component) {
12183 const hostElement = getHostElement(component);
12184 return hostElement.textContent || '';
12185}
12186/**
12187 * Retrieves a list of event listeners associated with a DOM element. The list does include host
12188 * listeners, but it does not include event listeners defined outside of the Angular context
12189 * (e.g. through `addEventListener`).
12190 *
12191 * @usageNotes
12192 * Given the following DOM structure:
12193 *
12194 * ```html
12195 * <app-root>
12196 * <div (click)="doSomething()"></div>
12197 * </app-root>
12198 * ```
12199 *
12200 * Calling `getListeners` on `<div>` will return an object that looks as follows:
12201 *
12202 * ```ts
12203 * {
12204 * name: 'click',
12205 * element: <div>,
12206 * callback: () => doSomething(),
12207 * useCapture: false
12208 * }
12209 * ```
12210 *
12211 * @param element Element for which the DOM listeners should be retrieved.
12212 * @returns Array of event listeners on the DOM element.
12213 *
12214 * @publicApi
12215 * @globalApi ng
12216 */
12217function getListeners(element) {
12218 assertDomElement(element);
12219 const lContext = getLContext(element);
12220 if (lContext === null)
12221 return [];
12222 const lView = lContext.lView;
12223 const tView = lView[TVIEW];
12224 const lCleanup = lView[CLEANUP];
12225 const tCleanup = tView.cleanup;
12226 const listeners = [];
12227 if (tCleanup && lCleanup) {
12228 for (let i = 0; i < tCleanup.length;) {
12229 const firstParam = tCleanup[i++];
12230 const secondParam = tCleanup[i++];
12231 if (typeof firstParam === 'string') {
12232 const name = firstParam;
12233 const listenerElement = unwrapRNode(lView[secondParam]);
12234 const callback = lCleanup[tCleanup[i++]];
12235 const useCaptureOrIndx = tCleanup[i++];
12236 // if useCaptureOrIndx is boolean then report it as is.
12237 // if useCaptureOrIndx is positive number then it in unsubscribe method
12238 // if useCaptureOrIndx is negative number then it is a Subscription
12239 const type = (typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0) ? 'dom' : 'output';
12240 const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
12241 if (element == listenerElement) {
12242 listeners.push({ element, name, callback, useCapture, type });
12243 }
12244 }
12245 }
12246 }
12247 listeners.sort(sortListeners);
12248 return listeners;
12249}
12250function sortListeners(a, b) {
12251 if (a.name == b.name)
12252 return 0;
12253 return a.name < b.name ? -1 : 1;
12254}
12255/**
12256 * This function should not exist because it is megamorphic and only mostly correct.
12257 *
12258 * See call site for more info.
12259 */
12260function isDirectiveDefHack(obj) {
12261 return obj.type !== undefined && obj.template !== undefined && obj.declaredInputs !== undefined;
12262}
12263/**
12264 * Returns the attached `DebugNode` instance for an element in the DOM.
12265 *
12266 * @param element DOM element which is owned by an existing component's view.
12267 */
12268function getDebugNode$1(element) {
12269 if (ngDevMode && !(element instanceof Node)) {
12270 throw new Error('Expecting instance of DOM Element');
12271 }
12272 const lContext = getLContext(element);
12273 if (lContext === null) {
12274 return null;
12275 }
12276 const lView = lContext.lView;
12277 const nodeIndex = lContext.nodeIndex;
12278 if (nodeIndex !== -1) {
12279 const valueInLView = lView[nodeIndex];
12280 // this means that value in the lView is a component with its own
12281 // data. In this situation the TNode is not accessed at the same spot.
12282 const tNode = isLView(valueInLView) ? valueInLView[T_HOST] : getTNode(lView[TVIEW], nodeIndex);
12283 ngDevMode &&
12284 assertEqual(tNode.index, nodeIndex, 'Expecting that TNode at index is same as index');
12285 return buildDebugNode(tNode, lView);
12286 }
12287 return null;
12288}
12289/**
12290 * Retrieve the component `LView` from component/element.
12291 *
12292 * NOTE: `LView` is a private and should not be leaked outside.
12293 * Don't export this method to `ng.*` on window.
12294 *
12295 * @param target DOM element or component instance for which to retrieve the LView.
12296 */
12297function getComponentLView(target) {
12298 const lContext = getLContext(target);
12299 const nodeIndx = lContext.nodeIndex;
12300 const lView = lContext.lView;
12301 const componentLView = lView[nodeIndx];
12302 ngDevMode && assertLView(componentLView);
12303 return componentLView;
12304}
12305/** Asserts that a value is a DOM Element. */
12306function assertDomElement(value) {
12307 if (typeof Element !== 'undefined' && !(value instanceof Element)) {
12308 throw new Error('Expecting instance of DOM Element');
12309 }
12310}
12311
12312/**
12313 * @license
12314 * Copyright Google LLC All Rights Reserved.
12315 *
12316 * Use of this source code is governed by an MIT-style license that can be
12317 * found in the LICENSE file at https://angular.io/license
12318 */
12319/**
12320 * Marks a component for check (in case of OnPush components) and synchronously
12321 * performs change detection on the application this component belongs to.
12322 *
12323 * @param component Component to {@link ChangeDetectorRef#markForCheck mark for check}.
12324 *
12325 * @publicApi
12326 * @globalApi ng
12327 */
12328function applyChanges(component) {
12329 markDirty(component);
12330 getRootComponents(component).forEach(rootComponent => detectChanges(rootComponent));
12331}
12332
12333/**
12334 * @license
12335 * Copyright Google LLC All Rights Reserved.
12336 *
12337 * Use of this source code is governed by an MIT-style license that can be
12338 * found in the LICENSE file at https://angular.io/license
12339 */
12340/**
12341 * This file introduces series of globally accessible debug tools
12342 * to allow for the Angular debugging story to function.
12343 *
12344 * To see this in action run the following command:
12345 *
12346 * bazel run //packages/core/test/bundling/todo:devserver
12347 *
12348 * Then load `localhost:5432` and start using the console tools.
12349 */
12350/**
12351 * This value reflects the property on the window where the dev
12352 * tools are patched (window.ng).
12353 * */
12354const GLOBAL_PUBLISH_EXPANDO_KEY = 'ng';
12355let _published = false;
12356/**
12357 * Publishes a collection of default debug tools onto`window.ng`.
12358 *
12359 * These functions are available globally when Angular is in development
12360 * mode and are automatically stripped away from prod mode is on.
12361 */
12362function publishDefaultGlobalUtils$1() {
12363 if (!_published) {
12364 _published = true;
12365 /**
12366 * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
12367 * The contract of the function might be changed in any release and/or the function can be
12368 * removed completely.
12369 */
12370 publishGlobalUtil('ɵsetProfiler', setProfiler);
12371 publishGlobalUtil('getDirectiveMetadata', getDirectiveMetadata$1);
12372 publishGlobalUtil('getComponent', getComponent$1);
12373 publishGlobalUtil('getContext', getContext);
12374 publishGlobalUtil('getListeners', getListeners);
12375 publishGlobalUtil('getOwningComponent', getOwningComponent);
12376 publishGlobalUtil('getHostElement', getHostElement);
12377 publishGlobalUtil('getInjector', getInjector);
12378 publishGlobalUtil('getRootComponents', getRootComponents);
12379 publishGlobalUtil('getDirectives', getDirectives);
12380 publishGlobalUtil('applyChanges', applyChanges);
12381 }
12382}
12383/**
12384 * Publishes the given function to `window.ng` so that it can be
12385 * used from the browser console when an application is not in production.
12386 */
12387function publishGlobalUtil(name, fn) {
12388 if (typeof COMPILED === 'undefined' || !COMPILED) {
12389 // Note: we can't export `ng` when using closure enhanced optimization as:
12390 // - closure declares globals itself for minified names, which sometimes clobber our `ng` global
12391 // - we can't declare a closure extern as the namespace `ng` is already used within Google
12392 // for typings for AngularJS (via `goog.provide('ng....')`).
12393 const w = _global;
12394 ngDevMode && assertDefined(fn, 'function not defined');
12395 if (w) {
12396 let container = w[GLOBAL_PUBLISH_EXPANDO_KEY];
12397 if (!container) {
12398 container = w[GLOBAL_PUBLISH_EXPANDO_KEY] = {};
12399 }
12400 container[name] = fn;
12401 }
12402 }
12403}
12404
12405/**
12406 * @license
12407 * Copyright Google LLC All Rights Reserved.
12408 *
12409 * Use of this source code is governed by an MIT-style license that can be
12410 * found in the LICENSE file at https://angular.io/license
12411 */
12412// TODO: A hack to not pull in the NullInjector from @angular/core.
12413const NULL_INJECTOR = {
12414 get: (token, notFoundValue) => {
12415 throwProviderNotFoundError(token, 'NullInjector');
12416 }
12417};
12418/**
12419 * Bootstraps a Component into an existing host element and returns an instance
12420 * of the component.
12421 *
12422 * Use this function to bootstrap a component into the DOM tree. Each invocation
12423 * of this function will create a separate tree of components, injectors and
12424 * change detection cycles and lifetimes. To dynamically insert a new component
12425 * into an existing tree such that it shares the same injection, change detection
12426 * and object lifetime, use {@link ViewContainer#createComponent}.
12427 *
12428 * @param componentType Component to bootstrap
12429 * @param options Optional parameters which control bootstrapping
12430 */
12431function renderComponent(componentType /* Type as workaround for: Microsoft/TypeScript/issues/4881 */, opts = {}) {
12432 ngDevMode && publishDefaultGlobalUtils$1();
12433 ngDevMode && assertComponentType(componentType);
12434 const rendererFactory = opts.rendererFactory || domRendererFactory3;
12435 const sanitizer = opts.sanitizer || null;
12436 const componentDef = getComponentDef(componentType);
12437 if (componentDef.type != componentType)
12438 componentDef.type = componentType;
12439 // The first index of the first selector is the tag name.
12440 const componentTag = componentDef.selectors[0][0];
12441 const hostRenderer = rendererFactory.createRenderer(null, null);
12442 const hostRNode = locateHostElement(hostRenderer, opts.host || componentTag, componentDef.encapsulation);
12443 const rootFlags = componentDef.onPush ? 64 /* Dirty */ | 512 /* IsRoot */ :
12444 16 /* CheckAlways */ | 512 /* IsRoot */;
12445 const rootContext = createRootContext(opts.scheduler, opts.playerHandler);
12446 const renderer = rendererFactory.createRenderer(hostRNode, componentDef);
12447 const rootTView = createTView(0 /* Root */, null, null, 1, 0, null, null, null, null, null);
12448 const rootView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, renderer, null, opts.injector || null);
12449 enterView(rootView);
12450 let component;
12451 try {
12452 if (rendererFactory.begin)
12453 rendererFactory.begin();
12454 const componentView = createRootComponentView(hostRNode, componentDef, rootView, rendererFactory, renderer, sanitizer);
12455 component = createRootComponent(componentView, componentDef, rootView, rootContext, opts.hostFeatures || null);
12456 // create mode pass
12457 renderView(rootTView, rootView, null);
12458 // update mode pass
12459 refreshView(rootTView, rootView, null, null);
12460 }
12461 finally {
12462 leaveView();
12463 if (rendererFactory.end)
12464 rendererFactory.end();
12465 }
12466 return component;
12467}
12468/**
12469 * Creates the root component view and the root component node.
12470 *
12471 * @param rNode Render host element.
12472 * @param def ComponentDef
12473 * @param rootView The parent view where the host node is stored
12474 * @param rendererFactory Factory to be used for creating child renderers.
12475 * @param hostRenderer The current renderer
12476 * @param sanitizer The sanitizer, if provided
12477 *
12478 * @returns Component view created
12479 */
12480function createRootComponentView(rNode, def, rootView, rendererFactory, hostRenderer, sanitizer) {
12481 const tView = rootView[TVIEW];
12482 const index = HEADER_OFFSET;
12483 ngDevMode && assertIndexInRange(rootView, index);
12484 rootView[index] = rNode;
12485 // '#host' is added here as we don't know the real host DOM name (we don't want to read it) and at
12486 // the same time we want to communicate the debug `TNode` that this is a special `TNode`
12487 // representing a host element.
12488 const tNode = getOrCreateTNode(tView, index, 2 /* Element */, '#host', null);
12489 const mergedAttrs = tNode.mergedAttrs = def.hostAttrs;
12490 if (mergedAttrs !== null) {
12491 computeStaticStyling(tNode, mergedAttrs, true);
12492 if (rNode !== null) {
12493 setUpAttributes(hostRenderer, rNode, mergedAttrs);
12494 if (tNode.classes !== null) {
12495 writeDirectClass(hostRenderer, rNode, tNode.classes);
12496 }
12497 if (tNode.styles !== null) {
12498 writeDirectStyle(hostRenderer, rNode, tNode.styles);
12499 }
12500 }
12501 }
12502 const viewRenderer = rendererFactory.createRenderer(rNode, def);
12503 const componentView = createLView(rootView, getOrCreateTComponentView(def), null, def.onPush ? 64 /* Dirty */ : 16 /* CheckAlways */, rootView[index], tNode, rendererFactory, viewRenderer, sanitizer || null, null);
12504 if (tView.firstCreatePass) {
12505 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, rootView), tView, def.type);
12506 markAsComponentHost(tView, tNode);
12507 initTNodeFlags(tNode, rootView.length, 1);
12508 }
12509 addToViewTree(rootView, componentView);
12510 // Store component view at node index, with node as the HOST
12511 return rootView[index] = componentView;
12512}
12513/**
12514 * Creates a root component and sets it up with features and host bindings. Shared by
12515 * renderComponent() and ViewContainerRef.createComponent().
12516 */
12517function createRootComponent(componentView, componentDef, rootLView, rootContext, hostFeatures) {
12518 const tView = rootLView[TVIEW];
12519 // Create directive instance with factory() and store at next index in viewData
12520 const component = instantiateRootComponent(tView, rootLView, componentDef);
12521 rootContext.components.push(component);
12522 componentView[CONTEXT] = component;
12523 hostFeatures && hostFeatures.forEach((feature) => feature(component, componentDef));
12524 // We want to generate an empty QueryList for root content queries for backwards
12525 // compatibility with ViewEngine.
12526 if (componentDef.contentQueries) {
12527 const tNode = getCurrentTNode();
12528 ngDevMode && assertDefined(tNode, 'TNode expected');
12529 componentDef.contentQueries(1 /* Create */, component, tNode.directiveStart);
12530 }
12531 const rootTNode = getCurrentTNode();
12532 ngDevMode && assertDefined(rootTNode, 'tNode should have been already created');
12533 if (tView.firstCreatePass &&
12534 (componentDef.hostBindings !== null || componentDef.hostAttrs !== null)) {
12535 setSelectedIndex(rootTNode.index);
12536 const rootTView = rootLView[TVIEW];
12537 registerHostBindingOpCodes(rootTView, rootTNode, rootLView, rootTNode.directiveStart, rootTNode.directiveEnd, componentDef);
12538 invokeHostBindingsInCreationMode(componentDef, component);
12539 }
12540 return component;
12541}
12542function createRootContext(scheduler, playerHandler) {
12543 return {
12544 components: [],
12545 scheduler: scheduler || defaultScheduler,
12546 clean: CLEAN_PROMISE,
12547 playerHandler: playerHandler || null,
12548 flags: 0 /* Empty */
12549 };
12550}
12551/**
12552 * Used to enable lifecycle hooks on the root component.
12553 *
12554 * Include this feature when calling `renderComponent` if the root component
12555 * you are rendering has lifecycle hooks defined. Otherwise, the hooks won't
12556 * be called properly.
12557 *
12558 * Example:
12559 *
12560 * ```
12561 * renderComponent(AppComponent, {hostFeatures: [LifecycleHooksFeature]});
12562 * ```
12563 */
12564function LifecycleHooksFeature(component, def) {
12565 const lView = readPatchedLView(component);
12566 ngDevMode && assertDefined(lView, 'LView is required');
12567 const tView = lView[TVIEW];
12568 const tNode = getCurrentTNode();
12569 ngDevMode && assertDefined(tNode, 'TNode is required');
12570 registerPostOrderHooks(tView, tNode);
12571}
12572/**
12573 * Wait on component until it is rendered.
12574 *
12575 * This function returns a `Promise` which is resolved when the component's
12576 * change detection is executed. This is determined by finding the scheduler
12577 * associated with the `component`'s render tree and waiting until the scheduler
12578 * flushes. If nothing is scheduled, the function returns a resolved promise.
12579 *
12580 * Example:
12581 * ```
12582 * await whenRendered(myComponent);
12583 * ```
12584 *
12585 * @param component Component to wait upon
12586 * @returns Promise which resolves when the component is rendered.
12587 */
12588function whenRendered(component) {
12589 return getRootContext(component).clean;
12590}
12591
12592/**
12593 * @license
12594 * Copyright Google LLC All Rights Reserved.
12595 *
12596 * Use of this source code is governed by an MIT-style license that can be
12597 * found in the LICENSE file at https://angular.io/license
12598 */
12599function getSuperType(type) {
12600 return Object.getPrototypeOf(type.prototype).constructor;
12601}
12602/**
12603 * Merges the definition from a super class to a sub class.
12604 * @param definition The definition that is a SubClass of another directive of component
12605 *
12606 * @codeGenApi
12607 */
12608function ɵɵInheritDefinitionFeature(definition) {
12609 let superType = getSuperType(definition.type);
12610 let shouldInheritFields = true;
12611 const inheritanceChain = [definition];
12612 while (superType) {
12613 let superDef = undefined;
12614 if (isComponentDef(definition)) {
12615 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12616 superDef = superType.ɵcmp || superType.ɵdir;
12617 }
12618 else {
12619 if (superType.ɵcmp) {
12620 throw new Error('Directives cannot inherit Components');
12621 }
12622 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12623 superDef = superType.ɵdir;
12624 }
12625 if (superDef) {
12626 if (shouldInheritFields) {
12627 inheritanceChain.push(superDef);
12628 // Some fields in the definition may be empty, if there were no values to put in them that
12629 // would've justified object creation. Unwrap them if necessary.
12630 const writeableDef = definition;
12631 writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
12632 writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
12633 writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
12634 // Merge hostBindings
12635 const superHostBindings = superDef.hostBindings;
12636 superHostBindings && inheritHostBindings(definition, superHostBindings);
12637 // Merge queries
12638 const superViewQuery = superDef.viewQuery;
12639 const superContentQueries = superDef.contentQueries;
12640 superViewQuery && inheritViewQuery(definition, superViewQuery);
12641 superContentQueries && inheritContentQueries(definition, superContentQueries);
12642 // Merge inputs and outputs
12643 fillProperties(definition.inputs, superDef.inputs);
12644 fillProperties(definition.declaredInputs, superDef.declaredInputs);
12645 fillProperties(definition.outputs, superDef.outputs);
12646 // Merge animations metadata.
12647 // If `superDef` is a Component, the `data` field is present (defaults to an empty object).
12648 if (isComponentDef(superDef) && superDef.data.animation) {
12649 // If super def is a Component, the `definition` is also a Component, since Directives can
12650 // not inherit Components (we throw an error above and cannot reach this code).
12651 const defData = definition.data;
12652 defData.animation = (defData.animation || []).concat(superDef.data.animation);
12653 }
12654 }
12655 // Run parent features
12656 const features = superDef.features;
12657 if (features) {
12658 for (let i = 0; i < features.length; i++) {
12659 const feature = features[i];
12660 if (feature && feature.ngInherit) {
12661 feature(definition);
12662 }
12663 // If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
12664 // def already has all the necessary information inherited from its super class(es), so we
12665 // can stop merging fields from super classes. However we need to iterate through the
12666 // prototype chain to look for classes that might contain other "features" (like
12667 // NgOnChanges), which we should invoke for the original `definition`. We set the
12668 // `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
12669 // logic and only invoking functions from the "features" list.
12670 if (feature === ɵɵInheritDefinitionFeature) {
12671 shouldInheritFields = false;
12672 }
12673 }
12674 }
12675 }
12676 superType = Object.getPrototypeOf(superType);
12677 }
12678 mergeHostAttrsAcrossInheritance(inheritanceChain);
12679}
12680/**
12681 * Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.
12682 *
12683 * @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing
12684 * sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child
12685 * type.
12686 */
12687function mergeHostAttrsAcrossInheritance(inheritanceChain) {
12688 let hostVars = 0;
12689 let hostAttrs = null;
12690 // We process the inheritance order from the base to the leaves here.
12691 for (let i = inheritanceChain.length - 1; i >= 0; i--) {
12692 const def = inheritanceChain[i];
12693 // For each `hostVars`, we need to add the superclass amount.
12694 def.hostVars = (hostVars += def.hostVars);
12695 // for each `hostAttrs` we need to merge it with superclass.
12696 def.hostAttrs =
12697 mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
12698 }
12699}
12700function maybeUnwrapEmpty(value) {
12701 if (value === EMPTY_OBJ) {
12702 return {};
12703 }
12704 else if (value === EMPTY_ARRAY) {
12705 return [];
12706 }
12707 else {
12708 return value;
12709 }
12710}
12711function inheritViewQuery(definition, superViewQuery) {
12712 const prevViewQuery = definition.viewQuery;
12713 if (prevViewQuery) {
12714 definition.viewQuery = (rf, ctx) => {
12715 superViewQuery(rf, ctx);
12716 prevViewQuery(rf, ctx);
12717 };
12718 }
12719 else {
12720 definition.viewQuery = superViewQuery;
12721 }
12722}
12723function inheritContentQueries(definition, superContentQueries) {
12724 const prevContentQueries = definition.contentQueries;
12725 if (prevContentQueries) {
12726 definition.contentQueries = (rf, ctx, directiveIndex) => {
12727 superContentQueries(rf, ctx, directiveIndex);
12728 prevContentQueries(rf, ctx, directiveIndex);
12729 };
12730 }
12731 else {
12732 definition.contentQueries = superContentQueries;
12733 }
12734}
12735function inheritHostBindings(definition, superHostBindings) {
12736 const prevHostBindings = definition.hostBindings;
12737 if (prevHostBindings) {
12738 definition.hostBindings = (rf, ctx) => {
12739 superHostBindings(rf, ctx);
12740 prevHostBindings(rf, ctx);
12741 };
12742 }
12743 else {
12744 definition.hostBindings = superHostBindings;
12745 }
12746}
12747
12748/**
12749 * @license
12750 * Copyright Google LLC All Rights Reserved.
12751 *
12752 * Use of this source code is governed by an MIT-style license that can be
12753 * found in the LICENSE file at https://angular.io/license
12754 */
12755/**
12756 * Fields which exist on either directive or component definitions, and need to be copied from
12757 * parent to child classes by the `ɵɵCopyDefinitionFeature`.
12758 */
12759const COPY_DIRECTIVE_FIELDS = [
12760 // The child class should use the providers of its parent.
12761 'providersResolver',
12762 // Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
12763 // as inputs, outputs, and host binding functions.
12764];
12765/**
12766 * Fields which exist only on component definitions, and need to be copied from parent to child
12767 * classes by the `ɵɵCopyDefinitionFeature`.
12768 *
12769 * The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
12770 * since those should go in `COPY_DIRECTIVE_FIELDS` above.
12771 */
12772const COPY_COMPONENT_FIELDS = [
12773 // The child class should use the template function of its parent, including all template
12774 // semantics.
12775 'template',
12776 'decls',
12777 'consts',
12778 'vars',
12779 'onPush',
12780 'ngContentSelectors',
12781 // The child class should use the CSS styles of its parent, including all styling semantics.
12782 'styles',
12783 'encapsulation',
12784 // The child class should be checked by the runtime in the same way as its parent.
12785 'schemas',
12786];
12787/**
12788 * Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a
12789 * definition.
12790 *
12791 * This exists primarily to support ngcc migration of an existing View Engine pattern, where an
12792 * entire decorator is inherited from a parent to a child class. When ngcc detects this case, it
12793 * generates a skeleton definition on the child class, and applies this feature.
12794 *
12795 * The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition,
12796 * including things like the component template function.
12797 *
12798 * @param definition The definition of a child class which inherits from a parent class with its
12799 * own definition.
12800 *
12801 * @codeGenApi
12802 */
12803function ɵɵCopyDefinitionFeature(definition) {
12804 let superType = getSuperType(definition.type);
12805 let superDef = undefined;
12806 if (isComponentDef(definition)) {
12807 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12808 superDef = superType.ɵcmp;
12809 }
12810 else {
12811 // Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
12812 superDef = superType.ɵdir;
12813 }
12814 // Needed because `definition` fields are readonly.
12815 const defAny = definition;
12816 // Copy over any fields that apply to either directives or components.
12817 for (const field of COPY_DIRECTIVE_FIELDS) {
12818 defAny[field] = superDef[field];
12819 }
12820 if (isComponentDef(superDef)) {
12821 // Copy over any component-specific fields.
12822 for (const field of COPY_COMPONENT_FIELDS) {
12823 defAny[field] = superDef[field];
12824 }
12825 }
12826}
12827
12828/**
12829 * @license
12830 * Copyright Google LLC All Rights Reserved.
12831 *
12832 * Use of this source code is governed by an MIT-style license that can be
12833 * found in the LICENSE file at https://angular.io/license
12834 */
12835let _symbolIterator = null;
12836function getSymbolIterator() {
12837 if (!_symbolIterator) {
12838 const Symbol = _global['Symbol'];
12839 if (Symbol && Symbol.iterator) {
12840 _symbolIterator = Symbol.iterator;
12841 }
12842 else {
12843 // es6-shim specific logic
12844 const keys = Object.getOwnPropertyNames(Map.prototype);
12845 for (let i = 0; i < keys.length; ++i) {
12846 const key = keys[i];
12847 if (key !== 'entries' && key !== 'size' &&
12848 Map.prototype[key] === Map.prototype['entries']) {
12849 _symbolIterator = key;
12850 }
12851 }
12852 }
12853 }
12854 return _symbolIterator;
12855}
12856
12857/**
12858 * @license
12859 * Copyright Google LLC All Rights Reserved.
12860 *
12861 * Use of this source code is governed by an MIT-style license that can be
12862 * found in the LICENSE file at https://angular.io/license
12863 */
12864function devModeEqual(a, b) {
12865 const isListLikeIterableA = isListLikeIterable(a);
12866 const isListLikeIterableB = isListLikeIterable(b);
12867 if (isListLikeIterableA && isListLikeIterableB) {
12868 return areIterablesEqual(a, b, devModeEqual);
12869 }
12870 else {
12871 const isAObject = a && (typeof a === 'object' || typeof a === 'function');
12872 const isBObject = b && (typeof b === 'object' || typeof b === 'function');
12873 if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
12874 return true;
12875 }
12876 else {
12877 return Object.is(a, b);
12878 }
12879 }
12880}
12881function isListLikeIterable(obj) {
12882 if (!isJsObject(obj))
12883 return false;
12884 return Array.isArray(obj) ||
12885 (!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
12886 getSymbolIterator() in obj); // JS Iterable have a Symbol.iterator prop
12887}
12888function areIterablesEqual(a, b, comparator) {
12889 const iterator1 = a[getSymbolIterator()]();
12890 const iterator2 = b[getSymbolIterator()]();
12891 while (true) {
12892 const item1 = iterator1.next();
12893 const item2 = iterator2.next();
12894 if (item1.done && item2.done)
12895 return true;
12896 if (item1.done || item2.done)
12897 return false;
12898 if (!comparator(item1.value, item2.value))
12899 return false;
12900 }
12901}
12902function iterateListLike(obj, fn) {
12903 if (Array.isArray(obj)) {
12904 for (let i = 0; i < obj.length; i++) {
12905 fn(obj[i]);
12906 }
12907 }
12908 else {
12909 const iterator = obj[getSymbolIterator()]();
12910 let item;
12911 while (!((item = iterator.next()).done)) {
12912 fn(item.value);
12913 }
12914 }
12915}
12916function isJsObject(o) {
12917 return o !== null && (typeof o === 'function' || typeof o === 'object');
12918}
12919
12920/**
12921 * @license
12922 * Copyright Google LLC All Rights Reserved.
12923 *
12924 * Use of this source code is governed by an MIT-style license that can be
12925 * found in the LICENSE file at https://angular.io/license
12926 */
12927// TODO(misko): consider inlining
12928/** Updates binding and returns the value. */
12929function updateBinding(lView, bindingIndex, value) {
12930 return lView[bindingIndex] = value;
12931}
12932/** Gets the current binding value. */
12933function getBinding(lView, bindingIndex) {
12934 ngDevMode && assertIndexInRange(lView, bindingIndex);
12935 ngDevMode &&
12936 assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
12937 return lView[bindingIndex];
12938}
12939/**
12940 * Updates binding if changed, then returns whether it was updated.
12941 *
12942 * This function also checks the `CheckNoChangesMode` and throws if changes are made.
12943 * Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
12944 * behavior.
12945 *
12946 * @param lView current `LView`
12947 * @param bindingIndex The binding in the `LView` to check
12948 * @param value New value to check against `lView[bindingIndex]`
12949 * @returns `true` if the bindings has changed. (Throws if binding has changed during
12950 * `CheckNoChangesMode`)
12951 */
12952function bindingUpdated(lView, bindingIndex, value) {
12953 ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
12954 ngDevMode &&
12955 assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
12956 const oldValue = lView[bindingIndex];
12957 if (Object.is(oldValue, value)) {
12958 return false;
12959 }
12960 else {
12961 if (ngDevMode && isInCheckNoChangesMode()) {
12962 // View engine didn't report undefined values as changed on the first checkNoChanges pass
12963 // (before the change detection was run).
12964 const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
12965 if (!devModeEqual(oldValueToCompare, value)) {
12966 const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
12967 throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName);
12968 }
12969 // There was a change, but the `devModeEqual` decided that the change is exempt from an error.
12970 // For this reason we exit as if no change. The early exit is needed to prevent the changed
12971 // value to be written into `LView` (If we would write the new value that we would not see it
12972 // as change on next CD.)
12973 return false;
12974 }
12975 lView[bindingIndex] = value;
12976 return true;
12977 }
12978}
12979/** Updates 2 bindings if changed, then returns whether either was updated. */
12980function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
12981 const different = bindingUpdated(lView, bindingIndex, exp1);
12982 return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
12983}
12984/** Updates 3 bindings if changed, then returns whether any was updated. */
12985function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
12986 const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
12987 return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
12988}
12989/** Updates 4 bindings if changed, then returns whether any was updated. */
12990function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
12991 const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
12992 return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
12993}
12994
12995/**
12996 * @license
12997 * Copyright Google LLC All Rights Reserved.
12998 *
12999 * Use of this source code is governed by an MIT-style license that can be
13000 * found in the LICENSE file at https://angular.io/license
13001 */
13002/**
13003 * Updates the value of or removes a bound attribute on an Element.
13004 *
13005 * Used in the case of `[attr.title]="value"`
13006 *
13007 * @param name name The name of the attribute.
13008 * @param value value The attribute is removed when value is `null` or `undefined`.
13009 * Otherwise the attribute value is set to the stringified value.
13010 * @param sanitizer An optional function used to sanitize the value.
13011 * @param namespace Optional namespace to use when setting the attribute.
13012 *
13013 * @codeGenApi
13014 */
13015function ɵɵattribute(name, value, sanitizer, namespace) {
13016 const lView = getLView();
13017 const bindingIndex = nextBindingIndex();
13018 if (bindingUpdated(lView, bindingIndex, value)) {
13019 const tView = getTView();
13020 const tNode = getSelectedTNode();
13021 elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace);
13022 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, 'attr.' + name, bindingIndex);
13023 }
13024 return ɵɵattribute;
13025}
13026
13027/**
13028 * @license
13029 * Copyright Google LLC All Rights Reserved.
13030 *
13031 * Use of this source code is governed by an MIT-style license that can be
13032 * found in the LICENSE file at https://angular.io/license
13033 */
13034/**
13035 * Create interpolation bindings with a variable number of expressions.
13036 *
13037 * If there are 1 to 8 expressions `interpolation1()` to `interpolation8()` should be used instead.
13038 * Those are faster because there is no need to create an array of expressions and iterate over it.
13039 *
13040 * `values`:
13041 * - has static text at even indexes,
13042 * - has evaluated expressions at odd indexes.
13043 *
13044 * Returns the concatenated string when any of the arguments changes, `NO_CHANGE` otherwise.
13045 */
13046function interpolationV(lView, values) {
13047 ngDevMode && assertLessThan(2, values.length, 'should have at least 3 values');
13048 ngDevMode && assertEqual(values.length % 2, 1, 'should have an odd number of values');
13049 let isBindingUpdated = false;
13050 let bindingIndex = getBindingIndex();
13051 for (let i = 1; i < values.length; i += 2) {
13052 // Check if bindings (odd indexes) have changed
13053 isBindingUpdated = bindingUpdated(lView, bindingIndex++, values[i]) || isBindingUpdated;
13054 }
13055 setBindingIndex(bindingIndex);
13056 if (!isBindingUpdated) {
13057 return NO_CHANGE;
13058 }
13059 // Build the updated content
13060 let content = values[0];
13061 for (let i = 1; i < values.length; i += 2) {
13062 content += renderStringify(values[i]) + values[i + 1];
13063 }
13064 return content;
13065}
13066/**
13067 * Creates an interpolation binding with 1 expression.
13068 *
13069 * @param prefix static value used for concatenation only.
13070 * @param v0 value checked for change.
13071 * @param suffix static value used for concatenation only.
13072 */
13073function interpolation1(lView, prefix, v0, suffix) {
13074 const different = bindingUpdated(lView, nextBindingIndex(), v0);
13075 return different ? prefix + renderStringify(v0) + suffix : NO_CHANGE;
13076}
13077/**
13078 * Creates an interpolation binding with 2 expressions.
13079 */
13080function interpolation2(lView, prefix, v0, i0, v1, suffix) {
13081 const bindingIndex = getBindingIndex();
13082 const different = bindingUpdated2(lView, bindingIndex, v0, v1);
13083 incrementBindingIndex(2);
13084 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + suffix : NO_CHANGE;
13085}
13086/**
13087 * Creates an interpolation binding with 3 expressions.
13088 */
13089function interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix) {
13090 const bindingIndex = getBindingIndex();
13091 const different = bindingUpdated3(lView, bindingIndex, v0, v1, v2);
13092 incrementBindingIndex(3);
13093 return different ?
13094 prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + suffix :
13095 NO_CHANGE;
13096}
13097/**
13098 * Create an interpolation binding with 4 expressions.
13099 */
13100function interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
13101 const bindingIndex = getBindingIndex();
13102 const different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13103 incrementBindingIndex(4);
13104 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13105 renderStringify(v2) + i2 + renderStringify(v3) + suffix :
13106 NO_CHANGE;
13107}
13108/**
13109 * Creates an interpolation binding with 5 expressions.
13110 */
13111function interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
13112 const bindingIndex = getBindingIndex();
13113 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13114 different = bindingUpdated(lView, bindingIndex + 4, v4) || different;
13115 incrementBindingIndex(5);
13116 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13117 renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + suffix :
13118 NO_CHANGE;
13119}
13120/**
13121 * Creates an interpolation binding with 6 expressions.
13122 */
13123function interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
13124 const bindingIndex = getBindingIndex();
13125 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13126 different = bindingUpdated2(lView, bindingIndex + 4, v4, v5) || different;
13127 incrementBindingIndex(6);
13128 return different ?
13129 prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 + renderStringify(v2) + i2 +
13130 renderStringify(v3) + i3 + renderStringify(v4) + i4 + renderStringify(v5) + suffix :
13131 NO_CHANGE;
13132}
13133/**
13134 * Creates an interpolation binding with 7 expressions.
13135 */
13136function interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
13137 const bindingIndex = getBindingIndex();
13138 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13139 different = bindingUpdated3(lView, bindingIndex + 4, v4, v5, v6) || different;
13140 incrementBindingIndex(7);
13141 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13142 renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
13143 renderStringify(v5) + i5 + renderStringify(v6) + suffix :
13144 NO_CHANGE;
13145}
13146/**
13147 * Creates an interpolation binding with 8 expressions.
13148 */
13149function interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
13150 const bindingIndex = getBindingIndex();
13151 let different = bindingUpdated4(lView, bindingIndex, v0, v1, v2, v3);
13152 different = bindingUpdated4(lView, bindingIndex + 4, v4, v5, v6, v7) || different;
13153 incrementBindingIndex(8);
13154 return different ? prefix + renderStringify(v0) + i0 + renderStringify(v1) + i1 +
13155 renderStringify(v2) + i2 + renderStringify(v3) + i3 + renderStringify(v4) + i4 +
13156 renderStringify(v5) + i5 + renderStringify(v6) + i6 + renderStringify(v7) + suffix :
13157 NO_CHANGE;
13158}
13159
13160/**
13161 *
13162 * Update an interpolated attribute on an element with single bound value surrounded by text.
13163 *
13164 * Used when the value passed to a property has 1 interpolated value in it:
13165 *
13166 * ```html
13167 * <div attr.title="prefix{{v0}}suffix"></div>
13168 * ```
13169 *
13170 * Its compiled representation is::
13171 *
13172 * ```ts
13173 * ɵɵattributeInterpolate1('title', 'prefix', v0, 'suffix');
13174 * ```
13175 *
13176 * @param attrName The name of the attribute to update
13177 * @param prefix Static value used for concatenation only.
13178 * @param v0 Value checked for change.
13179 * @param suffix Static value used for concatenation only.
13180 * @param sanitizer An optional sanitizer function
13181 * @returns itself, so that it may be chained.
13182 * @codeGenApi
13183 */
13184function ɵɵattributeInterpolate1(attrName, prefix, v0, suffix, sanitizer, namespace) {
13185 const lView = getLView();
13186 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
13187 if (interpolatedValue !== NO_CHANGE) {
13188 const tNode = getSelectedTNode();
13189 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13190 ngDevMode &&
13191 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 1, prefix, suffix);
13192 }
13193 return ɵɵattributeInterpolate1;
13194}
13195/**
13196 *
13197 * Update an interpolated attribute on an element with 2 bound values surrounded by text.
13198 *
13199 * Used when the value passed to a property has 2 interpolated values in it:
13200 *
13201 * ```html
13202 * <div attr.title="prefix{{v0}}-{{v1}}suffix"></div>
13203 * ```
13204 *
13205 * Its compiled representation is::
13206 *
13207 * ```ts
13208 * ɵɵattributeInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
13209 * ```
13210 *
13211 * @param attrName The name of the attribute to update
13212 * @param prefix Static value used for concatenation only.
13213 * @param v0 Value checked for change.
13214 * @param i0 Static value used for concatenation only.
13215 * @param v1 Value checked for change.
13216 * @param suffix Static value used for concatenation only.
13217 * @param sanitizer An optional sanitizer function
13218 * @returns itself, so that it may be chained.
13219 * @codeGenApi
13220 */
13221function ɵɵattributeInterpolate2(attrName, prefix, v0, i0, v1, suffix, sanitizer, namespace) {
13222 const lView = getLView();
13223 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
13224 if (interpolatedValue !== NO_CHANGE) {
13225 const tNode = getSelectedTNode();
13226 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13227 ngDevMode &&
13228 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 2, prefix, i0, suffix);
13229 }
13230 return ɵɵattributeInterpolate2;
13231}
13232/**
13233 *
13234 * Update an interpolated attribute on an element with 3 bound values surrounded by text.
13235 *
13236 * Used when the value passed to a property has 3 interpolated values in it:
13237 *
13238 * ```html
13239 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
13240 * ```
13241 *
13242 * Its compiled representation is::
13243 *
13244 * ```ts
13245 * ɵɵattributeInterpolate3(
13246 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
13247 * ```
13248 *
13249 * @param attrName The name of the attribute to update
13250 * @param prefix Static value used for concatenation only.
13251 * @param v0 Value checked for change.
13252 * @param i0 Static value used for concatenation only.
13253 * @param v1 Value checked for change.
13254 * @param i1 Static value used for concatenation only.
13255 * @param v2 Value checked for change.
13256 * @param suffix Static value used for concatenation only.
13257 * @param sanitizer An optional sanitizer function
13258 * @returns itself, so that it may be chained.
13259 * @codeGenApi
13260 */
13261function ɵɵattributeInterpolate3(attrName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer, namespace) {
13262 const lView = getLView();
13263 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
13264 if (interpolatedValue !== NO_CHANGE) {
13265 const tNode = getSelectedTNode();
13266 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13267 ngDevMode &&
13268 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 3, prefix, i0, i1, suffix);
13269 }
13270 return ɵɵattributeInterpolate3;
13271}
13272/**
13273 *
13274 * Update an interpolated attribute on an element with 4 bound values surrounded by text.
13275 *
13276 * Used when the value passed to a property has 4 interpolated values in it:
13277 *
13278 * ```html
13279 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
13280 * ```
13281 *
13282 * Its compiled representation is::
13283 *
13284 * ```ts
13285 * ɵɵattributeInterpolate4(
13286 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
13287 * ```
13288 *
13289 * @param attrName The name of the attribute to update
13290 * @param prefix Static value used for concatenation only.
13291 * @param v0 Value checked for change.
13292 * @param i0 Static value used for concatenation only.
13293 * @param v1 Value checked for change.
13294 * @param i1 Static value used for concatenation only.
13295 * @param v2 Value checked for change.
13296 * @param i2 Static value used for concatenation only.
13297 * @param v3 Value checked for change.
13298 * @param suffix Static value used for concatenation only.
13299 * @param sanitizer An optional sanitizer function
13300 * @returns itself, so that it may be chained.
13301 * @codeGenApi
13302 */
13303function ɵɵattributeInterpolate4(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer, namespace) {
13304 const lView = getLView();
13305 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
13306 if (interpolatedValue !== NO_CHANGE) {
13307 const tNode = getSelectedTNode();
13308 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13309 ngDevMode &&
13310 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
13311 }
13312 return ɵɵattributeInterpolate4;
13313}
13314/**
13315 *
13316 * Update an interpolated attribute on an element with 5 bound values surrounded by text.
13317 *
13318 * Used when the value passed to a property has 5 interpolated values in it:
13319 *
13320 * ```html
13321 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
13322 * ```
13323 *
13324 * Its compiled representation is::
13325 *
13326 * ```ts
13327 * ɵɵattributeInterpolate5(
13328 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
13329 * ```
13330 *
13331 * @param attrName The name of the attribute to update
13332 * @param prefix Static value used for concatenation only.
13333 * @param v0 Value checked for change.
13334 * @param i0 Static value used for concatenation only.
13335 * @param v1 Value checked for change.
13336 * @param i1 Static value used for concatenation only.
13337 * @param v2 Value checked for change.
13338 * @param i2 Static value used for concatenation only.
13339 * @param v3 Value checked for change.
13340 * @param i3 Static value used for concatenation only.
13341 * @param v4 Value checked for change.
13342 * @param suffix Static value used for concatenation only.
13343 * @param sanitizer An optional sanitizer function
13344 * @returns itself, so that it may be chained.
13345 * @codeGenApi
13346 */
13347function ɵɵattributeInterpolate5(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer, namespace) {
13348 const lView = getLView();
13349 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
13350 if (interpolatedValue !== NO_CHANGE) {
13351 const tNode = getSelectedTNode();
13352 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13353 ngDevMode &&
13354 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
13355 }
13356 return ɵɵattributeInterpolate5;
13357}
13358/**
13359 *
13360 * Update an interpolated attribute on an element with 6 bound values surrounded by text.
13361 *
13362 * Used when the value passed to a property has 6 interpolated values in it:
13363 *
13364 * ```html
13365 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
13366 * ```
13367 *
13368 * Its compiled representation is::
13369 *
13370 * ```ts
13371 * ɵɵattributeInterpolate6(
13372 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
13373 * ```
13374 *
13375 * @param attrName The name of the attribute to update
13376 * @param prefix Static value used for concatenation only.
13377 * @param v0 Value checked for change.
13378 * @param i0 Static value used for concatenation only.
13379 * @param v1 Value checked for change.
13380 * @param i1 Static value used for concatenation only.
13381 * @param v2 Value checked for change.
13382 * @param i2 Static value used for concatenation only.
13383 * @param v3 Value checked for change.
13384 * @param i3 Static value used for concatenation only.
13385 * @param v4 Value checked for change.
13386 * @param i4 Static value used for concatenation only.
13387 * @param v5 Value checked for change.
13388 * @param suffix Static value used for concatenation only.
13389 * @param sanitizer An optional sanitizer function
13390 * @returns itself, so that it may be chained.
13391 * @codeGenApi
13392 */
13393function ɵɵattributeInterpolate6(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer, namespace) {
13394 const lView = getLView();
13395 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
13396 if (interpolatedValue !== NO_CHANGE) {
13397 const tNode = getSelectedTNode();
13398 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13399 ngDevMode &&
13400 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
13401 }
13402 return ɵɵattributeInterpolate6;
13403}
13404/**
13405 *
13406 * Update an interpolated attribute on an element with 7 bound values surrounded by text.
13407 *
13408 * Used when the value passed to a property has 7 interpolated values in it:
13409 *
13410 * ```html
13411 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
13412 * ```
13413 *
13414 * Its compiled representation is::
13415 *
13416 * ```ts
13417 * ɵɵattributeInterpolate7(
13418 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
13419 * ```
13420 *
13421 * @param attrName The name of the attribute to update
13422 * @param prefix Static value used for concatenation only.
13423 * @param v0 Value checked for change.
13424 * @param i0 Static value used for concatenation only.
13425 * @param v1 Value checked for change.
13426 * @param i1 Static value used for concatenation only.
13427 * @param v2 Value checked for change.
13428 * @param i2 Static value used for concatenation only.
13429 * @param v3 Value checked for change.
13430 * @param i3 Static value used for concatenation only.
13431 * @param v4 Value checked for change.
13432 * @param i4 Static value used for concatenation only.
13433 * @param v5 Value checked for change.
13434 * @param i5 Static value used for concatenation only.
13435 * @param v6 Value checked for change.
13436 * @param suffix Static value used for concatenation only.
13437 * @param sanitizer An optional sanitizer function
13438 * @returns itself, so that it may be chained.
13439 * @codeGenApi
13440 */
13441function ɵɵattributeInterpolate7(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer, namespace) {
13442 const lView = getLView();
13443 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
13444 if (interpolatedValue !== NO_CHANGE) {
13445 const tNode = getSelectedTNode();
13446 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13447 ngDevMode &&
13448 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix);
13449 }
13450 return ɵɵattributeInterpolate7;
13451}
13452/**
13453 *
13454 * Update an interpolated attribute on an element with 8 bound values surrounded by text.
13455 *
13456 * Used when the value passed to a property has 8 interpolated values in it:
13457 *
13458 * ```html
13459 * <div attr.title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
13460 * ```
13461 *
13462 * Its compiled representation is::
13463 *
13464 * ```ts
13465 * ɵɵattributeInterpolate8(
13466 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
13467 * ```
13468 *
13469 * @param attrName The name of the attribute to update
13470 * @param prefix Static value used for concatenation only.
13471 * @param v0 Value checked for change.
13472 * @param i0 Static value used for concatenation only.
13473 * @param v1 Value checked for change.
13474 * @param i1 Static value used for concatenation only.
13475 * @param v2 Value checked for change.
13476 * @param i2 Static value used for concatenation only.
13477 * @param v3 Value checked for change.
13478 * @param i3 Static value used for concatenation only.
13479 * @param v4 Value checked for change.
13480 * @param i4 Static value used for concatenation only.
13481 * @param v5 Value checked for change.
13482 * @param i5 Static value used for concatenation only.
13483 * @param v6 Value checked for change.
13484 * @param i6 Static value used for concatenation only.
13485 * @param v7 Value checked for change.
13486 * @param suffix Static value used for concatenation only.
13487 * @param sanitizer An optional sanitizer function
13488 * @returns itself, so that it may be chained.
13489 * @codeGenApi
13490 */
13491function ɵɵattributeInterpolate8(attrName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer, namespace) {
13492 const lView = getLView();
13493 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
13494 if (interpolatedValue !== NO_CHANGE) {
13495 const tNode = getSelectedTNode();
13496 elementAttributeInternal(tNode, lView, attrName, interpolatedValue, sanitizer, namespace);
13497 ngDevMode &&
13498 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
13499 }
13500 return ɵɵattributeInterpolate8;
13501}
13502/**
13503 * Update an interpolated attribute on an element with 9 or more bound values surrounded by text.
13504 *
13505 * Used when the number of interpolated values exceeds 8.
13506 *
13507 * ```html
13508 * <div
13509 * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
13510 * ```
13511 *
13512 * Its compiled representation is::
13513 *
13514 * ```ts
13515 * ɵɵattributeInterpolateV(
13516 * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
13517 * 'suffix']);
13518 * ```
13519 *
13520 * @param attrName The name of the attribute to update.
13521 * @param values The collection of values and the strings in-between those values, beginning with
13522 * a string prefix and ending with a string suffix.
13523 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
13524 * @param sanitizer An optional sanitizer function
13525 * @returns itself, so that it may be chained.
13526 * @codeGenApi
13527 */
13528function ɵɵattributeInterpolateV(attrName, values, sanitizer, namespace) {
13529 const lView = getLView();
13530 const interpolated = interpolationV(lView, values);
13531 if (interpolated !== NO_CHANGE) {
13532 const tNode = getSelectedTNode();
13533 elementAttributeInternal(tNode, lView, attrName, interpolated, sanitizer, namespace);
13534 if (ngDevMode) {
13535 const interpolationInBetween = [values[0]]; // prefix
13536 for (let i = 2; i < values.length; i += 2) {
13537 interpolationInBetween.push(values[i]);
13538 }
13539 storePropertyBindingMetadata(getTView().data, tNode, 'attr.' + attrName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
13540 }
13541 }
13542 return ɵɵattributeInterpolateV;
13543}
13544
13545/**
13546 * @license
13547 * Copyright Google LLC All Rights Reserved.
13548 *
13549 * Use of this source code is governed by an MIT-style license that can be
13550 * found in the LICENSE file at https://angular.io/license
13551 */
13552function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
13553 ngDevMode && assertFirstCreatePass(tView);
13554 ngDevMode && ngDevMode.firstCreatePass++;
13555 const tViewConsts = tView.consts;
13556 // TODO(pk): refactor getOrCreateTNode to have the "create" only version
13557 const tNode = getOrCreateTNode(tView, index, 4 /* Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
13558 resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
13559 registerPostOrderHooks(tView, tNode);
13560 const embeddedTView = tNode.tViews = createTView(2 /* Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
13561 if (tView.queries !== null) {
13562 tView.queries.template(tView, tNode);
13563 embeddedTView.queries = tView.queries.embeddedTView(tNode);
13564 }
13565 return tNode;
13566}
13567/**
13568 * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
13569 *
13570 * <ng-template #foo>
13571 * <div></div>
13572 * </ng-template>
13573 *
13574 * @param index The index of the container in the data array
13575 * @param templateFn Inline template
13576 * @param decls The number of nodes, local refs, and pipes for this template
13577 * @param vars The number of bindings for this template
13578 * @param tagName The name of the container element, if applicable
13579 * @param attrsIndex Index of template attributes in the `consts` array.
13580 * @param localRefs Index of the local references in the `consts` array.
13581 * @param localRefExtractor A function which extracts local-refs values from the template.
13582 * Defaults to the current element associated with the local-ref.
13583 *
13584 * @codeGenApi
13585 */
13586function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
13587 const lView = getLView();
13588 const tView = getTView();
13589 const adjustedIndex = index + HEADER_OFFSET;
13590 const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
13591 tView.data[adjustedIndex];
13592 setCurrentTNode(tNode, false);
13593 const comment = lView[RENDERER].createComment(ngDevMode ? 'container' : '');
13594 appendChild(tView, lView, comment, tNode);
13595 attachPatchData(comment, lView);
13596 addToViewTree(lView, lView[adjustedIndex] = createLContainer(comment, lView, comment, tNode));
13597 if (isDirectiveHost(tNode)) {
13598 createDirectivesInstances(tView, lView, tNode);
13599 }
13600 if (localRefsIndex != null) {
13601 saveResolvedLocalsInData(lView, tNode, localRefExtractor);
13602 }
13603}
13604
13605/**
13606 * @license
13607 * Copyright Google LLC All Rights Reserved.
13608 *
13609 * Use of this source code is governed by an MIT-style license that can be
13610 * found in the LICENSE file at https://angular.io/license
13611 */
13612/** Store a value in the `data` at a given `index`. */
13613function store(tView, lView, index, value) {
13614 // We don't store any static data for local variables, so the first time
13615 // we see the template, we should store as null to avoid a sparse array
13616 if (index >= tView.data.length) {
13617 tView.data[index] = null;
13618 tView.blueprint[index] = null;
13619 }
13620 lView[index] = value;
13621}
13622/**
13623 * Retrieves a local reference from the current contextViewData.
13624 *
13625 * If the reference to retrieve is in a parent view, this instruction is used in conjunction
13626 * with a nextContext() call, which walks up the tree and updates the contextViewData instance.
13627 *
13628 * @param index The index of the local ref in contextViewData.
13629 *
13630 * @codeGenApi
13631 */
13632function ɵɵreference(index) {
13633 const contextLView = getContextLView();
13634 return load(contextLView, HEADER_OFFSET + index);
13635}
13636
13637/**
13638 * @license
13639 * Copyright Google LLC All Rights Reserved.
13640 *
13641 * Use of this source code is governed by an MIT-style license that can be
13642 * found in the LICENSE file at https://angular.io/license
13643 */
13644/**
13645 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
13646 *
13647 * This should be kept up to date with the public exports of @angular/core.
13648 */
13649const angularCoreDiEnv = {
13650 'ɵɵdefineInjectable': ɵɵdefineInjectable,
13651 'ɵɵdefineInjector': ɵɵdefineInjector,
13652 'ɵɵinject': ɵɵinject,
13653 'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
13654 'resolveForwardRef': resolveForwardRef,
13655};
13656
13657/**
13658 * @license
13659 * Copyright Google LLC All Rights Reserved.
13660 *
13661 * Use of this source code is governed by an MIT-style license that can be
13662 * found in the LICENSE file at https://angular.io/license
13663 */
13664/**
13665 * Compile an Angular injectable according to its `Injectable` metadata, and patch the resulting
13666 * injectable def (`ɵprov`) onto the injectable type.
13667 */
13668function compileInjectable(type, meta) {
13669 let ngInjectableDef = null;
13670 let ngFactoryDef = null;
13671 // if NG_PROV_DEF is already defined on this class then don't overwrite it
13672 if (!type.hasOwnProperty(NG_PROV_DEF)) {
13673 Object.defineProperty(type, NG_PROV_DEF, {
13674 get: () => {
13675 if (ngInjectableDef === null) {
13676 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'injectable', type });
13677 ngInjectableDef = compiler.compileInjectable(angularCoreDiEnv, `ng:///${type.name}/ɵprov.js`, getInjectableMetadata(type, meta));
13678 }
13679 return ngInjectableDef;
13680 },
13681 });
13682 }
13683 // if NG_FACTORY_DEF is already defined on this class then don't overwrite it
13684 if (!type.hasOwnProperty(NG_FACTORY_DEF)) {
13685 Object.defineProperty(type, NG_FACTORY_DEF, {
13686 get: () => {
13687 if (ngFactoryDef === null) {
13688 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'injectable', type });
13689 ngFactoryDef = compiler.compileFactory(angularCoreDiEnv, `ng:///${type.name}/ɵfac.js`, {
13690 name: type.name,
13691 type,
13692 typeArgumentCount: 0,
13693 deps: reflectDependencies(type),
13694 target: compiler.FactoryTarget.Injectable
13695 });
13696 }
13697 return ngFactoryDef;
13698 },
13699 // Leave this configurable so that the factories from directives or pipes can take precedence.
13700 configurable: true
13701 });
13702 }
13703}
13704const USE_VALUE$1 = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
13705function isUseClassProvider(meta) {
13706 return meta.useClass !== undefined;
13707}
13708function isUseValueProvider(meta) {
13709 return USE_VALUE$1 in meta;
13710}
13711function isUseFactoryProvider(meta) {
13712 return meta.useFactory !== undefined;
13713}
13714function isUseExistingProvider(meta) {
13715 return meta.useExisting !== undefined;
13716}
13717function getInjectableMetadata(type, srcMeta) {
13718 // Allow the compilation of a class with a `@Injectable()` decorator without parameters
13719 const meta = srcMeta || { providedIn: null };
13720 const compilerMeta = {
13721 name: type.name,
13722 type: type,
13723 typeArgumentCount: 0,
13724 providedIn: meta.providedIn,
13725 };
13726 if ((isUseClassProvider(meta) || isUseFactoryProvider(meta)) && meta.deps !== undefined) {
13727 compilerMeta.deps = convertDependencies(meta.deps);
13728 }
13729 // Check to see if the user explicitly provided a `useXxxx` property.
13730 if (isUseClassProvider(meta)) {
13731 compilerMeta.useClass = meta.useClass;
13732 }
13733 else if (isUseValueProvider(meta)) {
13734 compilerMeta.useValue = meta.useValue;
13735 }
13736 else if (isUseFactoryProvider(meta)) {
13737 compilerMeta.useFactory = meta.useFactory;
13738 }
13739 else if (isUseExistingProvider(meta)) {
13740 compilerMeta.useExisting = meta.useExisting;
13741 }
13742 return compilerMeta;
13743}
13744
13745/**
13746 * @license
13747 * Copyright Google LLC All Rights Reserved.
13748 *
13749 * Use of this source code is governed by an MIT-style license that can be
13750 * found in the LICENSE file at https://angular.io/license
13751 */
13752const USE_VALUE = getClosureSafeProperty({ provide: String, useValue: getClosureSafeProperty });
13753function convertInjectableProviderToFactory(type, provider) {
13754 if (!provider) {
13755 const reflectionCapabilities = new ReflectionCapabilities();
13756 const deps = reflectionCapabilities.parameters(type);
13757 // TODO - convert to flags.
13758 return () => new type(...injectArgs(deps));
13759 }
13760 if (USE_VALUE in provider) {
13761 const valueProvider = provider;
13762 return () => valueProvider.useValue;
13763 }
13764 else if (provider.useExisting) {
13765 const existingProvider = provider;
13766 return () => ɵɵinject(resolveForwardRef(existingProvider.useExisting));
13767 }
13768 else if (provider.useFactory) {
13769 const factoryProvider = provider;
13770 return () => factoryProvider.useFactory(...injectArgs(factoryProvider.deps || EMPTY_ARRAY));
13771 }
13772 else if (provider.useClass) {
13773 const classProvider = provider;
13774 let deps = provider.deps;
13775 if (!deps) {
13776 const reflectionCapabilities = new ReflectionCapabilities();
13777 deps = reflectionCapabilities.parameters(type);
13778 }
13779 return () => new (resolveForwardRef(classProvider.useClass))(...injectArgs(deps));
13780 }
13781 else {
13782 let deps = provider.deps;
13783 if (!deps) {
13784 const reflectionCapabilities = new ReflectionCapabilities();
13785 deps = reflectionCapabilities.parameters(type);
13786 }
13787 return () => new type(...injectArgs(deps));
13788 }
13789}
13790
13791/**
13792 * Injectable decorator and metadata.
13793 *
13794 * @Annotation
13795 * @publicApi
13796 */
13797const Injectable = makeDecorator('Injectable', undefined, undefined, undefined, (type, meta) => SWITCH_COMPILE_INJECTABLE(type, meta));
13798/**
13799 * Supports @Injectable() in JIT mode for Render2.
13800 */
13801function render2CompileInjectable(injectableType, options) {
13802 if (options && options.providedIn !== undefined && !getInjectableDef(injectableType)) {
13803 injectableType.ɵprov = ɵɵdefineInjectable({
13804 token: injectableType,
13805 providedIn: options.providedIn,
13806 factory: convertInjectableProviderToFactory(injectableType, options),
13807 });
13808 }
13809}
13810const SWITCH_COMPILE_INJECTABLE__POST_R3__ = compileInjectable;
13811const SWITCH_COMPILE_INJECTABLE__PRE_R3__ = render2CompileInjectable;
13812const SWITCH_COMPILE_INJECTABLE = SWITCH_COMPILE_INJECTABLE__POST_R3__;
13813
13814/**
13815 * @license
13816 * Copyright Google LLC All Rights Reserved.
13817 *
13818 * Use of this source code is governed by an MIT-style license that can be
13819 * found in the LICENSE file at https://angular.io/license
13820 */
13821function findFirstClosedCycle(keys) {
13822 const res = [];
13823 for (let i = 0; i < keys.length; ++i) {
13824 if (res.indexOf(keys[i]) > -1) {
13825 res.push(keys[i]);
13826 return res;
13827 }
13828 res.push(keys[i]);
13829 }
13830 return res;
13831}
13832function constructResolvingPath(keys) {
13833 if (keys.length > 1) {
13834 const reversed = findFirstClosedCycle(keys.slice().reverse());
13835 const tokenStrs = reversed.map(k => stringify(k.token));
13836 return ' (' + tokenStrs.join(' -> ') + ')';
13837 }
13838 return '';
13839}
13840function injectionError(injector, key, constructResolvingMessage, originalError) {
13841 const keys = [key];
13842 const errMsg = constructResolvingMessage(keys);
13843 const error = (originalError ? wrappedError(errMsg, originalError) : Error(errMsg));
13844 error.addKey = addKey;
13845 error.keys = keys;
13846 error.injectors = [injector];
13847 error.constructResolvingMessage = constructResolvingMessage;
13848 error[ERROR_ORIGINAL_ERROR] = originalError;
13849 return error;
13850}
13851function addKey(injector, key) {
13852 this.injectors.push(injector);
13853 this.keys.push(key);
13854 // Note: This updated message won't be reflected in the `.stack` property
13855 this.message = this.constructResolvingMessage(this.keys);
13856}
13857/**
13858 * Thrown when trying to retrieve a dependency by key from {@link Injector}, but the
13859 * {@link Injector} does not have a {@link Provider} for the given key.
13860 *
13861 * @usageNotes
13862 * ### Example
13863 *
13864 * ```typescript
13865 * class A {
13866 * constructor(b:B) {}
13867 * }
13868 *
13869 * expect(() => Injector.resolveAndCreate([A])).toThrowError();
13870 * ```
13871 */
13872function noProviderError(injector, key) {
13873 return injectionError(injector, key, function (keys) {
13874 const first = stringify(keys[0].token);
13875 return `No provider for ${first}!${constructResolvingPath(keys)}`;
13876 });
13877}
13878/**
13879 * Thrown when dependencies form a cycle.
13880 *
13881 * @usageNotes
13882 * ### Example
13883 *
13884 * ```typescript
13885 * var injector = Injector.resolveAndCreate([
13886 * {provide: "one", useFactory: (two) => "two", deps: [[new Inject("two")]]},
13887 * {provide: "two", useFactory: (one) => "one", deps: [[new Inject("one")]]}
13888 * ]);
13889 *
13890 * expect(() => injector.get("one")).toThrowError();
13891 * ```
13892 *
13893 * Retrieving `A` or `B` throws a `CyclicDependencyError` as the graph above cannot be constructed.
13894 */
13895function cyclicDependencyError(injector, key) {
13896 return injectionError(injector, key, function (keys) {
13897 return `Cannot instantiate cyclic dependency!${constructResolvingPath(keys)}`;
13898 });
13899}
13900/**
13901 * Thrown when a constructing type returns with an Error.
13902 *
13903 * The `InstantiationError` class contains the original error plus the dependency graph which caused
13904 * this object to be instantiated.
13905 *
13906 * @usageNotes
13907 * ### Example
13908 *
13909 * ```typescript
13910 * class A {
13911 * constructor() {
13912 * throw new Error('message');
13913 * }
13914 * }
13915 *
13916 * var injector = Injector.resolveAndCreate([A]);
13917
13918 * try {
13919 * injector.get(A);
13920 * } catch (e) {
13921 * expect(e instanceof InstantiationError).toBe(true);
13922 * expect(e.originalException.message).toEqual("message");
13923 * expect(e.originalStack).toBeDefined();
13924 * }
13925 * ```
13926 */
13927function instantiationError(injector, originalException, originalStack, key) {
13928 return injectionError(injector, key, function (keys) {
13929 const first = stringify(keys[0].token);
13930 return `${originalException.message}: Error during instantiation of ${first}!${constructResolvingPath(keys)}.`;
13931 }, originalException);
13932}
13933/**
13934 * Thrown when an object other then {@link Provider} (or `Type`) is passed to {@link Injector}
13935 * creation.
13936 *
13937 * @usageNotes
13938 * ### Example
13939 *
13940 * ```typescript
13941 * expect(() => Injector.resolveAndCreate(["not a type"])).toThrowError();
13942 * ```
13943 */
13944function invalidProviderError(provider) {
13945 return Error(`Invalid provider - only instances of Provider and Type are allowed, got: ${provider}`);
13946}
13947/**
13948 * Thrown when the class has no annotation information.
13949 *
13950 * Lack of annotation information prevents the {@link Injector} from determining which dependencies
13951 * need to be injected into the constructor.
13952 *
13953 * @usageNotes
13954 * ### Example
13955 *
13956 * ```typescript
13957 * class A {
13958 * constructor(b) {}
13959 * }
13960 *
13961 * expect(() => Injector.resolveAndCreate([A])).toThrowError();
13962 * ```
13963 *
13964 * This error is also thrown when the class not marked with {@link Injectable} has parameter types.
13965 *
13966 * ```typescript
13967 * class B {}
13968 *
13969 * class A {
13970 * constructor(b:B) {} // no information about the parameter types of A is available at runtime.
13971 * }
13972 *
13973 * expect(() => Injector.resolveAndCreate([A,B])).toThrowError();
13974 * ```
13975 *
13976 */
13977function noAnnotationError(typeOrFunc, params) {
13978 const signature = [];
13979 for (let i = 0, ii = params.length; i < ii; i++) {
13980 const parameter = params[i];
13981 if (!parameter || parameter.length == 0) {
13982 signature.push('?');
13983 }
13984 else {
13985 signature.push(parameter.map(stringify).join(' '));
13986 }
13987 }
13988 return Error('Cannot resolve all parameters for \'' + stringify(typeOrFunc) + '\'(' +
13989 signature.join(', ') + '). ' +
13990 'Make sure that all the parameters are decorated with Inject or have valid type annotations and that \'' +
13991 stringify(typeOrFunc) + '\' is decorated with Injectable.');
13992}
13993/**
13994 * Thrown when getting an object by index.
13995 *
13996 * @usageNotes
13997 * ### Example
13998 *
13999 * ```typescript
14000 * class A {}
14001 *
14002 * var injector = Injector.resolveAndCreate([A]);
14003 *
14004 * expect(() => injector.getAt(100)).toThrowError();
14005 * ```
14006 *
14007 */
14008function outOfBoundsError(index) {
14009 return Error(`Index ${index} is out-of-bounds.`);
14010}
14011// TODO: add a working example after alpha38 is released
14012/**
14013 * Thrown when a multi provider and a regular provider are bound to the same token.
14014 *
14015 * @usageNotes
14016 * ### Example
14017 *
14018 * ```typescript
14019 * expect(() => Injector.resolveAndCreate([
14020 * { provide: "Strings", useValue: "string1", multi: true},
14021 * { provide: "Strings", useValue: "string2", multi: false}
14022 * ])).toThrowError();
14023 * ```
14024 */
14025function mixingMultiProvidersWithRegularProvidersError(provider1, provider2) {
14026 return Error(`Cannot mix multi providers and regular providers, got: ${provider1} ${provider2}`);
14027}
14028
14029/**
14030 * @license
14031 * Copyright Google LLC All Rights Reserved.
14032 *
14033 * Use of this source code is governed by an MIT-style license that can be
14034 * found in the LICENSE file at https://angular.io/license
14035 */
14036/**
14037 * A unique object used for retrieving items from the {@link ReflectiveInjector}.
14038 *
14039 * Keys have:
14040 * - a system-wide unique `id`.
14041 * - a `token`.
14042 *
14043 * `Key` is used internally by {@link ReflectiveInjector} because its system-wide unique `id` allows
14044 * the
14045 * injector to store created objects in a more efficient way.
14046 *
14047 * `Key` should not be created directly. {@link ReflectiveInjector} creates keys automatically when
14048 * resolving
14049 * providers.
14050 *
14051 * @deprecated No replacement
14052 * @publicApi
14053 */
14054class ReflectiveKey {
14055 /**
14056 * Private
14057 */
14058 constructor(token, id) {
14059 this.token = token;
14060 this.id = id;
14061 if (!token) {
14062 throw new Error('Token must be defined!');
14063 }
14064 this.displayName = stringify(this.token);
14065 }
14066 /**
14067 * Retrieves a `Key` for a token.
14068 */
14069 static get(token) {
14070 return _globalKeyRegistry.get(resolveForwardRef(token));
14071 }
14072 /**
14073 * @returns the number of keys registered in the system.
14074 */
14075 static get numberOfKeys() {
14076 return _globalKeyRegistry.numberOfKeys;
14077 }
14078}
14079class KeyRegistry {
14080 constructor() {
14081 this._allKeys = new Map();
14082 }
14083 get(token) {
14084 if (token instanceof ReflectiveKey)
14085 return token;
14086 if (this._allKeys.has(token)) {
14087 return this._allKeys.get(token);
14088 }
14089 const newKey = new ReflectiveKey(token, ReflectiveKey.numberOfKeys);
14090 this._allKeys.set(token, newKey);
14091 return newKey;
14092 }
14093 get numberOfKeys() {
14094 return this._allKeys.size;
14095 }
14096}
14097const _globalKeyRegistry = new KeyRegistry();
14098
14099/**
14100 * @license
14101 * Copyright Google LLC All Rights Reserved.
14102 *
14103 * Use of this source code is governed by an MIT-style license that can be
14104 * found in the LICENSE file at https://angular.io/license
14105 */
14106/**
14107 * Provides access to reflection data about symbols. Used internally by Angular
14108 * to power dependency injection and compilation.
14109 */
14110class Reflector {
14111 constructor(reflectionCapabilities) {
14112 this.reflectionCapabilities = reflectionCapabilities;
14113 }
14114 updateCapabilities(caps) {
14115 this.reflectionCapabilities = caps;
14116 }
14117 factory(type) {
14118 return this.reflectionCapabilities.factory(type);
14119 }
14120 parameters(typeOrFunc) {
14121 return this.reflectionCapabilities.parameters(typeOrFunc);
14122 }
14123 annotations(typeOrFunc) {
14124 return this.reflectionCapabilities.annotations(typeOrFunc);
14125 }
14126 propMetadata(typeOrFunc) {
14127 return this.reflectionCapabilities.propMetadata(typeOrFunc);
14128 }
14129 hasLifecycleHook(type, lcProperty) {
14130 return this.reflectionCapabilities.hasLifecycleHook(type, lcProperty);
14131 }
14132 getter(name) {
14133 return this.reflectionCapabilities.getter(name);
14134 }
14135 setter(name) {
14136 return this.reflectionCapabilities.setter(name);
14137 }
14138 method(name) {
14139 return this.reflectionCapabilities.method(name);
14140 }
14141 importUri(type) {
14142 return this.reflectionCapabilities.importUri(type);
14143 }
14144 resourceUri(type) {
14145 return this.reflectionCapabilities.resourceUri(type);
14146 }
14147 resolveIdentifier(name, moduleUrl, members, runtime) {
14148 return this.reflectionCapabilities.resolveIdentifier(name, moduleUrl, members, runtime);
14149 }
14150 resolveEnum(identifier, name) {
14151 return this.reflectionCapabilities.resolveEnum(identifier, name);
14152 }
14153}
14154
14155/**
14156 * @license
14157 * Copyright Google LLC All Rights Reserved.
14158 *
14159 * Use of this source code is governed by an MIT-style license that can be
14160 * found in the LICENSE file at https://angular.io/license
14161 */
14162/**
14163 * The {@link Reflector} used internally in Angular to access metadata
14164 * about symbols.
14165 */
14166const reflector = new Reflector(new ReflectionCapabilities());
14167
14168/**
14169 * @license
14170 * Copyright Google LLC All Rights Reserved.
14171 *
14172 * Use of this source code is governed by an MIT-style license that can be
14173 * found in the LICENSE file at https://angular.io/license
14174 */
14175/**
14176 * `Dependency` is used by the framework to extend DI.
14177 * This is internal to Angular and should not be used directly.
14178 */
14179class ReflectiveDependency {
14180 constructor(key, optional, visibility) {
14181 this.key = key;
14182 this.optional = optional;
14183 this.visibility = visibility;
14184 }
14185 static fromKey(key) {
14186 return new ReflectiveDependency(key, false, null);
14187 }
14188}
14189const _EMPTY_LIST = [];
14190class ResolvedReflectiveProvider_ {
14191 constructor(key, resolvedFactories, multiProvider) {
14192 this.key = key;
14193 this.resolvedFactories = resolvedFactories;
14194 this.multiProvider = multiProvider;
14195 this.resolvedFactory = this.resolvedFactories[0];
14196 }
14197}
14198/**
14199 * An internal resolved representation of a factory function created by resolving `Provider`.
14200 * @publicApi
14201 */
14202class ResolvedReflectiveFactory {
14203 constructor(
14204 /**
14205 * Factory function which can return an instance of an object represented by a key.
14206 */
14207 factory,
14208 /**
14209 * Arguments (dependencies) to the `factory` function.
14210 */
14211 dependencies) {
14212 this.factory = factory;
14213 this.dependencies = dependencies;
14214 }
14215}
14216/**
14217 * Resolve a single provider.
14218 */
14219function resolveReflectiveFactory(provider) {
14220 let factoryFn;
14221 let resolvedDeps;
14222 if (provider.useClass) {
14223 const useClass = resolveForwardRef(provider.useClass);
14224 factoryFn = reflector.factory(useClass);
14225 resolvedDeps = _dependenciesFor(useClass);
14226 }
14227 else if (provider.useExisting) {
14228 factoryFn = (aliasInstance) => aliasInstance;
14229 resolvedDeps = [ReflectiveDependency.fromKey(ReflectiveKey.get(provider.useExisting))];
14230 }
14231 else if (provider.useFactory) {
14232 factoryFn = provider.useFactory;
14233 resolvedDeps = constructDependencies(provider.useFactory, provider.deps);
14234 }
14235 else {
14236 factoryFn = () => provider.useValue;
14237 resolvedDeps = _EMPTY_LIST;
14238 }
14239 return new ResolvedReflectiveFactory(factoryFn, resolvedDeps);
14240}
14241/**
14242 * Converts the `Provider` into `ResolvedProvider`.
14243 *
14244 * `Injector` internally only uses `ResolvedProvider`, `Provider` contains convenience provider
14245 * syntax.
14246 */
14247function resolveReflectiveProvider(provider) {
14248 return new ResolvedReflectiveProvider_(ReflectiveKey.get(provider.provide), [resolveReflectiveFactory(provider)], provider.multi || false);
14249}
14250/**
14251 * Resolve a list of Providers.
14252 */
14253function resolveReflectiveProviders(providers) {
14254 const normalized = _normalizeProviders(providers, []);
14255 const resolved = normalized.map(resolveReflectiveProvider);
14256 const resolvedProviderMap = mergeResolvedReflectiveProviders(resolved, new Map());
14257 return Array.from(resolvedProviderMap.values());
14258}
14259/**
14260 * Merges a list of ResolvedProviders into a list where each key is contained exactly once and
14261 * multi providers have been merged.
14262 */
14263function mergeResolvedReflectiveProviders(providers, normalizedProvidersMap) {
14264 for (let i = 0; i < providers.length; i++) {
14265 const provider = providers[i];
14266 const existing = normalizedProvidersMap.get(provider.key.id);
14267 if (existing) {
14268 if (provider.multiProvider !== existing.multiProvider) {
14269 throw mixingMultiProvidersWithRegularProvidersError(existing, provider);
14270 }
14271 if (provider.multiProvider) {
14272 for (let j = 0; j < provider.resolvedFactories.length; j++) {
14273 existing.resolvedFactories.push(provider.resolvedFactories[j]);
14274 }
14275 }
14276 else {
14277 normalizedProvidersMap.set(provider.key.id, provider);
14278 }
14279 }
14280 else {
14281 let resolvedProvider;
14282 if (provider.multiProvider) {
14283 resolvedProvider = new ResolvedReflectiveProvider_(provider.key, provider.resolvedFactories.slice(), provider.multiProvider);
14284 }
14285 else {
14286 resolvedProvider = provider;
14287 }
14288 normalizedProvidersMap.set(provider.key.id, resolvedProvider);
14289 }
14290 }
14291 return normalizedProvidersMap;
14292}
14293function _normalizeProviders(providers, res) {
14294 providers.forEach(b => {
14295 if (b instanceof Type) {
14296 res.push({ provide: b, useClass: b });
14297 }
14298 else if (b && typeof b == 'object' && b.provide !== undefined) {
14299 res.push(b);
14300 }
14301 else if (Array.isArray(b)) {
14302 _normalizeProviders(b, res);
14303 }
14304 else {
14305 throw invalidProviderError(b);
14306 }
14307 });
14308 return res;
14309}
14310function constructDependencies(typeOrFunc, dependencies) {
14311 if (!dependencies) {
14312 return _dependenciesFor(typeOrFunc);
14313 }
14314 else {
14315 const params = dependencies.map(t => [t]);
14316 return dependencies.map(t => _extractToken(typeOrFunc, t, params));
14317 }
14318}
14319function _dependenciesFor(typeOrFunc) {
14320 const params = reflector.parameters(typeOrFunc);
14321 if (!params)
14322 return [];
14323 if (params.some(p => p == null)) {
14324 throw noAnnotationError(typeOrFunc, params);
14325 }
14326 return params.map(p => _extractToken(typeOrFunc, p, params));
14327}
14328function _extractToken(typeOrFunc, metadata, params) {
14329 let token = null;
14330 let optional = false;
14331 if (!Array.isArray(metadata)) {
14332 if (metadata instanceof Inject) {
14333 return _createDependency(metadata.token, optional, null);
14334 }
14335 else {
14336 return _createDependency(metadata, optional, null);
14337 }
14338 }
14339 let visibility = null;
14340 for (let i = 0; i < metadata.length; ++i) {
14341 const paramMetadata = metadata[i];
14342 if (paramMetadata instanceof Type) {
14343 token = paramMetadata;
14344 }
14345 else if (paramMetadata instanceof Inject) {
14346 token = paramMetadata.token;
14347 }
14348 else if (paramMetadata instanceof Optional) {
14349 optional = true;
14350 }
14351 else if (paramMetadata instanceof Self || paramMetadata instanceof SkipSelf) {
14352 visibility = paramMetadata;
14353 }
14354 else if (paramMetadata instanceof InjectionToken) {
14355 token = paramMetadata;
14356 }
14357 }
14358 token = resolveForwardRef(token);
14359 if (token != null) {
14360 return _createDependency(token, optional, visibility);
14361 }
14362 else {
14363 throw noAnnotationError(typeOrFunc, params);
14364 }
14365}
14366function _createDependency(token, optional, visibility) {
14367 return new ReflectiveDependency(ReflectiveKey.get(token), optional, visibility);
14368}
14369
14370/**
14371 * @license
14372 * Copyright Google LLC All Rights Reserved.
14373 *
14374 * Use of this source code is governed by an MIT-style license that can be
14375 * found in the LICENSE file at https://angular.io/license
14376 */
14377// Threshold for the dynamic version
14378const UNDEFINED = {};
14379/**
14380 * A ReflectiveDependency injection container used for instantiating objects and resolving
14381 * dependencies.
14382 *
14383 * An `Injector` is a replacement for a `new` operator, which can automatically resolve the
14384 * constructor dependencies.
14385 *
14386 * In typical use, application code asks for the dependencies in the constructor and they are
14387 * resolved by the `Injector`.
14388 *
14389 * @usageNotes
14390 * ### Example
14391 *
14392 * The following example creates an `Injector` configured to create `Engine` and `Car`.
14393 *
14394 * ```typescript
14395 * @Injectable()
14396 * class Engine {
14397 * }
14398 *
14399 * @Injectable()
14400 * class Car {
14401 * constructor(public engine:Engine) {}
14402 * }
14403 *
14404 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
14405 * var car = injector.get(Car);
14406 * expect(car instanceof Car).toBe(true);
14407 * expect(car.engine instanceof Engine).toBe(true);
14408 * ```
14409 *
14410 * Notice, we don't use the `new` operator because we explicitly want to have the `Injector`
14411 * resolve all of the object's dependencies automatically.
14412 *
14413 * @deprecated from v5 - slow and brings in a lot of code, Use `Injector.create` instead.
14414 * @publicApi
14415 */
14416class ReflectiveInjector {
14417 /**
14418 * Turns an array of provider definitions into an array of resolved providers.
14419 *
14420 * A resolution is a process of flattening multiple nested arrays and converting individual
14421 * providers into an array of `ResolvedReflectiveProvider`s.
14422 *
14423 * @usageNotes
14424 * ### Example
14425 *
14426 * ```typescript
14427 * @Injectable()
14428 * class Engine {
14429 * }
14430 *
14431 * @Injectable()
14432 * class Car {
14433 * constructor(public engine:Engine) {}
14434 * }
14435 *
14436 * var providers = ReflectiveInjector.resolve([Car, [[Engine]]]);
14437 *
14438 * expect(providers.length).toEqual(2);
14439 *
14440 * expect(providers[0] instanceof ResolvedReflectiveProvider).toBe(true);
14441 * expect(providers[0].key.displayName).toBe("Car");
14442 * expect(providers[0].dependencies.length).toEqual(1);
14443 * expect(providers[0].factory).toBeDefined();
14444 *
14445 * expect(providers[1].key.displayName).toBe("Engine");
14446 * });
14447 * ```
14448 *
14449 */
14450 static resolve(providers) {
14451 return resolveReflectiveProviders(providers);
14452 }
14453 /**
14454 * Resolves an array of providers and creates an injector from those providers.
14455 *
14456 * The passed-in providers can be an array of `Type`, `Provider`,
14457 * or a recursive array of more providers.
14458 *
14459 * @usageNotes
14460 * ### Example
14461 *
14462 * ```typescript
14463 * @Injectable()
14464 * class Engine {
14465 * }
14466 *
14467 * @Injectable()
14468 * class Car {
14469 * constructor(public engine:Engine) {}
14470 * }
14471 *
14472 * var injector = ReflectiveInjector.resolveAndCreate([Car, Engine]);
14473 * expect(injector.get(Car) instanceof Car).toBe(true);
14474 * ```
14475 */
14476 static resolveAndCreate(providers, parent) {
14477 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
14478 return ReflectiveInjector.fromResolvedProviders(ResolvedReflectiveProviders, parent);
14479 }
14480 /**
14481 * Creates an injector from previously resolved providers.
14482 *
14483 * This API is the recommended way to construct injectors in performance-sensitive parts.
14484 *
14485 * @usageNotes
14486 * ### Example
14487 *
14488 * ```typescript
14489 * @Injectable()
14490 * class Engine {
14491 * }
14492 *
14493 * @Injectable()
14494 * class Car {
14495 * constructor(public engine:Engine) {}
14496 * }
14497 *
14498 * var providers = ReflectiveInjector.resolve([Car, Engine]);
14499 * var injector = ReflectiveInjector.fromResolvedProviders(providers);
14500 * expect(injector.get(Car) instanceof Car).toBe(true);
14501 * ```
14502 */
14503 static fromResolvedProviders(providers, parent) {
14504 return new ReflectiveInjector_(providers, parent);
14505 }
14506}
14507class ReflectiveInjector_ {
14508 /**
14509 * Private
14510 */
14511 constructor(_providers, _parent) {
14512 /** @internal */
14513 this._constructionCounter = 0;
14514 this._providers = _providers;
14515 this.parent = _parent || null;
14516 const len = _providers.length;
14517 this.keyIds = [];
14518 this.objs = [];
14519 for (let i = 0; i < len; i++) {
14520 this.keyIds[i] = _providers[i].key.id;
14521 this.objs[i] = UNDEFINED;
14522 }
14523 }
14524 get(token, notFoundValue = THROW_IF_NOT_FOUND) {
14525 return this._getByKey(ReflectiveKey.get(token), null, notFoundValue);
14526 }
14527 resolveAndCreateChild(providers) {
14528 const ResolvedReflectiveProviders = ReflectiveInjector.resolve(providers);
14529 return this.createChildFromResolved(ResolvedReflectiveProviders);
14530 }
14531 createChildFromResolved(providers) {
14532 const inj = new ReflectiveInjector_(providers);
14533 inj.parent = this;
14534 return inj;
14535 }
14536 resolveAndInstantiate(provider) {
14537 return this.instantiateResolved(ReflectiveInjector.resolve([provider])[0]);
14538 }
14539 instantiateResolved(provider) {
14540 return this._instantiateProvider(provider);
14541 }
14542 getProviderAtIndex(index) {
14543 if (index < 0 || index >= this._providers.length) {
14544 throw outOfBoundsError(index);
14545 }
14546 return this._providers[index];
14547 }
14548 /** @internal */
14549 _new(provider) {
14550 if (this._constructionCounter++ > this._getMaxNumberOfObjects()) {
14551 throw cyclicDependencyError(this, provider.key);
14552 }
14553 return this._instantiateProvider(provider);
14554 }
14555 _getMaxNumberOfObjects() {
14556 return this.objs.length;
14557 }
14558 _instantiateProvider(provider) {
14559 if (provider.multiProvider) {
14560 const res = [];
14561 for (let i = 0; i < provider.resolvedFactories.length; ++i) {
14562 res[i] = this._instantiate(provider, provider.resolvedFactories[i]);
14563 }
14564 return res;
14565 }
14566 else {
14567 return this._instantiate(provider, provider.resolvedFactories[0]);
14568 }
14569 }
14570 _instantiate(provider, ResolvedReflectiveFactory) {
14571 const factory = ResolvedReflectiveFactory.factory;
14572 let deps;
14573 try {
14574 deps =
14575 ResolvedReflectiveFactory.dependencies.map(dep => this._getByReflectiveDependency(dep));
14576 }
14577 catch (e) {
14578 if (e.addKey) {
14579 e.addKey(this, provider.key);
14580 }
14581 throw e;
14582 }
14583 let obj;
14584 try {
14585 obj = factory(...deps);
14586 }
14587 catch (e) {
14588 throw instantiationError(this, e, e.stack, provider.key);
14589 }
14590 return obj;
14591 }
14592 _getByReflectiveDependency(dep) {
14593 return this._getByKey(dep.key, dep.visibility, dep.optional ? null : THROW_IF_NOT_FOUND);
14594 }
14595 _getByKey(key, visibility, notFoundValue) {
14596 if (key === ReflectiveInjector_.INJECTOR_KEY) {
14597 return this;
14598 }
14599 if (visibility instanceof Self) {
14600 return this._getByKeySelf(key, notFoundValue);
14601 }
14602 else {
14603 return this._getByKeyDefault(key, notFoundValue, visibility);
14604 }
14605 }
14606 _getObjByKeyId(keyId) {
14607 for (let i = 0; i < this.keyIds.length; i++) {
14608 if (this.keyIds[i] === keyId) {
14609 if (this.objs[i] === UNDEFINED) {
14610 this.objs[i] = this._new(this._providers[i]);
14611 }
14612 return this.objs[i];
14613 }
14614 }
14615 return UNDEFINED;
14616 }
14617 /** @internal */
14618 _throwOrNull(key, notFoundValue) {
14619 if (notFoundValue !== THROW_IF_NOT_FOUND) {
14620 return notFoundValue;
14621 }
14622 else {
14623 throw noProviderError(this, key);
14624 }
14625 }
14626 /** @internal */
14627 _getByKeySelf(key, notFoundValue) {
14628 const obj = this._getObjByKeyId(key.id);
14629 return (obj !== UNDEFINED) ? obj : this._throwOrNull(key, notFoundValue);
14630 }
14631 /** @internal */
14632 _getByKeyDefault(key, notFoundValue, visibility) {
14633 let inj;
14634 if (visibility instanceof SkipSelf) {
14635 inj = this.parent;
14636 }
14637 else {
14638 inj = this;
14639 }
14640 while (inj instanceof ReflectiveInjector_) {
14641 const inj_ = inj;
14642 const obj = inj_._getObjByKeyId(key.id);
14643 if (obj !== UNDEFINED)
14644 return obj;
14645 inj = inj_.parent;
14646 }
14647 if (inj !== null) {
14648 return inj.get(key.token, notFoundValue);
14649 }
14650 else {
14651 return this._throwOrNull(key, notFoundValue);
14652 }
14653 }
14654 get displayName() {
14655 const providers = _mapProviders(this, (b) => ' "' + b.key.displayName + '" ')
14656 .join(', ');
14657 return `ReflectiveInjector(providers: [${providers}])`;
14658 }
14659 toString() {
14660 return this.displayName;
14661 }
14662}
14663ReflectiveInjector_.INJECTOR_KEY = ( /* @__PURE__ */ReflectiveKey.get(Injector));
14664function _mapProviders(injector, fn) {
14665 const res = [];
14666 for (let i = 0; i < injector._providers.length; ++i) {
14667 res[i] = fn(injector.getProviderAtIndex(i));
14668 }
14669 return res;
14670}
14671
14672/**
14673 * @license
14674 * Copyright Google LLC All Rights Reserved.
14675 *
14676 * Use of this source code is governed by an MIT-style license that can be
14677 * found in the LICENSE file at https://angular.io/license
14678 */
14679
14680/**
14681 * @license
14682 * Copyright Google LLC All Rights Reserved.
14683 *
14684 * Use of this source code is governed by an MIT-style license that can be
14685 * found in the LICENSE file at https://angular.io/license
14686 */
14687
14688/**
14689 * @license
14690 * Copyright Google LLC All Rights Reserved.
14691 *
14692 * Use of this source code is governed by an MIT-style license that can be
14693 * found in the LICENSE file at https://angular.io/license
14694 */
14695function ɵɵdirectiveInject(token, flags = InjectFlags.Default) {
14696 const lView = getLView();
14697 // Fall back to inject() if view hasn't been created. This situation can happen in tests
14698 // if inject utilities are used before bootstrapping.
14699 if (lView === null) {
14700 // Verify that we will not get into infinite loop.
14701 ngDevMode && assertInjectImplementationNotEqual(ɵɵdirectiveInject);
14702 return ɵɵinject(token, flags);
14703 }
14704 const tNode = getCurrentTNode();
14705 return getOrCreateInjectable(tNode, lView, resolveForwardRef(token), flags);
14706}
14707/**
14708 * Throws an error indicating that a factory function could not be generated by the compiler for a
14709 * particular class.
14710 *
14711 * This instruction allows the actual error message to be optimized away when ngDevMode is turned
14712 * off, saving bytes of generated code while still providing a good experience in dev mode.
14713 *
14714 * The name of the class is not mentioned here, but will be in the generated factory function name
14715 * and thus in the stack trace.
14716 *
14717 * @codeGenApi
14718 */
14719function ɵɵinvalidFactory() {
14720 const msg = ngDevMode ? `This constructor was not compatible with Dependency Injection.` : 'invalid';
14721 throw new Error(msg);
14722}
14723
14724/**
14725 * @license
14726 * Copyright Google LLC All Rights Reserved.
14727 *
14728 * Use of this source code is governed by an MIT-style license that can be
14729 * found in the LICENSE file at https://angular.io/license
14730 */
14731/**
14732 * Update a property on a selected element.
14733 *
14734 * Operates on the element selected by index via the {@link select} instruction.
14735 *
14736 * If the property name also exists as an input property on one of the element's directives,
14737 * the component property will be set instead of the element property. This check must
14738 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled
14739 *
14740 * @param propName Name of property. Because it is going to DOM, this is not subject to
14741 * renaming as part of minification.
14742 * @param value New value to write.
14743 * @param sanitizer An optional function used to sanitize the value.
14744 * @returns This function returns itself so that it may be chained
14745 * (e.g. `property('name', ctx.name)('title', ctx.title)`)
14746 *
14747 * @codeGenApi
14748 */
14749function ɵɵproperty(propName, value, sanitizer) {
14750 const lView = getLView();
14751 const bindingIndex = nextBindingIndex();
14752 if (bindingUpdated(lView, bindingIndex, value)) {
14753 const tView = getTView();
14754 const tNode = getSelectedTNode();
14755 elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, false);
14756 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
14757 }
14758 return ɵɵproperty;
14759}
14760/**
14761 * Given `<div style="..." my-dir>` and `MyDir` with `@Input('style')` we need to write to
14762 * directive input.
14763 */
14764function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased) {
14765 const inputs = tNode.inputs;
14766 const property = isClassBased ? 'class' : 'style';
14767 // We support both 'class' and `className` hence the fallback.
14768 setInputsForProperty(tView, lView, inputs[property], property, value);
14769}
14770
14771/**
14772 * @license
14773 * Copyright Google LLC All Rights Reserved.
14774 *
14775 * Use of this source code is governed by an MIT-style license that can be
14776 * found in the LICENSE file at https://angular.io/license
14777 */
14778function elementStartFirstCreatePass(index, tView, lView, native, name, attrsIndex, localRefsIndex) {
14779 ngDevMode && assertFirstCreatePass(tView);
14780 ngDevMode && ngDevMode.firstCreatePass++;
14781 const tViewConsts = tView.consts;
14782 const attrs = getConstant(tViewConsts, attrsIndex);
14783 const tNode = getOrCreateTNode(tView, index, 2 /* Element */, name, attrs);
14784 const hasDirectives = resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
14785 ngDevMode && logUnknownElementError(tView, native, tNode, hasDirectives);
14786 if (tNode.attrs !== null) {
14787 computeStaticStyling(tNode, tNode.attrs, false);
14788 }
14789 if (tNode.mergedAttrs !== null) {
14790 computeStaticStyling(tNode, tNode.mergedAttrs, true);
14791 }
14792 if (tView.queries !== null) {
14793 tView.queries.elementStart(tView, tNode);
14794 }
14795 return tNode;
14796}
14797/**
14798 * Create DOM element. The instruction must later be followed by `elementEnd()` call.
14799 *
14800 * @param index Index of the element in the LView array
14801 * @param name Name of the DOM Node
14802 * @param attrsIndex Index of the element's attributes in the `consts` array.
14803 * @param localRefsIndex Index of the element's local references in the `consts` array.
14804 *
14805 * Attributes and localRefs are passed as an array of strings where elements with an even index
14806 * hold an attribute name and elements with an odd index hold an attribute value, ex.:
14807 * ['id', 'warning5', 'class', 'alert']
14808 *
14809 * @codeGenApi
14810 */
14811function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
14812 const lView = getLView();
14813 const tView = getTView();
14814 const adjustedIndex = HEADER_OFFSET + index;
14815 ngDevMode &&
14816 assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
14817 ngDevMode && assertIndexInRange(lView, adjustedIndex);
14818 const renderer = lView[RENDERER];
14819 const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace$1());
14820 const tNode = tView.firstCreatePass ?
14821 elementStartFirstCreatePass(adjustedIndex, tView, lView, native, name, attrsIndex, localRefsIndex) :
14822 tView.data[adjustedIndex];
14823 setCurrentTNode(tNode, true);
14824 const mergedAttrs = tNode.mergedAttrs;
14825 if (mergedAttrs !== null) {
14826 setUpAttributes(renderer, native, mergedAttrs);
14827 }
14828 const classes = tNode.classes;
14829 if (classes !== null) {
14830 writeDirectClass(renderer, native, classes);
14831 }
14832 const styles = tNode.styles;
14833 if (styles !== null) {
14834 writeDirectStyle(renderer, native, styles);
14835 }
14836 if ((tNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
14837 // In the i18n case, the translation may have removed this element, so only add it if it is not
14838 // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
14839 appendChild(tView, lView, native, tNode);
14840 }
14841 // any immediate children of a component or template container must be pre-emptively
14842 // monkey-patched with the component view data so that the element can be inspected
14843 // later on using any element discovery utility methods (see `element_discovery.ts`)
14844 if (getElementDepthCount() === 0) {
14845 attachPatchData(native, lView);
14846 }
14847 increaseElementDepthCount();
14848 if (isDirectiveHost(tNode)) {
14849 createDirectivesInstances(tView, lView, tNode);
14850 executeContentQueries(tView, tNode, lView);
14851 }
14852 if (localRefsIndex !== null) {
14853 saveResolvedLocalsInData(lView, tNode);
14854 }
14855}
14856/**
14857 * Mark the end of the element.
14858 *
14859 * @codeGenApi
14860 */
14861function ɵɵelementEnd() {
14862 let currentTNode = getCurrentTNode();
14863 ngDevMode && assertDefined(currentTNode, 'No parent node to close.');
14864 if (isCurrentTNodeParent()) {
14865 setCurrentTNodeAsNotParent();
14866 }
14867 else {
14868 ngDevMode && assertHasParent(getCurrentTNode());
14869 currentTNode = currentTNode.parent;
14870 setCurrentTNode(currentTNode, false);
14871 }
14872 const tNode = currentTNode;
14873 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */);
14874 decreaseElementDepthCount();
14875 const tView = getTView();
14876 if (tView.firstCreatePass) {
14877 registerPostOrderHooks(tView, currentTNode);
14878 if (isContentQueryHost(currentTNode)) {
14879 tView.queries.elementEnd(currentTNode);
14880 }
14881 }
14882 if (tNode.classesWithoutHost != null && hasClassInput(tNode)) {
14883 setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true);
14884 }
14885 if (tNode.stylesWithoutHost != null && hasStyleInput(tNode)) {
14886 setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.stylesWithoutHost, false);
14887 }
14888}
14889/**
14890 * Creates an empty element using {@link elementStart} and {@link elementEnd}
14891 *
14892 * @param index Index of the element in the data array
14893 * @param name Name of the DOM Node
14894 * @param attrsIndex Index of the element's attributes in the `consts` array.
14895 * @param localRefsIndex Index of the element's local references in the `consts` array.
14896 *
14897 * @codeGenApi
14898 */
14899function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
14900 ɵɵelementStart(index, name, attrsIndex, localRefsIndex);
14901 ɵɵelementEnd();
14902}
14903function logUnknownElementError(tView, element, tNode, hasDirectives) {
14904 const schemas = tView.schemas;
14905 // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
14906 // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
14907 // defined as an array (as an empty array in case `schemas` field is not defined) and we should
14908 // execute the check below.
14909 if (schemas === null)
14910 return;
14911 const tagName = tNode.value;
14912 // If the element matches any directive, it's considered as valid.
14913 if (!hasDirectives && tagName !== null) {
14914 // The element is unknown if it's an instance of HTMLUnknownElement or it isn't registered
14915 // as a custom element. Note that unknown elements with a dash in their name won't be instances
14916 // of HTMLUnknownElement in browsers that support web components.
14917 const isUnknown =
14918 // Note that we can't check for `typeof HTMLUnknownElement === 'function'`,
14919 // because while most browsers return 'function', IE returns 'object'.
14920 (typeof HTMLUnknownElement !== 'undefined' && HTMLUnknownElement &&
14921 element instanceof HTMLUnknownElement) ||
14922 (typeof customElements !== 'undefined' && tagName.indexOf('-') > -1 &&
14923 !customElements.get(tagName));
14924 if (isUnknown && !matchingSchemas(tView, tagName)) {
14925 let message = `'${tagName}' is not a known element:\n`;
14926 message += `1. If '${tagName}' is an Angular component, then verify that it is part of this module.\n`;
14927 if (tagName && tagName.indexOf('-') > -1) {
14928 message += `2. If '${tagName}' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.`;
14929 }
14930 else {
14931 message +=
14932 `2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component.`;
14933 }
14934 console.error(formatRuntimeError("304" /* UNKNOWN_ELEMENT */, message));
14935 }
14936 }
14937}
14938
14939/**
14940 * @license
14941 * Copyright Google LLC All Rights Reserved.
14942 *
14943 * Use of this source code is governed by an MIT-style license that can be
14944 * found in the LICENSE file at https://angular.io/license
14945 */
14946function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
14947 ngDevMode && ngDevMode.firstCreatePass++;
14948 const tViewConsts = tView.consts;
14949 const attrs = getConstant(tViewConsts, attrsIndex);
14950 const tNode = getOrCreateTNode(tView, index, 8 /* ElementContainer */, 'ng-container', attrs);
14951 // While ng-container doesn't necessarily support styling, we use the style context to identify
14952 // and execute directives on the ng-container.
14953 if (attrs !== null) {
14954 computeStaticStyling(tNode, attrs, true);
14955 }
14956 const localRefs = getConstant(tViewConsts, localRefsIndex);
14957 resolveDirectives(tView, lView, tNode, localRefs);
14958 if (tView.queries !== null) {
14959 tView.queries.elementStart(tView, tNode);
14960 }
14961 return tNode;
14962}
14963/**
14964 * Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.
14965 * The instruction must later be followed by `elementContainerEnd()` call.
14966 *
14967 * @param index Index of the element in the LView array
14968 * @param attrsIndex Index of the container attributes in the `consts` array.
14969 * @param localRefsIndex Index of the container's local references in the `consts` array.
14970 *
14971 * Even if this instruction accepts a set of attributes no actual attribute values are propagated to
14972 * the DOM (as a comment node can't have attributes). Attributes are here only for directive
14973 * matching purposes and setting initial inputs of directives.
14974 *
14975 * @codeGenApi
14976 */
14977function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
14978 const lView = getLView();
14979 const tView = getTView();
14980 const adjustedIndex = index + HEADER_OFFSET;
14981 ngDevMode && assertIndexInRange(lView, adjustedIndex);
14982 ngDevMode &&
14983 assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings');
14984 const tNode = tView.firstCreatePass ?
14985 elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex) :
14986 tView.data[adjustedIndex];
14987 setCurrentTNode(tNode, true);
14988 ngDevMode && ngDevMode.rendererCreateComment++;
14989 const native = lView[adjustedIndex] =
14990 lView[RENDERER].createComment(ngDevMode ? 'ng-container' : '');
14991 appendChild(tView, lView, native, tNode);
14992 attachPatchData(native, lView);
14993 if (isDirectiveHost(tNode)) {
14994 createDirectivesInstances(tView, lView, tNode);
14995 executeContentQueries(tView, tNode, lView);
14996 }
14997 if (localRefsIndex != null) {
14998 saveResolvedLocalsInData(lView, tNode);
14999 }
15000}
15001/**
15002 * Mark the end of the <ng-container>.
15003 *
15004 * @codeGenApi
15005 */
15006function ɵɵelementContainerEnd() {
15007 let currentTNode = getCurrentTNode();
15008 const tView = getTView();
15009 if (isCurrentTNodeParent()) {
15010 setCurrentTNodeAsNotParent();
15011 }
15012 else {
15013 ngDevMode && assertHasParent(currentTNode);
15014 currentTNode = currentTNode.parent;
15015 setCurrentTNode(currentTNode, false);
15016 }
15017 ngDevMode && assertTNodeType(currentTNode, 8 /* ElementContainer */);
15018 if (tView.firstCreatePass) {
15019 registerPostOrderHooks(tView, currentTNode);
15020 if (isContentQueryHost(currentTNode)) {
15021 tView.queries.elementEnd(currentTNode);
15022 }
15023 }
15024}
15025/**
15026 * Creates an empty logical container using {@link elementContainerStart}
15027 * and {@link elementContainerEnd}
15028 *
15029 * @param index Index of the element in the LView array
15030 * @param attrsIndex Index of the container attributes in the `consts` array.
15031 * @param localRefsIndex Index of the container's local references in the `consts` array.
15032 *
15033 * @codeGenApi
15034 */
15035function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
15036 ɵɵelementContainerStart(index, attrsIndex, localRefsIndex);
15037 ɵɵelementContainerEnd();
15038}
15039
15040/**
15041 * Returns the current OpaqueViewState instance.
15042 *
15043 * Used in conjunction with the restoreView() instruction to save a snapshot
15044 * of the current view and restore it when listeners are invoked. This allows
15045 * walking the declaration view tree in listeners to get vars from parent views.
15046 *
15047 * @codeGenApi
15048 */
15049function ɵɵgetCurrentView() {
15050 return getLView();
15051}
15052
15053/**
15054 * @license
15055 * Copyright Google LLC All Rights Reserved.
15056 *
15057 * Use of this source code is governed by an MIT-style license that can be
15058 * found in the LICENSE file at https://angular.io/license
15059 */
15060/**
15061 * Determine if the argument is shaped like a Promise
15062 */
15063function isPromise(obj) {
15064 // allow any Promise/A+ compliant thenable.
15065 // It's up to the caller to ensure that obj.then conforms to the spec
15066 return !!obj && typeof obj.then === 'function';
15067}
15068/**
15069 * Determine if the argument is a Subscribable
15070 */
15071function isSubscribable(obj) {
15072 return !!obj && typeof obj.subscribe === 'function';
15073}
15074/**
15075 * Determine if the argument is an Observable
15076 *
15077 * Strictly this tests that the `obj` is `Subscribable`, since `Observable`
15078 * types need additional methods, such as `lift()`. But it is adequate for our
15079 * needs since within the Angular framework code we only ever need to use the
15080 * `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects
15081 * into `Observable` as needed.
15082 */
15083const isObservable = isSubscribable;
15084
15085/**
15086 * @license
15087 * Copyright Google LLC All Rights Reserved.
15088 *
15089 * Use of this source code is governed by an MIT-style license that can be
15090 * found in the LICENSE file at https://angular.io/license
15091 */
15092/**
15093 * Adds an event listener to the current node.
15094 *
15095 * If an output exists on one of the node's directives, it also subscribes to the output
15096 * and saves the subscription for later cleanup.
15097 *
15098 * @param eventName Name of the event
15099 * @param listenerFn The function to be called when event emits
15100 * @param useCapture Whether or not to use capture in event listener
15101 * @param eventTargetResolver Function that returns global target information in case this listener
15102 * should be attached to a global object like window, document or body
15103 *
15104 * @codeGenApi
15105 */
15106function ɵɵlistener(eventName, listenerFn, useCapture, eventTargetResolver) {
15107 const lView = getLView();
15108 const tView = getTView();
15109 const tNode = getCurrentTNode();
15110 listenerInternal(tView, lView, lView[RENDERER], tNode, eventName, listenerFn, !!useCapture, eventTargetResolver);
15111 return ɵɵlistener;
15112}
15113/**
15114 * Registers a synthetic host listener (e.g. `(@foo.start)`) on a component or directive.
15115 *
15116 * This instruction is for compatibility purposes and is designed to ensure that a
15117 * synthetic host listener (e.g. `@HostListener('@foo.start')`) properly gets rendered
15118 * in the component's renderer. Normally all host listeners are evaluated with the
15119 * parent component's renderer, but, in the case of animation @triggers, they need
15120 * to be evaluated with the sub component's renderer (because that's where the
15121 * animation triggers are defined).
15122 *
15123 * Do not use this instruction as a replacement for `listener`. This instruction
15124 * only exists to ensure compatibility with the ViewEngine's host binding behavior.
15125 *
15126 * @param eventName Name of the event
15127 * @param listenerFn The function to be called when event emits
15128 * @param useCapture Whether or not to use capture in event listener
15129 * @param eventTargetResolver Function that returns global target information in case this listener
15130 * should be attached to a global object like window, document or body
15131 *
15132 * @codeGenApi
15133 */
15134function ɵɵsyntheticHostListener(eventName, listenerFn) {
15135 const tNode = getCurrentTNode();
15136 const lView = getLView();
15137 const tView = getTView();
15138 const currentDef = getCurrentDirectiveDef(tView.data);
15139 const renderer = loadComponentRenderer(currentDef, tNode, lView);
15140 listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, false);
15141 return ɵɵsyntheticHostListener;
15142}
15143/**
15144 * A utility function that checks if a given element has already an event handler registered for an
15145 * event with a specified name. The TView.cleanup data structure is used to find out which events
15146 * are registered for a given element.
15147 */
15148function findExistingListener(tView, lView, eventName, tNodeIdx) {
15149 const tCleanup = tView.cleanup;
15150 if (tCleanup != null) {
15151 for (let i = 0; i < tCleanup.length - 1; i += 2) {
15152 const cleanupEventName = tCleanup[i];
15153 if (cleanupEventName === eventName && tCleanup[i + 1] === tNodeIdx) {
15154 // We have found a matching event name on the same node but it might not have been
15155 // registered yet, so we must explicitly verify entries in the LView cleanup data
15156 // structures.
15157 const lCleanup = lView[CLEANUP];
15158 const listenerIdxInLCleanup = tCleanup[i + 2];
15159 return lCleanup.length > listenerIdxInLCleanup ? lCleanup[listenerIdxInLCleanup] : null;
15160 }
15161 // TView.cleanup can have a mix of 4-elements entries (for event handler cleanups) or
15162 // 2-element entries (for directive and queries destroy hooks). As such we can encounter
15163 // blocks of 4 or 2 items in the tView.cleanup and this is why we iterate over 2 elements
15164 // first and jump another 2 elements if we detect listeners cleanup (4 elements). Also check
15165 // documentation of TView.cleanup for more details of this data structure layout.
15166 if (typeof cleanupEventName === 'string') {
15167 i += 2;
15168 }
15169 }
15170 }
15171 return null;
15172}
15173function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn, useCapture, eventTargetResolver) {
15174 const isTNodeDirectiveHost = isDirectiveHost(tNode);
15175 const firstCreatePass = tView.firstCreatePass;
15176 const tCleanup = firstCreatePass && getOrCreateTViewCleanup(tView);
15177 const context = lView[CONTEXT];
15178 // When the ɵɵlistener instruction was generated and is executed we know that there is either a
15179 // native listener or a directive output on this element. As such we we know that we will have to
15180 // register a listener and store its cleanup function on LView.
15181 const lCleanup = getOrCreateLViewCleanup(lView);
15182 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
15183 let processOutputs = true;
15184 // Adding a native event listener is applicable when:
15185 // - The corresponding TNode represents a DOM element.
15186 // - The event target has a resolver (usually resulting in a global object,
15187 // such as `window` or `document`).
15188 if ((tNode.type & 3 /* AnyRNode */) || eventTargetResolver) {
15189 const native = getNativeByTNode(tNode, lView);
15190 const target = eventTargetResolver ? eventTargetResolver(native) : native;
15191 const lCleanupIndex = lCleanup.length;
15192 const idxOrTargetGetter = eventTargetResolver ?
15193 (_lView) => eventTargetResolver(unwrapRNode(_lView[tNode.index])) :
15194 tNode.index;
15195 // In order to match current behavior, native DOM event listeners must be added for all
15196 // events (including outputs).
15197 if (isProceduralRenderer(renderer)) {
15198 // There might be cases where multiple directives on the same element try to register an event
15199 // handler function for the same event. In this situation we want to avoid registration of
15200 // several native listeners as each registration would be intercepted by NgZone and
15201 // trigger change detection. This would mean that a single user action would result in several
15202 // change detections being invoked. To avoid this situation we want to have only one call to
15203 // native handler registration (for the same element and same type of event).
15204 //
15205 // In order to have just one native event handler in presence of multiple handler functions,
15206 // we just register a first handler function as a native event listener and then chain
15207 // (coalesce) other handler functions on top of the first native handler function.
15208 let existingListener = null;
15209 // Please note that the coalescing described here doesn't happen for events specifying an
15210 // alternative target (ex. (document:click)) - this is to keep backward compatibility with the
15211 // view engine.
15212 // Also, we don't have to search for existing listeners is there are no directives
15213 // matching on a given node as we can't register multiple event handlers for the same event in
15214 // a template (this would mean having duplicate attributes).
15215 if (!eventTargetResolver && isTNodeDirectiveHost) {
15216 existingListener = findExistingListener(tView, lView, eventName, tNode.index);
15217 }
15218 if (existingListener !== null) {
15219 // Attach a new listener to coalesced listeners list, maintaining the order in which
15220 // listeners are registered. For performance reasons, we keep a reference to the last
15221 // listener in that list (in `__ngLastListenerFn__` field), so we can avoid going through
15222 // the entire set each time we need to add a new listener.
15223 const lastListenerFn = existingListener.__ngLastListenerFn__ || existingListener;
15224 lastListenerFn.__ngNextListenerFn__ = listenerFn;
15225 existingListener.__ngLastListenerFn__ = listenerFn;
15226 processOutputs = false;
15227 }
15228 else {
15229 listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
15230 const cleanupFn = renderer.listen(target, eventName, listenerFn);
15231 ngDevMode && ngDevMode.rendererAddEventListener++;
15232 lCleanup.push(listenerFn, cleanupFn);
15233 tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, lCleanupIndex + 1);
15234 }
15235 }
15236 else {
15237 listenerFn = wrapListener(tNode, lView, context, listenerFn, true /** preventDefault */);
15238 target.addEventListener(eventName, listenerFn, useCapture);
15239 ngDevMode && ngDevMode.rendererAddEventListener++;
15240 lCleanup.push(listenerFn);
15241 tCleanup && tCleanup.push(eventName, idxOrTargetGetter, lCleanupIndex, useCapture);
15242 }
15243 }
15244 else {
15245 // Even if there is no native listener to add, we still need to wrap the listener so that OnPush
15246 // ancestors are marked dirty when an event occurs.
15247 listenerFn = wrapListener(tNode, lView, context, listenerFn, false /** preventDefault */);
15248 }
15249 // subscribe to directive outputs
15250 const outputs = tNode.outputs;
15251 let props;
15252 if (processOutputs && outputs !== null && (props = outputs[eventName])) {
15253 const propsLength = props.length;
15254 if (propsLength) {
15255 for (let i = 0; i < propsLength; i += 2) {
15256 const index = props[i];
15257 ngDevMode && assertIndexInRange(lView, index);
15258 const minifiedName = props[i + 1];
15259 const directiveInstance = lView[index];
15260 const output = directiveInstance[minifiedName];
15261 if (ngDevMode && !isObservable(output)) {
15262 throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`);
15263 }
15264 const subscription = output.subscribe(listenerFn);
15265 const idx = lCleanup.length;
15266 lCleanup.push(listenerFn, subscription);
15267 tCleanup && tCleanup.push(eventName, tNode.index, idx, -(idx + 1));
15268 }
15269 }
15270 }
15271}
15272function executeListenerWithErrorHandling(lView, context, listenerFn, e) {
15273 try {
15274 profiler(6 /* OutputStart */, context, listenerFn);
15275 // Only explicitly returning false from a listener should preventDefault
15276 return listenerFn(e) !== false;
15277 }
15278 catch (error) {
15279 handleError(lView, error);
15280 return false;
15281 }
15282 finally {
15283 profiler(7 /* OutputEnd */, context, listenerFn);
15284 }
15285}
15286/**
15287 * Wraps an event listener with a function that marks ancestors dirty and prevents default behavior,
15288 * if applicable.
15289 *
15290 * @param tNode The TNode associated with this listener
15291 * @param lView The LView that contains this listener
15292 * @param listenerFn The listener function to call
15293 * @param wrapWithPreventDefault Whether or not to prevent default behavior
15294 * (the procedural renderer does this already, so in those cases, we should skip)
15295 */
15296function wrapListener(tNode, lView, context, listenerFn, wrapWithPreventDefault) {
15297 // Note: we are performing most of the work in the listener function itself
15298 // to optimize listener registration.
15299 return function wrapListenerIn_markDirtyAndPreventDefault(e) {
15300 // Ivy uses `Function` as a special token that allows us to unwrap the function
15301 // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`.
15302 if (e === Function) {
15303 return listenerFn;
15304 }
15305 // In order to be backwards compatible with View Engine, events on component host nodes
15306 // must also mark the component view itself dirty (i.e. the view that it owns).
15307 const startView = tNode.flags & 2 /* isComponentHost */ ?
15308 getComponentLViewByIndex(tNode.index, lView) :
15309 lView;
15310 // See interfaces/view.ts for more on LViewFlags.ManualOnPush
15311 if ((lView[FLAGS] & 32 /* ManualOnPush */) === 0) {
15312 markViewDirty(startView);
15313 }
15314 let result = executeListenerWithErrorHandling(lView, context, listenerFn, e);
15315 // A just-invoked listener function might have coalesced listeners so we need to check for
15316 // their presence and invoke as needed.
15317 let nextListenerFn = wrapListenerIn_markDirtyAndPreventDefault.__ngNextListenerFn__;
15318 while (nextListenerFn) {
15319 // We should prevent default if any of the listeners explicitly return false
15320 result = executeListenerWithErrorHandling(lView, context, nextListenerFn, e) && result;
15321 nextListenerFn = nextListenerFn.__ngNextListenerFn__;
15322 }
15323 if (wrapWithPreventDefault && result === false) {
15324 e.preventDefault();
15325 // Necessary for legacy browsers that don't support preventDefault (e.g. IE)
15326 e.returnValue = false;
15327 }
15328 return result;
15329 };
15330}
15331
15332/**
15333 * @license
15334 * Copyright Google LLC All Rights Reserved.
15335 *
15336 * Use of this source code is governed by an MIT-style license that can be
15337 * found in the LICENSE file at https://angular.io/license
15338 */
15339
15340/**
15341 * @license
15342 * Copyright Google LLC All Rights Reserved.
15343 *
15344 * Use of this source code is governed by an MIT-style license that can be
15345 * found in the LICENSE file at https://angular.io/license
15346 */
15347/**
15348 * Retrieves a context at the level specified and saves it as the global, contextViewData.
15349 * Will get the next level up if level is not specified.
15350 *
15351 * This is used to save contexts of parent views so they can be bound in embedded views, or
15352 * in conjunction with reference() to bind a ref from a parent view.
15353 *
15354 * @param level The relative level of the view from which to grab context compared to contextVewData
15355 * @returns context
15356 *
15357 * @codeGenApi
15358 */
15359function ɵɵnextContext(level = 1) {
15360 return nextContextImpl(level);
15361}
15362
15363/**
15364 * @license
15365 * Copyright Google LLC All Rights Reserved.
15366 *
15367 * Use of this source code is governed by an MIT-style license that can be
15368 * found in the LICENSE file at https://angular.io/license
15369 */
15370/**
15371 * Checks a given node against matching projection slots and returns the
15372 * determined slot index. Returns "null" if no slot matched the given node.
15373 *
15374 * This function takes into account the parsed ngProjectAs selector from the
15375 * node's attributes. If present, it will check whether the ngProjectAs selector
15376 * matches any of the projection slot selectors.
15377 */
15378function matchingProjectionSlotIndex(tNode, projectionSlots) {
15379 let wildcardNgContentIndex = null;
15380 const ngProjectAsAttrVal = getProjectAsAttrValue(tNode);
15381 for (let i = 0; i < projectionSlots.length; i++) {
15382 const slotValue = projectionSlots[i];
15383 // The last wildcard projection slot should match all nodes which aren't matching
15384 // any selector. This is necessary to be backwards compatible with view engine.
15385 if (slotValue === '*') {
15386 wildcardNgContentIndex = i;
15387 continue;
15388 }
15389 // If we ran into an `ngProjectAs` attribute, we should match its parsed selector
15390 // to the list of selectors, otherwise we fall back to matching against the node.
15391 if (ngProjectAsAttrVal === null ?
15392 isNodeMatchingSelectorList(tNode, slotValue, /* isProjectionMode */ true) :
15393 isSelectorInSelectorList(ngProjectAsAttrVal, slotValue)) {
15394 return i; // first matching selector "captures" a given node
15395 }
15396 }
15397 return wildcardNgContentIndex;
15398}
15399/**
15400 * Instruction to distribute projectable nodes among <ng-content> occurrences in a given template.
15401 * It takes all the selectors from the entire component's template and decides where
15402 * each projected node belongs (it re-distributes nodes among "buckets" where each "bucket" is
15403 * backed by a selector).
15404 *
15405 * This function requires CSS selectors to be provided in 2 forms: parsed (by a compiler) and text,
15406 * un-parsed form.
15407 *
15408 * The parsed form is needed for efficient matching of a node against a given CSS selector.
15409 * The un-parsed, textual form is needed for support of the ngProjectAs attribute.
15410 *
15411 * Having a CSS selector in 2 different formats is not ideal, but alternatives have even more
15412 * drawbacks:
15413 * - having only a textual form would require runtime parsing of CSS selectors;
15414 * - we can't have only a parsed as we can't re-construct textual form from it (as entered by a
15415 * template author).
15416 *
15417 * @param projectionSlots? A collection of projection slots. A projection slot can be based
15418 * on a parsed CSS selectors or set to the wildcard selector ("*") in order to match
15419 * all nodes which do not match any selector. If not specified, a single wildcard
15420 * selector projection slot will be defined.
15421 *
15422 * @codeGenApi
15423 */
15424function ɵɵprojectionDef(projectionSlots) {
15425 const componentNode = getLView()[DECLARATION_COMPONENT_VIEW][T_HOST];
15426 if (!componentNode.projection) {
15427 // If no explicit projection slots are defined, fall back to a single
15428 // projection slot with the wildcard selector.
15429 const numProjectionSlots = projectionSlots ? projectionSlots.length : 1;
15430 const projectionHeads = componentNode.projection =
15431 newArray(numProjectionSlots, null);
15432 const tails = projectionHeads.slice();
15433 let componentChild = componentNode.child;
15434 while (componentChild !== null) {
15435 const slotIndex = projectionSlots ? matchingProjectionSlotIndex(componentChild, projectionSlots) : 0;
15436 if (slotIndex !== null) {
15437 if (tails[slotIndex]) {
15438 tails[slotIndex].projectionNext = componentChild;
15439 }
15440 else {
15441 projectionHeads[slotIndex] = componentChild;
15442 }
15443 tails[slotIndex] = componentChild;
15444 }
15445 componentChild = componentChild.next;
15446 }
15447 }
15448}
15449/**
15450 * Inserts previously re-distributed projected nodes. This instruction must be preceded by a call
15451 * to the projectionDef instruction.
15452 *
15453 * @param nodeIndex
15454 * @param selectorIndex:
15455 * - 0 when the selector is `*` (or unspecified as this is the default value),
15456 * - 1 based index of the selector from the {@link projectionDef}
15457 *
15458 * @codeGenApi
15459 */
15460function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
15461 const lView = getLView();
15462 const tView = getTView();
15463 const tProjectionNode = getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, 16 /* Projection */, null, attrs || null);
15464 // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
15465 if (tProjectionNode.projection === null)
15466 tProjectionNode.projection = selectorIndex;
15467 // `<ng-content>` has no content
15468 setCurrentTNodeAsNotParent();
15469 if ((tProjectionNode.flags & 64 /* isDetached */) !== 64 /* isDetached */) {
15470 // re-distribution of projectable nodes is stored on a component's view level
15471 applyProjection(tView, lView, tProjectionNode);
15472 }
15473}
15474
15475/**
15476 *
15477 * Update an interpolated property on an element with a lone bound value
15478 *
15479 * Used when the value passed to a property has 1 interpolated value in it, an no additional text
15480 * surrounds that interpolated value:
15481 *
15482 * ```html
15483 * <div title="{{v0}}"></div>
15484 * ```
15485 *
15486 * Its compiled representation is::
15487 *
15488 * ```ts
15489 * ɵɵpropertyInterpolate('title', v0);
15490 * ```
15491 *
15492 * If the property name also exists as an input property on one of the element's directives,
15493 * the component property will be set instead of the element property. This check must
15494 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15495 *
15496 * @param propName The name of the property to update
15497 * @param prefix Static value used for concatenation only.
15498 * @param v0 Value checked for change.
15499 * @param suffix Static value used for concatenation only.
15500 * @param sanitizer An optional sanitizer function
15501 * @returns itself, so that it may be chained.
15502 * @codeGenApi
15503 */
15504function ɵɵpropertyInterpolate(propName, v0, sanitizer) {
15505 ɵɵpropertyInterpolate1(propName, '', v0, '', sanitizer);
15506 return ɵɵpropertyInterpolate;
15507}
15508/**
15509 *
15510 * Update an interpolated property on an element with single bound value surrounded by text.
15511 *
15512 * Used when the value passed to a property has 1 interpolated value in it:
15513 *
15514 * ```html
15515 * <div title="prefix{{v0}}suffix"></div>
15516 * ```
15517 *
15518 * Its compiled representation is::
15519 *
15520 * ```ts
15521 * ɵɵpropertyInterpolate1('title', 'prefix', v0, 'suffix');
15522 * ```
15523 *
15524 * If the property name also exists as an input property on one of the element's directives,
15525 * the component property will be set instead of the element property. This check must
15526 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15527 *
15528 * @param propName The name of the property to update
15529 * @param prefix Static value used for concatenation only.
15530 * @param v0 Value checked for change.
15531 * @param suffix Static value used for concatenation only.
15532 * @param sanitizer An optional sanitizer function
15533 * @returns itself, so that it may be chained.
15534 * @codeGenApi
15535 */
15536function ɵɵpropertyInterpolate1(propName, prefix, v0, suffix, sanitizer) {
15537 const lView = getLView();
15538 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
15539 if (interpolatedValue !== NO_CHANGE) {
15540 const tView = getTView();
15541 const tNode = getSelectedTNode();
15542 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15543 ngDevMode &&
15544 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 1, prefix, suffix);
15545 }
15546 return ɵɵpropertyInterpolate1;
15547}
15548/**
15549 *
15550 * Update an interpolated property on an element with 2 bound values surrounded by text.
15551 *
15552 * Used when the value passed to a property has 2 interpolated values in it:
15553 *
15554 * ```html
15555 * <div title="prefix{{v0}}-{{v1}}suffix"></div>
15556 * ```
15557 *
15558 * Its compiled representation is::
15559 *
15560 * ```ts
15561 * ɵɵpropertyInterpolate2('title', 'prefix', v0, '-', v1, 'suffix');
15562 * ```
15563 *
15564 * If the property name also exists as an input property on one of the element's directives,
15565 * the component property will be set instead of the element property. This check must
15566 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15567 *
15568 * @param propName The name of the property to update
15569 * @param prefix Static value used for concatenation only.
15570 * @param v0 Value checked for change.
15571 * @param i0 Static value used for concatenation only.
15572 * @param v1 Value checked for change.
15573 * @param suffix Static value used for concatenation only.
15574 * @param sanitizer An optional sanitizer function
15575 * @returns itself, so that it may be chained.
15576 * @codeGenApi
15577 */
15578function ɵɵpropertyInterpolate2(propName, prefix, v0, i0, v1, suffix, sanitizer) {
15579 const lView = getLView();
15580 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
15581 if (interpolatedValue !== NO_CHANGE) {
15582 const tView = getTView();
15583 const tNode = getSelectedTNode();
15584 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15585 ngDevMode &&
15586 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 2, prefix, i0, suffix);
15587 }
15588 return ɵɵpropertyInterpolate2;
15589}
15590/**
15591 *
15592 * Update an interpolated property on an element with 3 bound values surrounded by text.
15593 *
15594 * Used when the value passed to a property has 3 interpolated values in it:
15595 *
15596 * ```html
15597 * <div title="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
15598 * ```
15599 *
15600 * Its compiled representation is::
15601 *
15602 * ```ts
15603 * ɵɵpropertyInterpolate3(
15604 * 'title', 'prefix', v0, '-', v1, '-', v2, 'suffix');
15605 * ```
15606 *
15607 * If the property name also exists as an input property on one of the element's directives,
15608 * the component property will be set instead of the element property. This check must
15609 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15610 *
15611 * @param propName The name of the property to update
15612 * @param prefix Static value used for concatenation only.
15613 * @param v0 Value checked for change.
15614 * @param i0 Static value used for concatenation only.
15615 * @param v1 Value checked for change.
15616 * @param i1 Static value used for concatenation only.
15617 * @param v2 Value checked for change.
15618 * @param suffix Static value used for concatenation only.
15619 * @param sanitizer An optional sanitizer function
15620 * @returns itself, so that it may be chained.
15621 * @codeGenApi
15622 */
15623function ɵɵpropertyInterpolate3(propName, prefix, v0, i0, v1, i1, v2, suffix, sanitizer) {
15624 const lView = getLView();
15625 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
15626 if (interpolatedValue !== NO_CHANGE) {
15627 const tView = getTView();
15628 const tNode = getSelectedTNode();
15629 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15630 ngDevMode &&
15631 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 3, prefix, i0, i1, suffix);
15632 }
15633 return ɵɵpropertyInterpolate3;
15634}
15635/**
15636 *
15637 * Update an interpolated property on an element with 4 bound values surrounded by text.
15638 *
15639 * Used when the value passed to a property has 4 interpolated values in it:
15640 *
15641 * ```html
15642 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
15643 * ```
15644 *
15645 * Its compiled representation is::
15646 *
15647 * ```ts
15648 * ɵɵpropertyInterpolate4(
15649 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
15650 * ```
15651 *
15652 * If the property name also exists as an input property on one of the element's directives,
15653 * the component property will be set instead of the element property. This check must
15654 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15655 *
15656 * @param propName The name of the property to update
15657 * @param prefix Static value used for concatenation only.
15658 * @param v0 Value checked for change.
15659 * @param i0 Static value used for concatenation only.
15660 * @param v1 Value checked for change.
15661 * @param i1 Static value used for concatenation only.
15662 * @param v2 Value checked for change.
15663 * @param i2 Static value used for concatenation only.
15664 * @param v3 Value checked for change.
15665 * @param suffix Static value used for concatenation only.
15666 * @param sanitizer An optional sanitizer function
15667 * @returns itself, so that it may be chained.
15668 * @codeGenApi
15669 */
15670function ɵɵpropertyInterpolate4(propName, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, sanitizer) {
15671 const lView = getLView();
15672 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
15673 if (interpolatedValue !== NO_CHANGE) {
15674 const tView = getTView();
15675 const tNode = getSelectedTNode();
15676 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15677 ngDevMode &&
15678 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 4, prefix, i0, i1, i2, suffix);
15679 }
15680 return ɵɵpropertyInterpolate4;
15681}
15682/**
15683 *
15684 * Update an interpolated property on an element with 5 bound values surrounded by text.
15685 *
15686 * Used when the value passed to a property has 5 interpolated values in it:
15687 *
15688 * ```html
15689 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
15690 * ```
15691 *
15692 * Its compiled representation is::
15693 *
15694 * ```ts
15695 * ɵɵpropertyInterpolate5(
15696 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
15697 * ```
15698 *
15699 * If the property name also exists as an input property on one of the element's directives,
15700 * the component property will be set instead of the element property. This check must
15701 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15702 *
15703 * @param propName The name of the property to update
15704 * @param prefix Static value used for concatenation only.
15705 * @param v0 Value checked for change.
15706 * @param i0 Static value used for concatenation only.
15707 * @param v1 Value checked for change.
15708 * @param i1 Static value used for concatenation only.
15709 * @param v2 Value checked for change.
15710 * @param i2 Static value used for concatenation only.
15711 * @param v3 Value checked for change.
15712 * @param i3 Static value used for concatenation only.
15713 * @param v4 Value checked for change.
15714 * @param suffix Static value used for concatenation only.
15715 * @param sanitizer An optional sanitizer function
15716 * @returns itself, so that it may be chained.
15717 * @codeGenApi
15718 */
15719function ɵɵpropertyInterpolate5(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, sanitizer) {
15720 const lView = getLView();
15721 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
15722 if (interpolatedValue !== NO_CHANGE) {
15723 const tView = getTView();
15724 const tNode = getSelectedTNode();
15725 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15726 ngDevMode &&
15727 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 5, prefix, i0, i1, i2, i3, suffix);
15728 }
15729 return ɵɵpropertyInterpolate5;
15730}
15731/**
15732 *
15733 * Update an interpolated property on an element with 6 bound values surrounded by text.
15734 *
15735 * Used when the value passed to a property has 6 interpolated values in it:
15736 *
15737 * ```html
15738 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
15739 * ```
15740 *
15741 * Its compiled representation is::
15742 *
15743 * ```ts
15744 * ɵɵpropertyInterpolate6(
15745 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
15746 * ```
15747 *
15748 * If the property name also exists as an input property on one of the element's directives,
15749 * the component property will be set instead of the element property. This check must
15750 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15751 *
15752 * @param propName The name of the property to update
15753 * @param prefix Static value used for concatenation only.
15754 * @param v0 Value checked for change.
15755 * @param i0 Static value used for concatenation only.
15756 * @param v1 Value checked for change.
15757 * @param i1 Static value used for concatenation only.
15758 * @param v2 Value checked for change.
15759 * @param i2 Static value used for concatenation only.
15760 * @param v3 Value checked for change.
15761 * @param i3 Static value used for concatenation only.
15762 * @param v4 Value checked for change.
15763 * @param i4 Static value used for concatenation only.
15764 * @param v5 Value checked for change.
15765 * @param suffix Static value used for concatenation only.
15766 * @param sanitizer An optional sanitizer function
15767 * @returns itself, so that it may be chained.
15768 * @codeGenApi
15769 */
15770function ɵɵpropertyInterpolate6(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, sanitizer) {
15771 const lView = getLView();
15772 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
15773 if (interpolatedValue !== NO_CHANGE) {
15774 const tView = getTView();
15775 const tNode = getSelectedTNode();
15776 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15777 ngDevMode &&
15778 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 6, prefix, i0, i1, i2, i3, i4, suffix);
15779 }
15780 return ɵɵpropertyInterpolate6;
15781}
15782/**
15783 *
15784 * Update an interpolated property on an element with 7 bound values surrounded by text.
15785 *
15786 * Used when the value passed to a property has 7 interpolated values in it:
15787 *
15788 * ```html
15789 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
15790 * ```
15791 *
15792 * Its compiled representation is::
15793 *
15794 * ```ts
15795 * ɵɵpropertyInterpolate7(
15796 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
15797 * ```
15798 *
15799 * If the property name also exists as an input property on one of the element's directives,
15800 * the component property will be set instead of the element property. This check must
15801 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15802 *
15803 * @param propName The name of the property to update
15804 * @param prefix Static value used for concatenation only.
15805 * @param v0 Value checked for change.
15806 * @param i0 Static value used for concatenation only.
15807 * @param v1 Value checked for change.
15808 * @param i1 Static value used for concatenation only.
15809 * @param v2 Value checked for change.
15810 * @param i2 Static value used for concatenation only.
15811 * @param v3 Value checked for change.
15812 * @param i3 Static value used for concatenation only.
15813 * @param v4 Value checked for change.
15814 * @param i4 Static value used for concatenation only.
15815 * @param v5 Value checked for change.
15816 * @param i5 Static value used for concatenation only.
15817 * @param v6 Value checked for change.
15818 * @param suffix Static value used for concatenation only.
15819 * @param sanitizer An optional sanitizer function
15820 * @returns itself, so that it may be chained.
15821 * @codeGenApi
15822 */
15823function ɵɵpropertyInterpolate7(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, sanitizer) {
15824 const lView = getLView();
15825 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
15826 if (interpolatedValue !== NO_CHANGE) {
15827 const tView = getTView();
15828 const tNode = getSelectedTNode();
15829 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15830 ngDevMode &&
15831 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 7, prefix, i0, i1, i2, i3, i4, i5, suffix);
15832 }
15833 return ɵɵpropertyInterpolate7;
15834}
15835/**
15836 *
15837 * Update an interpolated property on an element with 8 bound values surrounded by text.
15838 *
15839 * Used when the value passed to a property has 8 interpolated values in it:
15840 *
15841 * ```html
15842 * <div title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
15843 * ```
15844 *
15845 * Its compiled representation is::
15846 *
15847 * ```ts
15848 * ɵɵpropertyInterpolate8(
15849 * 'title', 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
15850 * ```
15851 *
15852 * If the property name also exists as an input property on one of the element's directives,
15853 * the component property will be set instead of the element property. This check must
15854 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15855 *
15856 * @param propName The name of the property to update
15857 * @param prefix Static value used for concatenation only.
15858 * @param v0 Value checked for change.
15859 * @param i0 Static value used for concatenation only.
15860 * @param v1 Value checked for change.
15861 * @param i1 Static value used for concatenation only.
15862 * @param v2 Value checked for change.
15863 * @param i2 Static value used for concatenation only.
15864 * @param v3 Value checked for change.
15865 * @param i3 Static value used for concatenation only.
15866 * @param v4 Value checked for change.
15867 * @param i4 Static value used for concatenation only.
15868 * @param v5 Value checked for change.
15869 * @param i5 Static value used for concatenation only.
15870 * @param v6 Value checked for change.
15871 * @param i6 Static value used for concatenation only.
15872 * @param v7 Value checked for change.
15873 * @param suffix Static value used for concatenation only.
15874 * @param sanitizer An optional sanitizer function
15875 * @returns itself, so that it may be chained.
15876 * @codeGenApi
15877 */
15878function ɵɵpropertyInterpolate8(propName, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, sanitizer) {
15879 const lView = getLView();
15880 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
15881 if (interpolatedValue !== NO_CHANGE) {
15882 const tView = getTView();
15883 const tNode = getSelectedTNode();
15884 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15885 ngDevMode &&
15886 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - 8, prefix, i0, i1, i2, i3, i4, i5, i6, suffix);
15887 }
15888 return ɵɵpropertyInterpolate8;
15889}
15890/**
15891 * Update an interpolated property on an element with 9 or more bound values surrounded by text.
15892 *
15893 * Used when the number of interpolated values exceeds 8.
15894 *
15895 * ```html
15896 * <div
15897 * title="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
15898 * ```
15899 *
15900 * Its compiled representation is::
15901 *
15902 * ```ts
15903 * ɵɵpropertyInterpolateV(
15904 * 'title', ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
15905 * 'suffix']);
15906 * ```
15907 *
15908 * If the property name also exists as an input property on one of the element's directives,
15909 * the component property will be set instead of the element property. This check must
15910 * be conducted at runtime so child components that add new `@Inputs` don't have to be re-compiled.
15911 *
15912 * @param propName The name of the property to update.
15913 * @param values The collection of values and the strings inbetween those values, beginning with a
15914 * string prefix and ending with a string suffix.
15915 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
15916 * @param sanitizer An optional sanitizer function
15917 * @returns itself, so that it may be chained.
15918 * @codeGenApi
15919 */
15920function ɵɵpropertyInterpolateV(propName, values, sanitizer) {
15921 const lView = getLView();
15922 const interpolatedValue = interpolationV(lView, values);
15923 if (interpolatedValue !== NO_CHANGE) {
15924 const tView = getTView();
15925 const tNode = getSelectedTNode();
15926 elementPropertyInternal(tView, tNode, lView, propName, interpolatedValue, lView[RENDERER], sanitizer, false);
15927 if (ngDevMode) {
15928 const interpolationInBetween = [values[0]]; // prefix
15929 for (let i = 2; i < values.length; i += 2) {
15930 interpolationInBetween.push(values[i]);
15931 }
15932 storePropertyBindingMetadata(tView.data, tNode, propName, getBindingIndex() - interpolationInBetween.length + 1, ...interpolationInBetween);
15933 }
15934 }
15935 return ɵɵpropertyInterpolateV;
15936}
15937
15938/**
15939 * @license
15940 * Copyright Google LLC All Rights Reserved.
15941 *
15942 * Use of this source code is governed by an MIT-style license that can be
15943 * found in the LICENSE file at https://angular.io/license
15944 */
15945/**
15946 * NOTE: The word `styling` is used interchangeably as style or class styling.
15947 *
15948 * This file contains code to link styling instructions together so that they can be replayed in
15949 * priority order. The file exists because Ivy styling instruction execution order does not match
15950 * that of the priority order. The purpose of this code is to create a linked list so that the
15951 * instructions can be traversed in priority order when computing the styles.
15952 *
15953 * Assume we are dealing with the following code:
15954 * ```
15955 * @Component({
15956 * template: `
15957 * <my-cmp [style]=" {color: '#001'} "
15958 * [style.color]=" #002 "
15959 * dir-style-color-1
15960 * dir-style-color-2> `
15961 * })
15962 * class ExampleComponent {
15963 * static ngComp = ... {
15964 * ...
15965 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
15966 * ɵɵstyleMap({color: '#001'});
15967 * ɵɵstyleProp('color', '#002');
15968 * ...
15969 * }
15970 * }
15971 *
15972 * @Directive({
15973 * selector: `[dir-style-color-1]',
15974 * })
15975 * class Style1Directive {
15976 * @HostBinding('style') style = {color: '#005'};
15977 * @HostBinding('style.color') color = '#006';
15978 *
15979 * static ngDir = ... {
15980 * ...
15981 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
15982 * ɵɵstyleMap({color: '#005'});
15983 * ɵɵstyleProp('color', '#006');
15984 * ...
15985 * }
15986 * }
15987 *
15988 * @Directive({
15989 * selector: `[dir-style-color-2]',
15990 * })
15991 * class Style2Directive {
15992 * @HostBinding('style') style = {color: '#007'};
15993 * @HostBinding('style.color') color = '#008';
15994 *
15995 * static ngDir = ... {
15996 * ...
15997 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
15998 * ɵɵstyleMap({color: '#007'});
15999 * ɵɵstyleProp('color', '#008');
16000 * ...
16001 * }
16002 * }
16003 *
16004 * @Directive({
16005 * selector: `my-cmp',
16006 * })
16007 * class MyComponent {
16008 * @HostBinding('style') style = {color: '#003'};
16009 * @HostBinding('style.color') color = '#004';
16010 *
16011 * static ngComp = ... {
16012 * ...
16013 * // Compiler ensures that `ɵɵstyleProp` is after `ɵɵstyleMap`
16014 * ɵɵstyleMap({color: '#003'});
16015 * ɵɵstyleProp('color', '#004');
16016 * ...
16017 * }
16018 * }
16019 * ```
16020 *
16021 * The Order of instruction execution is:
16022 *
16023 * NOTE: the comment binding location is for illustrative purposes only.
16024 *
16025 * ```
16026 * // Template: (ExampleComponent)
16027 * ɵɵstyleMap({color: '#001'}); // Binding index: 10
16028 * ɵɵstyleProp('color', '#002'); // Binding index: 12
16029 * // MyComponent
16030 * ɵɵstyleMap({color: '#003'}); // Binding index: 20
16031 * ɵɵstyleProp('color', '#004'); // Binding index: 22
16032 * // Style1Directive
16033 * ɵɵstyleMap({color: '#005'}); // Binding index: 24
16034 * ɵɵstyleProp('color', '#006'); // Binding index: 26
16035 * // Style2Directive
16036 * ɵɵstyleMap({color: '#007'}); // Binding index: 28
16037 * ɵɵstyleProp('color', '#008'); // Binding index: 30
16038 * ```
16039 *
16040 * The correct priority order of concatenation is:
16041 *
16042 * ```
16043 * // MyComponent
16044 * ɵɵstyleMap({color: '#003'}); // Binding index: 20
16045 * ɵɵstyleProp('color', '#004'); // Binding index: 22
16046 * // Style1Directive
16047 * ɵɵstyleMap({color: '#005'}); // Binding index: 24
16048 * ɵɵstyleProp('color', '#006'); // Binding index: 26
16049 * // Style2Directive
16050 * ɵɵstyleMap({color: '#007'}); // Binding index: 28
16051 * ɵɵstyleProp('color', '#008'); // Binding index: 30
16052 * // Template: (ExampleComponent)
16053 * ɵɵstyleMap({color: '#001'}); // Binding index: 10
16054 * ɵɵstyleProp('color', '#002'); // Binding index: 12
16055 * ```
16056 *
16057 * What color should be rendered?
16058 *
16059 * Once the items are correctly sorted in the list, the answer is simply the last item in the
16060 * concatenation list which is `#002`.
16061 *
16062 * To do so we keep a linked list of all of the bindings which pertain to this element.
16063 * Notice that the bindings are inserted in the order of execution, but the `TView.data` allows
16064 * us to traverse them in the order of priority.
16065 *
16066 * |Idx|`TView.data`|`LView` | Notes
16067 * |---|------------|-----------------|--------------
16068 * |...| | |
16069 * |10 |`null` |`{color: '#001'}`| `ɵɵstyleMap('color', {color: '#001'})`
16070 * |11 |`30 | 12` | ... |
16071 * |12 |`color` |`'#002'` | `ɵɵstyleProp('color', '#002')`
16072 * |13 |`10 | 0` | ... |
16073 * |...| | |
16074 * |20 |`null` |`{color: '#003'}`| `ɵɵstyleMap('color', {color: '#003'})`
16075 * |21 |`0 | 22` | ... |
16076 * |22 |`color` |`'#004'` | `ɵɵstyleProp('color', '#004')`
16077 * |23 |`20 | 24` | ... |
16078 * |24 |`null` |`{color: '#005'}`| `ɵɵstyleMap('color', {color: '#005'})`
16079 * |25 |`22 | 26` | ... |
16080 * |26 |`color` |`'#006'` | `ɵɵstyleProp('color', '#006')`
16081 * |27 |`24 | 28` | ... |
16082 * |28 |`null` |`{color: '#007'}`| `ɵɵstyleMap('color', {color: '#007'})`
16083 * |29 |`26 | 30` | ... |
16084 * |30 |`color` |`'#008'` | `ɵɵstyleProp('color', '#008')`
16085 * |31 |`28 | 10` | ... |
16086 *
16087 * The above data structure allows us to re-concatenate the styling no matter which data binding
16088 * changes.
16089 *
16090 * NOTE: in addition to keeping track of next/previous index the `TView.data` also stores prev/next
16091 * duplicate bit. The duplicate bit if true says there either is a binding with the same name or
16092 * there is a map (which may contain the name). This information is useful in knowing if other
16093 * styles with higher priority need to be searched for overwrites.
16094 *
16095 * NOTE: See `should support example in 'tnode_linked_list.ts' documentation` in
16096 * `tnode_linked_list_spec.ts` for working example.
16097 */
16098let __unused_const_as_closure_does_not_like_standalone_comment_blocks__;
16099/**
16100 * Insert new `tStyleValue` at `TData` and link existing style bindings such that we maintain linked
16101 * list of styles and compute the duplicate flag.
16102 *
16103 * Note: this function is executed during `firstUpdatePass` only to populate the `TView.data`.
16104 *
16105 * The function works by keeping track of `tStylingRange` which contains two pointers pointing to
16106 * the head/tail of the template portion of the styles.
16107 * - if `isHost === false` (we are template) then insertion is at tail of `TStylingRange`
16108 * - if `isHost === true` (we are host binding) then insertion is at head of `TStylingRange`
16109 *
16110 * @param tData The `TData` to insert into.
16111 * @param tNode `TNode` associated with the styling element.
16112 * @param tStylingKey See `TStylingKey`.
16113 * @param index location of where `tStyleValue` should be stored (and linked into list.)
16114 * @param isHostBinding `true` if the insertion is for a `hostBinding`. (insertion is in front of
16115 * template.)
16116 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
16117 * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
16118 */
16119function insertTStylingBinding(tData, tNode, tStylingKeyWithStatic, index, isHostBinding, isClassBinding) {
16120 ngDevMode && assertFirstUpdatePass(getTView());
16121 let tBindings = isClassBinding ? tNode.classBindings : tNode.styleBindings;
16122 let tmplHead = getTStylingRangePrev(tBindings);
16123 let tmplTail = getTStylingRangeNext(tBindings);
16124 tData[index] = tStylingKeyWithStatic;
16125 let isKeyDuplicateOfStatic = false;
16126 let tStylingKey;
16127 if (Array.isArray(tStylingKeyWithStatic)) {
16128 // We are case when the `TStylingKey` contains static fields as well.
16129 const staticKeyValueArray = tStylingKeyWithStatic;
16130 tStylingKey = staticKeyValueArray[1]; // unwrap.
16131 // We need to check if our key is present in the static so that we can mark it as duplicate.
16132 if (tStylingKey === null ||
16133 keyValueArrayIndexOf(staticKeyValueArray, tStylingKey) > 0) {
16134 // tStylingKey is present in the statics, need to mark it as duplicate.
16135 isKeyDuplicateOfStatic = true;
16136 }
16137 }
16138 else {
16139 tStylingKey = tStylingKeyWithStatic;
16140 }
16141 if (isHostBinding) {
16142 // We are inserting host bindings
16143 // If we don't have template bindings then `tail` is 0.
16144 const hasTemplateBindings = tmplTail !== 0;
16145 // This is important to know because that means that the `head` can't point to the first
16146 // template bindings (there are none.) Instead the head points to the tail of the template.
16147 if (hasTemplateBindings) {
16148 // template head's "prev" will point to last host binding or to 0 if no host bindings yet
16149 const previousNode = getTStylingRangePrev(tData[tmplHead + 1]);
16150 tData[index + 1] = toTStylingRange(previousNode, tmplHead);
16151 // if a host binding has already been registered, we need to update the next of that host
16152 // binding to point to this one
16153 if (previousNode !== 0) {
16154 // We need to update the template-tail value to point to us.
16155 tData[previousNode + 1] =
16156 setTStylingRangeNext(tData[previousNode + 1], index);
16157 }
16158 // The "previous" of the template binding head should point to this host binding
16159 tData[tmplHead + 1] = setTStylingRangePrev(tData[tmplHead + 1], index);
16160 }
16161 else {
16162 tData[index + 1] = toTStylingRange(tmplHead, 0);
16163 // if a host binding has already been registered, we need to update the next of that host
16164 // binding to point to this one
16165 if (tmplHead !== 0) {
16166 // We need to update the template-tail value to point to us.
16167 tData[tmplHead + 1] = setTStylingRangeNext(tData[tmplHead + 1], index);
16168 }
16169 // if we don't have template, the head points to template-tail, and needs to be advanced.
16170 tmplHead = index;
16171 }
16172 }
16173 else {
16174 // We are inserting in template section.
16175 // We need to set this binding's "previous" to the current template tail
16176 tData[index + 1] = toTStylingRange(tmplTail, 0);
16177 ngDevMode &&
16178 assertEqual(tmplHead !== 0 && tmplTail === 0, false, 'Adding template bindings after hostBindings is not allowed.');
16179 if (tmplHead === 0) {
16180 tmplHead = index;
16181 }
16182 else {
16183 // We need to update the previous value "next" to point to this binding
16184 tData[tmplTail + 1] = setTStylingRangeNext(tData[tmplTail + 1], index);
16185 }
16186 tmplTail = index;
16187 }
16188 // Now we need to update / compute the duplicates.
16189 // Starting with our location search towards head (least priority)
16190 if (isKeyDuplicateOfStatic) {
16191 tData[index + 1] = setTStylingRangePrevDuplicate(tData[index + 1]);
16192 }
16193 markDuplicates(tData, tStylingKey, index, true, isClassBinding);
16194 markDuplicates(tData, tStylingKey, index, false, isClassBinding);
16195 markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding);
16196 tBindings = toTStylingRange(tmplHead, tmplTail);
16197 if (isClassBinding) {
16198 tNode.classBindings = tBindings;
16199 }
16200 else {
16201 tNode.styleBindings = tBindings;
16202 }
16203}
16204/**
16205 * Look into the residual styling to see if the current `tStylingKey` is duplicate of residual.
16206 *
16207 * @param tNode `TNode` where the residual is stored.
16208 * @param tStylingKey `TStylingKey` to store.
16209 * @param tData `TData` associated with the current `LView`.
16210 * @param index location of where `tStyleValue` should be stored (and linked into list.)
16211 * @param isClassBinding True if the associated `tStylingKey` as a `class` styling.
16212 * `tNode.classBindings` should be used (or `tNode.styleBindings` otherwise.)
16213 */
16214function markDuplicateOfResidualStyling(tNode, tStylingKey, tData, index, isClassBinding) {
16215 const residual = isClassBinding ? tNode.residualClasses : tNode.residualStyles;
16216 if (residual != null /* or undefined */ && typeof tStylingKey == 'string' &&
16217 keyValueArrayIndexOf(residual, tStylingKey) >= 0) {
16218 // We have duplicate in the residual so mark ourselves as duplicate.
16219 tData[index + 1] = setTStylingRangeNextDuplicate(tData[index + 1]);
16220 }
16221}
16222/**
16223 * Marks `TStyleValue`s as duplicates if another style binding in the list has the same
16224 * `TStyleValue`.
16225 *
16226 * NOTE: this function is intended to be called twice once with `isPrevDir` set to `true` and once
16227 * with it set to `false` to search both the previous as well as next items in the list.
16228 *
16229 * No duplicate case
16230 * ```
16231 * [style.color]
16232 * [style.width.px] <<- index
16233 * [style.height.px]
16234 * ```
16235 *
16236 * In the above case adding `[style.width.px]` to the existing `[style.color]` produces no
16237 * duplicates because `width` is not found in any other part of the linked list.
16238 *
16239 * Duplicate case
16240 * ```
16241 * [style.color]
16242 * [style.width.em]
16243 * [style.width.px] <<- index
16244 * ```
16245 * In the above case adding `[style.width.px]` will produce a duplicate with `[style.width.em]`
16246 * because `width` is found in the chain.
16247 *
16248 * Map case 1
16249 * ```
16250 * [style.width.px]
16251 * [style.color]
16252 * [style] <<- index
16253 * ```
16254 * In the above case adding `[style]` will produce a duplicate with any other bindings because
16255 * `[style]` is a Map and as such is fully dynamic and could produce `color` or `width`.
16256 *
16257 * Map case 2
16258 * ```
16259 * [style]
16260 * [style.width.px]
16261 * [style.color] <<- index
16262 * ```
16263 * In the above case adding `[style.color]` will produce a duplicate because there is already a
16264 * `[style]` binding which is a Map and as such is fully dynamic and could produce `color` or
16265 * `width`.
16266 *
16267 * NOTE: Once `[style]` (Map) is added into the system all things are mapped as duplicates.
16268 * NOTE: We use `style` as example, but same logic is applied to `class`es as well.
16269 *
16270 * @param tData `TData` where the linked list is stored.
16271 * @param tStylingKey `TStylingKeyPrimitive` which contains the value to compare to other keys in
16272 * the linked list.
16273 * @param index Starting location in the linked list to search from
16274 * @param isPrevDir Direction.
16275 * - `true` for previous (lower priority);
16276 * - `false` for next (higher priority).
16277 */
16278function markDuplicates(tData, tStylingKey, index, isPrevDir, isClassBinding) {
16279 const tStylingAtIndex = tData[index + 1];
16280 const isMap = tStylingKey === null;
16281 let cursor = isPrevDir ? getTStylingRangePrev(tStylingAtIndex) : getTStylingRangeNext(tStylingAtIndex);
16282 let foundDuplicate = false;
16283 // We keep iterating as long as we have a cursor
16284 // AND either:
16285 // - we found what we are looking for, OR
16286 // - we are a map in which case we have to continue searching even after we find what we were
16287 // looking for since we are a wild card and everything needs to be flipped to duplicate.
16288 while (cursor !== 0 && (foundDuplicate === false || isMap)) {
16289 ngDevMode && assertIndexInRange(tData, cursor);
16290 const tStylingValueAtCursor = tData[cursor];
16291 const tStyleRangeAtCursor = tData[cursor + 1];
16292 if (isStylingMatch(tStylingValueAtCursor, tStylingKey)) {
16293 foundDuplicate = true;
16294 tData[cursor + 1] = isPrevDir ? setTStylingRangeNextDuplicate(tStyleRangeAtCursor) :
16295 setTStylingRangePrevDuplicate(tStyleRangeAtCursor);
16296 }
16297 cursor = isPrevDir ? getTStylingRangePrev(tStyleRangeAtCursor) :
16298 getTStylingRangeNext(tStyleRangeAtCursor);
16299 }
16300 if (foundDuplicate) {
16301 // if we found a duplicate, than mark ourselves.
16302 tData[index + 1] = isPrevDir ? setTStylingRangePrevDuplicate(tStylingAtIndex) :
16303 setTStylingRangeNextDuplicate(tStylingAtIndex);
16304 }
16305}
16306/**
16307 * Determines if two `TStylingKey`s are a match.
16308 *
16309 * When computing whether a binding contains a duplicate, we need to compare if the instruction
16310 * `TStylingKey` has a match.
16311 *
16312 * Here are examples of `TStylingKey`s which match given `tStylingKeyCursor` is:
16313 * - `color`
16314 * - `color` // Match another color
16315 * - `null` // That means that `tStylingKey` is a `classMap`/`styleMap` instruction
16316 * - `['', 'color', 'other', true]` // wrapped `color` so match
16317 * - `['', null, 'other', true]` // wrapped `null` so match
16318 * - `['', 'width', 'color', 'value']` // wrapped static value contains a match on `'color'`
16319 * - `null` // `tStylingKeyCursor` always match as it is `classMap`/`styleMap` instruction
16320 *
16321 * @param tStylingKeyCursor
16322 * @param tStylingKey
16323 */
16324function isStylingMatch(tStylingKeyCursor, tStylingKey) {
16325 ngDevMode &&
16326 assertNotEqual(Array.isArray(tStylingKey), true, 'Expected that \'tStylingKey\' has been unwrapped');
16327 if (tStylingKeyCursor === null || // If the cursor is `null` it means that we have map at that
16328 // location so we must assume that we have a match.
16329 tStylingKey == null || // If `tStylingKey` is `null` then it is a map therefor assume that it
16330 // contains a match.
16331 (Array.isArray(tStylingKeyCursor) ? tStylingKeyCursor[1] : tStylingKeyCursor) ===
16332 tStylingKey // If the keys match explicitly than we are a match.
16333 ) {
16334 return true;
16335 }
16336 else if (Array.isArray(tStylingKeyCursor) && typeof tStylingKey === 'string') {
16337 // if we did not find a match, but `tStylingKeyCursor` is `KeyValueArray` that means cursor has
16338 // statics and we need to check those as well.
16339 return keyValueArrayIndexOf(tStylingKeyCursor, tStylingKey) >=
16340 0; // see if we are matching the key
16341 }
16342 return false;
16343}
16344
16345/**
16346 * @license
16347 * Copyright Google LLC All Rights Reserved.
16348 *
16349 * Use of this source code is governed by an MIT-style license that can be
16350 * found in the LICENSE file at https://angular.io/license
16351 */
16352// Global state of the parser. (This makes parser non-reentrant, but that is not an issue)
16353const parserState = {
16354 textEnd: 0,
16355 key: 0,
16356 keyEnd: 0,
16357 value: 0,
16358 valueEnd: 0,
16359};
16360/**
16361 * Retrieves the last parsed `key` of style.
16362 * @param text the text to substring the key from.
16363 */
16364function getLastParsedKey(text) {
16365 return text.substring(parserState.key, parserState.keyEnd);
16366}
16367/**
16368 * Retrieves the last parsed `value` of style.
16369 * @param text the text to substring the key from.
16370 */
16371function getLastParsedValue(text) {
16372 return text.substring(parserState.value, parserState.valueEnd);
16373}
16374/**
16375 * Initializes `className` string for parsing and parses the first token.
16376 *
16377 * This function is intended to be used in this format:
16378 * ```
16379 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
16380 * const key = getLastParsedKey();
16381 * ...
16382 * }
16383 * ```
16384 * @param text `className` to parse
16385 * @returns index where the next invocation of `parseClassNameNext` should resume.
16386 */
16387function parseClassName(text) {
16388 resetParserState(text);
16389 return parseClassNameNext(text, consumeWhitespace(text, 0, parserState.textEnd));
16390}
16391/**
16392 * Parses next `className` token.
16393 *
16394 * This function is intended to be used in this format:
16395 * ```
16396 * for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
16397 * const key = getLastParsedKey();
16398 * ...
16399 * }
16400 * ```
16401 *
16402 * @param text `className` to parse
16403 * @param index where the parsing should resume.
16404 * @returns index where the next invocation of `parseClassNameNext` should resume.
16405 */
16406function parseClassNameNext(text, index) {
16407 const end = parserState.textEnd;
16408 if (end === index) {
16409 return -1;
16410 }
16411 index = parserState.keyEnd = consumeClassToken(text, parserState.key = index, end);
16412 return consumeWhitespace(text, index, end);
16413}
16414/**
16415 * Initializes `cssText` string for parsing and parses the first key/values.
16416 *
16417 * This function is intended to be used in this format:
16418 * ```
16419 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
16420 * const key = getLastParsedKey();
16421 * const value = getLastParsedValue();
16422 * ...
16423 * }
16424 * ```
16425 * @param text `cssText` to parse
16426 * @returns index where the next invocation of `parseStyleNext` should resume.
16427 */
16428function parseStyle(text) {
16429 resetParserState(text);
16430 return parseStyleNext(text, consumeWhitespace(text, 0, parserState.textEnd));
16431}
16432/**
16433 * Parses the next `cssText` key/values.
16434 *
16435 * This function is intended to be used in this format:
16436 * ```
16437 * for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i))) {
16438 * const key = getLastParsedKey();
16439 * const value = getLastParsedValue();
16440 * ...
16441 * }
16442 *
16443 * @param text `cssText` to parse
16444 * @param index where the parsing should resume.
16445 * @returns index where the next invocation of `parseStyleNext` should resume.
16446 */
16447function parseStyleNext(text, startIndex) {
16448 const end = parserState.textEnd;
16449 let index = parserState.key = consumeWhitespace(text, startIndex, end);
16450 if (end === index) {
16451 // we reached an end so just quit
16452 return -1;
16453 }
16454 index = parserState.keyEnd = consumeStyleKey(text, index, end);
16455 index = consumeSeparator(text, index, end, 58 /* COLON */);
16456 index = parserState.value = consumeWhitespace(text, index, end);
16457 index = parserState.valueEnd = consumeStyleValue(text, index, end);
16458 return consumeSeparator(text, index, end, 59 /* SEMI_COLON */);
16459}
16460/**
16461 * Reset the global state of the styling parser.
16462 * @param text The styling text to parse.
16463 */
16464function resetParserState(text) {
16465 parserState.key = 0;
16466 parserState.keyEnd = 0;
16467 parserState.value = 0;
16468 parserState.valueEnd = 0;
16469 parserState.textEnd = text.length;
16470}
16471/**
16472 * Returns index of next non-whitespace character.
16473 *
16474 * @param text Text to scan
16475 * @param startIndex Starting index of character where the scan should start.
16476 * @param endIndex Ending index of character where the scan should end.
16477 * @returns Index of next non-whitespace character (May be the same as `start` if no whitespace at
16478 * that location.)
16479 */
16480function consumeWhitespace(text, startIndex, endIndex) {
16481 while (startIndex < endIndex && text.charCodeAt(startIndex) <= 32 /* SPACE */) {
16482 startIndex++;
16483 }
16484 return startIndex;
16485}
16486/**
16487 * Returns index of last char in class token.
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 after last char in class token.
16493 */
16494function consumeClassToken(text, startIndex, endIndex) {
16495 while (startIndex < endIndex && text.charCodeAt(startIndex) > 32 /* SPACE */) {
16496 startIndex++;
16497 }
16498 return startIndex;
16499}
16500/**
16501 * Consumes all of the characters belonging to style key and token.
16502 *
16503 * @param text Text to scan
16504 * @param startIndex Starting index of character where the scan should start.
16505 * @param endIndex Ending index of character where the scan should end.
16506 * @returns Index after last style key character.
16507 */
16508function consumeStyleKey(text, startIndex, endIndex) {
16509 let ch;
16510 while (startIndex < endIndex &&
16511 ((ch = text.charCodeAt(startIndex)) === 45 /* DASH */ || ch === 95 /* UNDERSCORE */ ||
16512 ((ch & -33 /* UPPER_CASE */) >= 65 /* A */ && (ch & -33 /* UPPER_CASE */) <= 90 /* Z */) ||
16513 (ch >= 48 /* ZERO */ && ch <= 57 /* NINE */))) {
16514 startIndex++;
16515 }
16516 return startIndex;
16517}
16518/**
16519 * Consumes all whitespace and the separator `:` after the style key.
16520 *
16521 * @param text Text to scan
16522 * @param startIndex Starting index of character where the scan should start.
16523 * @param endIndex Ending index of character where the scan should end.
16524 * @returns Index after separator and surrounding whitespace.
16525 */
16526function consumeSeparator(text, startIndex, endIndex, separator) {
16527 startIndex = consumeWhitespace(text, startIndex, endIndex);
16528 if (startIndex < endIndex) {
16529 if (ngDevMode && text.charCodeAt(startIndex) !== separator) {
16530 malformedStyleError(text, String.fromCharCode(separator), startIndex);
16531 }
16532 startIndex++;
16533 }
16534 return startIndex;
16535}
16536/**
16537 * Consumes style value honoring `url()` and `""` text.
16538 *
16539 * @param text Text to scan
16540 * @param startIndex Starting index of character where the scan should start.
16541 * @param endIndex Ending index of character where the scan should end.
16542 * @returns Index after last style value character.
16543 */
16544function consumeStyleValue(text, startIndex, endIndex) {
16545 let ch1 = -1; // 1st previous character
16546 let ch2 = -1; // 2nd previous character
16547 let ch3 = -1; // 3rd previous character
16548 let i = startIndex;
16549 let lastChIndex = i;
16550 while (i < endIndex) {
16551 const ch = text.charCodeAt(i++);
16552 if (ch === 59 /* SEMI_COLON */) {
16553 return lastChIndex;
16554 }
16555 else if (ch === 34 /* DOUBLE_QUOTE */ || ch === 39 /* SINGLE_QUOTE */) {
16556 lastChIndex = i = consumeQuotedText(text, ch, i, endIndex);
16557 }
16558 else if (startIndex ===
16559 i - 4 && // We have seen only 4 characters so far "URL(" (Ignore "foo_URL()")
16560 ch3 === 85 /* U */ &&
16561 ch2 === 82 /* R */ && ch1 === 76 /* L */ && ch === 40 /* OPEN_PAREN */) {
16562 lastChIndex = i = consumeQuotedText(text, 41 /* CLOSE_PAREN */, i, endIndex);
16563 }
16564 else if (ch > 32 /* SPACE */) {
16565 // if we have a non-whitespace character then capture its location
16566 lastChIndex = i;
16567 }
16568 ch3 = ch2;
16569 ch2 = ch1;
16570 ch1 = ch & -33 /* UPPER_CASE */;
16571 }
16572 return lastChIndex;
16573}
16574/**
16575 * Consumes all of the quoted characters.
16576 *
16577 * @param text Text to scan
16578 * @param quoteCharCode CharCode of either `"` or `'` quote or `)` for `url(...)`.
16579 * @param startIndex Starting index of character where the scan should start.
16580 * @param endIndex Ending index of character where the scan should end.
16581 * @returns Index after quoted characters.
16582 */
16583function consumeQuotedText(text, quoteCharCode, startIndex, endIndex) {
16584 let ch1 = -1; // 1st previous character
16585 let index = startIndex;
16586 while (index < endIndex) {
16587 const ch = text.charCodeAt(index++);
16588 if (ch == quoteCharCode && ch1 !== 92 /* BACK_SLASH */) {
16589 return index;
16590 }
16591 if (ch == 92 /* BACK_SLASH */ && ch1 === 92 /* BACK_SLASH */) {
16592 // two back slashes cancel each other out. For example `"\\"` should properly end the
16593 // quotation. (It should not assume that the last `"` is escaped.)
16594 ch1 = 0;
16595 }
16596 else {
16597 ch1 = ch;
16598 }
16599 }
16600 throw ngDevMode ? malformedStyleError(text, String.fromCharCode(quoteCharCode), endIndex) :
16601 new Error();
16602}
16603function malformedStyleError(text, expecting, index) {
16604 ngDevMode && assertEqual(typeof text === 'string', true, 'String expected here');
16605 throw throwError(`Malformed style at location ${index} in string '` + text.substring(0, index) + '[>>' +
16606 text.substring(index, index + 1) + '<<]' + text.substr(index + 1) +
16607 `'. Expecting '${expecting}'.`);
16608}
16609
16610/**
16611 * @license
16612 * Copyright Google LLC All Rights Reserved.
16613 *
16614 * Use of this source code is governed by an MIT-style license that can be
16615 * found in the LICENSE file at https://angular.io/license
16616 */
16617/**
16618 * Update a style binding on an element with the provided value.
16619 *
16620 * If the style value is falsy then it will be removed from the element
16621 * (or assigned a different value depending if there are any styles placed
16622 * on the element with `styleMap` or any static styles that are
16623 * present from when the element was created with `styling`).
16624 *
16625 * Note that the styling element is updated as part of `stylingApply`.
16626 *
16627 * @param prop A valid CSS property.
16628 * @param value New value to write (`null` or an empty string to remove).
16629 * @param suffix Optional suffix. Used with scalar values to add unit such as `px`.
16630 *
16631 * Note that this will apply the provided style value to the host element if this function is called
16632 * within a host binding function.
16633 *
16634 * @codeGenApi
16635 */
16636function ɵɵstyleProp(prop, value, suffix) {
16637 checkStylingProperty(prop, value, suffix, false);
16638 return ɵɵstyleProp;
16639}
16640/**
16641 * Update a class binding on an element with the provided value.
16642 *
16643 * This instruction is meant to handle the `[class.foo]="exp"` case and,
16644 * therefore, the class binding itself must already be allocated using
16645 * `styling` within the creation block.
16646 *
16647 * @param prop A valid CSS class (only one).
16648 * @param value A true/false value which will turn the class on or off.
16649 *
16650 * Note that this will apply the provided class value to the host element if this function
16651 * is called within a host binding function.
16652 *
16653 * @codeGenApi
16654 */
16655function ɵɵclassProp(className, value) {
16656 checkStylingProperty(className, value, null, true);
16657 return ɵɵclassProp;
16658}
16659/**
16660 * Update style bindings using an object literal on an element.
16661 *
16662 * This instruction is meant to apply styling via the `[style]="exp"` template bindings.
16663 * When styles are applied to the element they will then be updated with respect to
16664 * any styles/classes set via `styleProp`. If any styles are set to falsy
16665 * then they will be removed from the element.
16666 *
16667 * Note that the styling instruction will not be applied until `stylingApply` is called.
16668 *
16669 * @param styles A key/value style map of the styles that will be applied to the given element.
16670 * Any missing styles (that have already been applied to the element beforehand) will be
16671 * removed (unset) from the element's styling.
16672 *
16673 * Note that this will apply the provided styleMap value to the host element if this function
16674 * is called within a host binding.
16675 *
16676 * @codeGenApi
16677 */
16678function ɵɵstyleMap(styles) {
16679 checkStylingMap(styleKeyValueArraySet, styleStringParser, styles, false);
16680}
16681/**
16682 * Parse text as style and add values to KeyValueArray.
16683 *
16684 * This code is pulled out to a separate function so that it can be tree shaken away if it is not
16685 * needed. It is only referenced from `ɵɵstyleMap`.
16686 *
16687 * @param keyValueArray KeyValueArray to add parsed values to.
16688 * @param text text to parse.
16689 */
16690function styleStringParser(keyValueArray, text) {
16691 for (let i = parseStyle(text); i >= 0; i = parseStyleNext(text, i)) {
16692 styleKeyValueArraySet(keyValueArray, getLastParsedKey(text), getLastParsedValue(text));
16693 }
16694}
16695/**
16696 * Update class bindings using an object literal or class-string on an element.
16697 *
16698 * This instruction is meant to apply styling via the `[class]="exp"` template bindings.
16699 * When classes are applied to the element they will then be updated with
16700 * respect to any styles/classes set via `classProp`. If any
16701 * classes are set to falsy then they will be removed from the element.
16702 *
16703 * Note that the styling instruction will not be applied until `stylingApply` is called.
16704 * Note that this will the provided classMap value to the host element if this function is called
16705 * within a host binding.
16706 *
16707 * @param classes A key/value map or string of CSS classes that will be added to the
16708 * given element. Any missing classes (that have already been applied to the element
16709 * beforehand) will be removed (unset) from the element's list of CSS classes.
16710 *
16711 * @codeGenApi
16712 */
16713function ɵɵclassMap(classes) {
16714 checkStylingMap(keyValueArraySet, classStringParser, classes, true);
16715}
16716/**
16717 * Parse text as class and add values to KeyValueArray.
16718 *
16719 * This code is pulled out to a separate function so that it can be tree shaken away if it is not
16720 * needed. It is only referenced from `ɵɵclassMap`.
16721 *
16722 * @param keyValueArray KeyValueArray to add parsed values to.
16723 * @param text text to parse.
16724 */
16725function classStringParser(keyValueArray, text) {
16726 for (let i = parseClassName(text); i >= 0; i = parseClassNameNext(text, i)) {
16727 keyValueArraySet(keyValueArray, getLastParsedKey(text), true);
16728 }
16729}
16730/**
16731 * Common code between `ɵɵclassProp` and `ɵɵstyleProp`.
16732 *
16733 * @param prop property name.
16734 * @param value binding value.
16735 * @param suffix suffix for the property (e.g. `em` or `px`)
16736 * @param isClassBased `true` if `class` change (`false` if `style`)
16737 */
16738function checkStylingProperty(prop, value, suffix, isClassBased) {
16739 const lView = getLView();
16740 const tView = getTView();
16741 // Styling instructions use 2 slots per binding.
16742 // 1. one for the value / TStylingKey
16743 // 2. one for the intermittent-value / TStylingRange
16744 const bindingIndex = incrementBindingIndex(2);
16745 if (tView.firstUpdatePass) {
16746 stylingFirstUpdatePass(tView, prop, bindingIndex, isClassBased);
16747 }
16748 if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
16749 const tNode = tView.data[getSelectedIndex()];
16750 updateStyling(tView, tNode, lView, lView[RENDERER], prop, lView[bindingIndex + 1] = normalizeSuffix(value, suffix), isClassBased, bindingIndex);
16751 }
16752}
16753/**
16754 * Common code between `ɵɵclassMap` and `ɵɵstyleMap`.
16755 *
16756 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
16757 * function so that `style` can be processed. This is done for tree shaking purposes.
16758 * @param stringParser Parser used to parse `value` if `string`. (Passed in as `style` and `class`
16759 * have different parsers.)
16760 * @param value bound value from application
16761 * @param isClassBased `true` if `class` change (`false` if `style`)
16762 */
16763function checkStylingMap(keyValueArraySet, stringParser, value, isClassBased) {
16764 const tView = getTView();
16765 const bindingIndex = incrementBindingIndex(2);
16766 if (tView.firstUpdatePass) {
16767 stylingFirstUpdatePass(tView, null, bindingIndex, isClassBased);
16768 }
16769 const lView = getLView();
16770 if (value !== NO_CHANGE && bindingUpdated(lView, bindingIndex, value)) {
16771 // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
16772 // if so as not to read unnecessarily.
16773 const tNode = tView.data[getSelectedIndex()];
16774 if (hasStylingInputShadow(tNode, isClassBased) && !isInHostBindings(tView, bindingIndex)) {
16775 if (ngDevMode) {
16776 // verify that if we are shadowing then `TData` is appropriately marked so that we skip
16777 // processing this binding in styling resolution.
16778 const tStylingKey = tView.data[bindingIndex];
16779 assertEqual(Array.isArray(tStylingKey) ? tStylingKey[1] : tStylingKey, false, 'Styling linked list shadow input should be marked as \'false\'');
16780 }
16781 // VE does not concatenate the static portion like we are doing here.
16782 // Instead VE just ignores the static completely if dynamic binding is present.
16783 // Because of locality we have already set the static portion because we don't know if there
16784 // is a dynamic portion until later. If we would ignore the static portion it would look like
16785 // the binding has removed it. This would confuse `[ngStyle]`/`[ngClass]` to do the wrong
16786 // thing as it would think that the static portion was removed. For this reason we
16787 // concatenate it so that `[ngStyle]`/`[ngClass]` can continue to work on changed.
16788 let staticPrefix = isClassBased ? tNode.classesWithoutHost : tNode.stylesWithoutHost;
16789 ngDevMode && isClassBased === false && staticPrefix !== null &&
16790 assertEqual(staticPrefix.endsWith(';'), true, 'Expecting static portion to end with \';\'');
16791 if (staticPrefix !== null) {
16792 // We want to make sure that falsy values of `value` become empty strings.
16793 value = concatStringsWithSpace(staticPrefix, value ? value : '');
16794 }
16795 // Given `<div [style] my-dir>` such that `my-dir` has `@Input('style')`.
16796 // This takes over the `[style]` binding. (Same for `[class]`)
16797 setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isClassBased);
16798 }
16799 else {
16800 updateStylingMap(tView, tNode, lView, lView[RENDERER], lView[bindingIndex + 1], lView[bindingIndex + 1] = toStylingKeyValueArray(keyValueArraySet, stringParser, value), isClassBased, bindingIndex);
16801 }
16802 }
16803}
16804/**
16805 * Determines when the binding is in `hostBindings` section
16806 *
16807 * @param tView Current `TView`
16808 * @param bindingIndex index of binding which we would like if it is in `hostBindings`
16809 */
16810function isInHostBindings(tView, bindingIndex) {
16811 // All host bindings are placed after the expando section.
16812 return bindingIndex >= tView.expandoStartIndex;
16813}
16814/**
16815 * Collects the necessary information to insert the binding into a linked list of style bindings
16816 * using `insertTStylingBinding`.
16817 *
16818 * @param tView `TView` where the binding linked list will be stored.
16819 * @param tStylingKey Property/key of the binding.
16820 * @param bindingIndex Index of binding associated with the `prop`
16821 * @param isClassBased `true` if `class` change (`false` if `style`)
16822 */
16823function stylingFirstUpdatePass(tView, tStylingKey, bindingIndex, isClassBased) {
16824 ngDevMode && assertFirstUpdatePass(tView);
16825 const tData = tView.data;
16826 if (tData[bindingIndex + 1] === null) {
16827 // The above check is necessary because we don't clear first update pass until first successful
16828 // (no exception) template execution. This prevents the styling instruction from double adding
16829 // itself to the list.
16830 // `getSelectedIndex()` should be here (rather than in instruction) so that it is guarded by the
16831 // if so as not to read unnecessarily.
16832 const tNode = tData[getSelectedIndex()];
16833 ngDevMode && assertDefined(tNode, 'TNode expected');
16834 const isHostBindings = isInHostBindings(tView, bindingIndex);
16835 if (hasStylingInputShadow(tNode, isClassBased) && tStylingKey === null && !isHostBindings) {
16836 // `tStylingKey === null` implies that we are either `[style]` or `[class]` binding.
16837 // If there is a directive which uses `@Input('style')` or `@Input('class')` than
16838 // we need to neutralize this binding since that directive is shadowing it.
16839 // We turn this into a noop by setting the key to `false`
16840 tStylingKey = false;
16841 }
16842 tStylingKey = wrapInStaticStylingKey(tData, tNode, tStylingKey, isClassBased);
16843 insertTStylingBinding(tData, tNode, tStylingKey, bindingIndex, isHostBindings, isClassBased);
16844 }
16845}
16846/**
16847 * Adds static styling information to the binding if applicable.
16848 *
16849 * The linked list of styles not only stores the list and keys, but also stores static styling
16850 * information on some of the keys. This function determines if the key should contain the styling
16851 * information and computes it.
16852 *
16853 * See `TStylingStatic` for more details.
16854 *
16855 * @param tData `TData` where the linked list is stored.
16856 * @param tNode `TNode` for which the styling is being computed.
16857 * @param stylingKey `TStylingKeyPrimitive` which may need to be wrapped into `TStylingKey`
16858 * @param isClassBased `true` if `class` (`false` if `style`)
16859 */
16860function wrapInStaticStylingKey(tData, tNode, stylingKey, isClassBased) {
16861 const hostDirectiveDef = getCurrentDirectiveDef(tData);
16862 let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
16863 if (hostDirectiveDef === null) {
16864 // We are in template node.
16865 // If template node already had styling instruction then it has already collected the static
16866 // styling and there is no need to collect them again. We know that we are the first styling
16867 // instruction because the `TNode.*Bindings` points to 0 (nothing has been inserted yet).
16868 const isFirstStylingInstructionInTemplate = (isClassBased ? tNode.classBindings : tNode.styleBindings) === 0;
16869 if (isFirstStylingInstructionInTemplate) {
16870 // It would be nice to be able to get the statics from `mergeAttrs`, however, at this point
16871 // they are already merged and it would not be possible to figure which property belongs where
16872 // in the priority.
16873 stylingKey = collectStylingFromDirectives(null, tData, tNode, stylingKey, isClassBased);
16874 stylingKey = collectStylingFromTAttrs(stylingKey, tNode.attrs, isClassBased);
16875 // We know that if we have styling binding in template we can't have residual.
16876 residual = null;
16877 }
16878 }
16879 else {
16880 // We are in host binding node and there was no binding instruction in template node.
16881 // This means that we need to compute the residual.
16882 const directiveStylingLast = tNode.directiveStylingLast;
16883 const isFirstStylingInstructionInHostBinding = directiveStylingLast === -1 || tData[directiveStylingLast] !== hostDirectiveDef;
16884 if (isFirstStylingInstructionInHostBinding) {
16885 stylingKey =
16886 collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased);
16887 if (residual === null) {
16888 // - If `null` than either:
16889 // - Template styling instruction already ran and it has consumed the static
16890 // styling into its `TStylingKey` and so there is no need to update residual. Instead
16891 // we need to update the `TStylingKey` associated with the first template node
16892 // instruction. OR
16893 // - Some other styling instruction ran and determined that there are no residuals
16894 let templateStylingKey = getTemplateHeadTStylingKey(tData, tNode, isClassBased);
16895 if (templateStylingKey !== undefined && Array.isArray(templateStylingKey)) {
16896 // Only recompute if `templateStylingKey` had static values. (If no static value found
16897 // then there is nothing to do since this operation can only produce less static keys, not
16898 // more.)
16899 templateStylingKey = collectStylingFromDirectives(null, tData, tNode, templateStylingKey[1] /* unwrap previous statics */, isClassBased);
16900 templateStylingKey =
16901 collectStylingFromTAttrs(templateStylingKey, tNode.attrs, isClassBased);
16902 setTemplateHeadTStylingKey(tData, tNode, isClassBased, templateStylingKey);
16903 }
16904 }
16905 else {
16906 // We only need to recompute residual if it is not `null`.
16907 // - If existing residual (implies there was no template styling). This means that some of
16908 // the statics may have moved from the residual to the `stylingKey` and so we have to
16909 // recompute.
16910 // - If `undefined` this is the first time we are running.
16911 residual = collectResidual(tData, tNode, isClassBased);
16912 }
16913 }
16914 }
16915 if (residual !== undefined) {
16916 isClassBased ? (tNode.residualClasses = residual) : (tNode.residualStyles = residual);
16917 }
16918 return stylingKey;
16919}
16920/**
16921 * Retrieve the `TStylingKey` for the template styling instruction.
16922 *
16923 * This is needed since `hostBinding` styling instructions are inserted after the template
16924 * instruction. While the template instruction needs to update the residual in `TNode` the
16925 * `hostBinding` instructions need to update the `TStylingKey` of the template instruction because
16926 * the template instruction is downstream from the `hostBindings` instructions.
16927 *
16928 * @param tData `TData` where the linked list is stored.
16929 * @param tNode `TNode` for which the styling is being computed.
16930 * @param isClassBased `true` if `class` (`false` if `style`)
16931 * @return `TStylingKey` if found or `undefined` if not found.
16932 */
16933function getTemplateHeadTStylingKey(tData, tNode, isClassBased) {
16934 const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
16935 if (getTStylingRangeNext(bindings) === 0) {
16936 // There does not seem to be a styling instruction in the `template`.
16937 return undefined;
16938 }
16939 return tData[getTStylingRangePrev(bindings)];
16940}
16941/**
16942 * Update the `TStylingKey` of the first template instruction in `TNode`.
16943 *
16944 * Logically `hostBindings` styling instructions are of lower priority than that of the template.
16945 * However, they execute after the template styling instructions. This means that they get inserted
16946 * in front of the template styling instructions.
16947 *
16948 * If we have a template styling instruction and a new `hostBindings` styling instruction is
16949 * executed it means that it may need to steal static fields from the template instruction. This
16950 * method allows us to update the first template instruction `TStylingKey` with a new value.
16951 *
16952 * Assume:
16953 * ```
16954 * <div my-dir style="color: red" [style.color]="tmplExp"></div>
16955 *
16956 * @Directive({
16957 * host: {
16958 * 'style': 'width: 100px',
16959 * '[style.color]': 'dirExp',
16960 * }
16961 * })
16962 * class MyDir {}
16963 * ```
16964 *
16965 * when `[style.color]="tmplExp"` executes it creates this data structure.
16966 * ```
16967 * ['', 'color', 'color', 'red', 'width', '100px'],
16968 * ```
16969 *
16970 * The reason for this is that the template instruction does not know if there are styling
16971 * instructions and must assume that there are none and must collect all of the static styling.
16972 * (both
16973 * `color' and 'width`)
16974 *
16975 * When `'[style.color]': 'dirExp',` executes we need to insert a new data into the linked list.
16976 * ```
16977 * ['', 'color', 'width', '100px'], // newly inserted
16978 * ['', 'color', 'color', 'red', 'width', '100px'], // this is wrong
16979 * ```
16980 *
16981 * Notice that the template statics is now wrong as it incorrectly contains `width` so we need to
16982 * update it like so:
16983 * ```
16984 * ['', 'color', 'width', '100px'],
16985 * ['', 'color', 'color', 'red'], // UPDATE
16986 * ```
16987 *
16988 * @param tData `TData` where the linked list is stored.
16989 * @param tNode `TNode` for which the styling is being computed.
16990 * @param isClassBased `true` if `class` (`false` if `style`)
16991 * @param tStylingKey New `TStylingKey` which is replacing the old one.
16992 */
16993function setTemplateHeadTStylingKey(tData, tNode, isClassBased, tStylingKey) {
16994 const bindings = isClassBased ? tNode.classBindings : tNode.styleBindings;
16995 ngDevMode &&
16996 assertNotEqual(getTStylingRangeNext(bindings), 0, 'Expecting to have at least one template styling binding.');
16997 tData[getTStylingRangePrev(bindings)] = tStylingKey;
16998}
16999/**
17000 * Collect all static values after the current `TNode.directiveStylingLast` index.
17001 *
17002 * Collect the remaining styling information which has not yet been collected by an existing
17003 * styling instruction.
17004 *
17005 * @param tData `TData` where the `DirectiveDefs` are stored.
17006 * @param tNode `TNode` which contains the directive range.
17007 * @param isClassBased `true` if `class` (`false` if `style`)
17008 */
17009function collectResidual(tData, tNode, isClassBased) {
17010 let residual = undefined;
17011 const directiveEnd = tNode.directiveEnd;
17012 ngDevMode &&
17013 assertNotEqual(tNode.directiveStylingLast, -1, 'By the time this function gets called at least one hostBindings-node styling instruction must have executed.');
17014 // We add `1 + tNode.directiveStart` because we need to skip the current directive (as we are
17015 // collecting things after the last `hostBindings` directive which had a styling instruction.)
17016 for (let i = 1 + tNode.directiveStylingLast; i < directiveEnd; i++) {
17017 const attrs = tData[i].hostAttrs;
17018 residual = collectStylingFromTAttrs(residual, attrs, isClassBased);
17019 }
17020 return collectStylingFromTAttrs(residual, tNode.attrs, isClassBased);
17021}
17022/**
17023 * Collect the static styling information with lower priority than `hostDirectiveDef`.
17024 *
17025 * (This is opposite of residual styling.)
17026 *
17027 * @param hostDirectiveDef `DirectiveDef` for which we want to collect lower priority static
17028 * styling. (Or `null` if template styling)
17029 * @param tData `TData` where the linked list is stored.
17030 * @param tNode `TNode` for which the styling is being computed.
17031 * @param stylingKey Existing `TStylingKey` to update or wrap.
17032 * @param isClassBased `true` if `class` (`false` if `style`)
17033 */
17034function collectStylingFromDirectives(hostDirectiveDef, tData, tNode, stylingKey, isClassBased) {
17035 // We need to loop because there can be directives which have `hostAttrs` but don't have
17036 // `hostBindings` so this loop catches up to the current directive..
17037 let currentDirective = null;
17038 const directiveEnd = tNode.directiveEnd;
17039 let directiveStylingLast = tNode.directiveStylingLast;
17040 if (directiveStylingLast === -1) {
17041 directiveStylingLast = tNode.directiveStart;
17042 }
17043 else {
17044 directiveStylingLast++;
17045 }
17046 while (directiveStylingLast < directiveEnd) {
17047 currentDirective = tData[directiveStylingLast];
17048 ngDevMode && assertDefined(currentDirective, 'expected to be defined');
17049 stylingKey = collectStylingFromTAttrs(stylingKey, currentDirective.hostAttrs, isClassBased);
17050 if (currentDirective === hostDirectiveDef)
17051 break;
17052 directiveStylingLast++;
17053 }
17054 if (hostDirectiveDef !== null) {
17055 // we only advance the styling cursor if we are collecting data from host bindings.
17056 // Template executes before host bindings and so if we would update the index,
17057 // host bindings would not get their statics.
17058 tNode.directiveStylingLast = directiveStylingLast;
17059 }
17060 return stylingKey;
17061}
17062/**
17063 * Convert `TAttrs` into `TStylingStatic`.
17064 *
17065 * @param stylingKey existing `TStylingKey` to update or wrap.
17066 * @param attrs `TAttributes` to process.
17067 * @param isClassBased `true` if `class` (`false` if `style`)
17068 */
17069function collectStylingFromTAttrs(stylingKey, attrs, isClassBased) {
17070 const desiredMarker = isClassBased ? 1 /* Classes */ : 2 /* Styles */;
17071 let currentMarker = -1 /* ImplicitAttributes */;
17072 if (attrs !== null) {
17073 for (let i = 0; i < attrs.length; i++) {
17074 const item = attrs[i];
17075 if (typeof item === 'number') {
17076 currentMarker = item;
17077 }
17078 else {
17079 if (currentMarker === desiredMarker) {
17080 if (!Array.isArray(stylingKey)) {
17081 stylingKey = stylingKey === undefined ? [] : ['', stylingKey];
17082 }
17083 keyValueArraySet(stylingKey, item, isClassBased ? true : attrs[++i]);
17084 }
17085 }
17086 }
17087 }
17088 return stylingKey === undefined ? null : stylingKey;
17089}
17090/**
17091 * Convert user input to `KeyValueArray`.
17092 *
17093 * This function takes user input which could be `string`, Object literal, or iterable and converts
17094 * it into a consistent representation. The output of this is `KeyValueArray` (which is an array
17095 * where
17096 * even indexes contain keys and odd indexes contain values for those keys).
17097 *
17098 * The advantage of converting to `KeyValueArray` is that we can perform diff in an input
17099 * independent
17100 * way.
17101 * (ie we can compare `foo bar` to `['bar', 'baz'] and determine a set of changes which need to be
17102 * applied)
17103 *
17104 * The fact that `KeyValueArray` is sorted is very important because it allows us to compute the
17105 * difference in linear fashion without the need to allocate any additional data.
17106 *
17107 * For example if we kept this as a `Map` we would have to iterate over previous `Map` to determine
17108 * which values need to be deleted, over the new `Map` to determine additions, and we would have to
17109 * keep additional `Map` to keep track of duplicates or items which have not yet been visited.
17110 *
17111 * @param keyValueArraySet (See `keyValueArraySet` in "util/array_utils") Gets passed in as a
17112 * function so that `style` can be processed. This is done
17113 * for tree shaking purposes.
17114 * @param stringParser The parser is passed in so that it will be tree shakable. See
17115 * `styleStringParser` and `classStringParser`
17116 * @param value The value to parse/convert to `KeyValueArray`
17117 */
17118function toStylingKeyValueArray(keyValueArraySet, stringParser, value) {
17119 if (value == null /*|| value === undefined */ || value === '')
17120 return EMPTY_ARRAY;
17121 const styleKeyValueArray = [];
17122 const unwrappedValue = unwrapSafeValue(value);
17123 if (Array.isArray(unwrappedValue)) {
17124 for (let i = 0; i < unwrappedValue.length; i++) {
17125 keyValueArraySet(styleKeyValueArray, unwrappedValue[i], true);
17126 }
17127 }
17128 else if (typeof unwrappedValue === 'object') {
17129 for (const key in unwrappedValue) {
17130 if (unwrappedValue.hasOwnProperty(key)) {
17131 keyValueArraySet(styleKeyValueArray, key, unwrappedValue[key]);
17132 }
17133 }
17134 }
17135 else if (typeof unwrappedValue === 'string') {
17136 stringParser(styleKeyValueArray, unwrappedValue);
17137 }
17138 else {
17139 ngDevMode &&
17140 throwError('Unsupported styling type ' + typeof unwrappedValue + ': ' + unwrappedValue);
17141 }
17142 return styleKeyValueArray;
17143}
17144/**
17145 * Set a `value` for a `key`.
17146 *
17147 * See: `keyValueArraySet` for details
17148 *
17149 * @param keyValueArray KeyValueArray to add to.
17150 * @param key Style key to add.
17151 * @param value The value to set.
17152 */
17153function styleKeyValueArraySet(keyValueArray, key, value) {
17154 keyValueArraySet(keyValueArray, key, unwrapSafeValue(value));
17155}
17156/**
17157 * Update map based styling.
17158 *
17159 * Map based styling could be anything which contains more than one binding. For example `string`,
17160 * or object literal. Dealing with all of these types would complicate the logic so
17161 * instead this function expects that the complex input is first converted into normalized
17162 * `KeyValueArray`. The advantage of normalization is that we get the values sorted, which makes it
17163 * very cheap to compute deltas between the previous and current value.
17164 *
17165 * @param tView Associated `TView.data` contains the linked list of binding priorities.
17166 * @param tNode `TNode` where the binding is located.
17167 * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
17168 * @param renderer Renderer to use if any updates.
17169 * @param oldKeyValueArray Previous value represented as `KeyValueArray`
17170 * @param newKeyValueArray Current value represented as `KeyValueArray`
17171 * @param isClassBased `true` if `class` (`false` if `style`)
17172 * @param bindingIndex Binding index of the binding.
17173 */
17174function updateStylingMap(tView, tNode, lView, renderer, oldKeyValueArray, newKeyValueArray, isClassBased, bindingIndex) {
17175 if (oldKeyValueArray === NO_CHANGE) {
17176 // On first execution the oldKeyValueArray is NO_CHANGE => treat it as empty KeyValueArray.
17177 oldKeyValueArray = EMPTY_ARRAY;
17178 }
17179 let oldIndex = 0;
17180 let newIndex = 0;
17181 let oldKey = 0 < oldKeyValueArray.length ? oldKeyValueArray[0] : null;
17182 let newKey = 0 < newKeyValueArray.length ? newKeyValueArray[0] : null;
17183 while (oldKey !== null || newKey !== null) {
17184 ngDevMode && assertLessThan(oldIndex, 999, 'Are we stuck in infinite loop?');
17185 ngDevMode && assertLessThan(newIndex, 999, 'Are we stuck in infinite loop?');
17186 const oldValue = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex + 1] : undefined;
17187 const newValue = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex + 1] : undefined;
17188 let setKey = null;
17189 let setValue = undefined;
17190 if (oldKey === newKey) {
17191 // UPDATE: Keys are equal => new value is overwriting old value.
17192 oldIndex += 2;
17193 newIndex += 2;
17194 if (oldValue !== newValue) {
17195 setKey = newKey;
17196 setValue = newValue;
17197 }
17198 }
17199 else if (newKey === null || oldKey !== null && oldKey < newKey) {
17200 // DELETE: oldKey key is missing or we did not find the oldKey in the newValue
17201 // (because the keyValueArray is sorted and `newKey` is found later alphabetically).
17202 // `"background" < "color"` so we need to delete `"background"` because it is not found in the
17203 // new array.
17204 oldIndex += 2;
17205 setKey = oldKey;
17206 }
17207 else {
17208 // CREATE: newKey's is earlier alphabetically than oldKey's (or no oldKey) => we have new key.
17209 // `"color" > "background"` so we need to add `color` because it is in new array but not in
17210 // old array.
17211 ngDevMode && assertDefined(newKey, 'Expecting to have a valid key');
17212 newIndex += 2;
17213 setKey = newKey;
17214 setValue = newValue;
17215 }
17216 if (setKey !== null) {
17217 updateStyling(tView, tNode, lView, renderer, setKey, setValue, isClassBased, bindingIndex);
17218 }
17219 oldKey = oldIndex < oldKeyValueArray.length ? oldKeyValueArray[oldIndex] : null;
17220 newKey = newIndex < newKeyValueArray.length ? newKeyValueArray[newIndex] : null;
17221 }
17222}
17223/**
17224 * Update a simple (property name) styling.
17225 *
17226 * This function takes `prop` and updates the DOM to that value. The function takes the binding
17227 * value as well as binding priority into consideration to determine which value should be written
17228 * to DOM. (For example it may be determined that there is a higher priority overwrite which blocks
17229 * the DOM write, or if the value goes to `undefined` a lower priority overwrite may be consulted.)
17230 *
17231 * @param tView Associated `TView.data` contains the linked list of binding priorities.
17232 * @param tNode `TNode` where the binding is located.
17233 * @param lView `LView` contains the values associated with other styling binding at this `TNode`.
17234 * @param renderer Renderer to use if any updates.
17235 * @param prop Either style property name or a class name.
17236 * @param value Either style value for `prop` or `true`/`false` if `prop` is class.
17237 * @param isClassBased `true` if `class` (`false` if `style`)
17238 * @param bindingIndex Binding index of the binding.
17239 */
17240function updateStyling(tView, tNode, lView, renderer, prop, value, isClassBased, bindingIndex) {
17241 if (!(tNode.type & 3 /* AnyRNode */)) {
17242 // It is possible to have styling on non-elements (such as ng-container).
17243 // This is rare, but it does happen. In such a case, just ignore the binding.
17244 return;
17245 }
17246 const tData = tView.data;
17247 const tRange = tData[bindingIndex + 1];
17248 const higherPriorityValue = getTStylingRangeNextDuplicate(tRange) ?
17249 findStylingValue(tData, tNode, lView, prop, getTStylingRangeNext(tRange), isClassBased) :
17250 undefined;
17251 if (!isStylingValuePresent(higherPriorityValue)) {
17252 // We don't have a next duplicate, or we did not find a duplicate value.
17253 if (!isStylingValuePresent(value)) {
17254 // We should delete current value or restore to lower priority value.
17255 if (getTStylingRangePrevDuplicate(tRange)) {
17256 // We have a possible prev duplicate, let's retrieve it.
17257 value = findStylingValue(tData, null, lView, prop, bindingIndex, isClassBased);
17258 }
17259 }
17260 const rNode = getNativeByIndex(getSelectedIndex(), lView);
17261 applyStyling(renderer, isClassBased, rNode, prop, value);
17262 }
17263}
17264/**
17265 * Search for styling value with higher priority which is overwriting current value, or a
17266 * value of lower priority to which we should fall back if the value is `undefined`.
17267 *
17268 * When value is being applied at a location, related values need to be consulted.
17269 * - If there is a higher priority binding, we should be using that one instead.
17270 * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp1`
17271 * requires that we check `exp2` to see if it is set to value other than `undefined`.
17272 * - If there is a lower priority binding and we are changing to `undefined`
17273 * For example `<div [style]="{color:exp1}" [style.color]="exp2">` change to `exp2` to
17274 * `undefined` requires that we check `exp1` (and static values) and use that as new value.
17275 *
17276 * NOTE: The styling stores two values.
17277 * 1. The raw value which came from the application is stored at `index + 0` location. (This value
17278 * is used for dirty checking).
17279 * 2. The normalized value is stored at `index + 1`.
17280 *
17281 * @param tData `TData` used for traversing the priority.
17282 * @param tNode `TNode` to use for resolving static styling. Also controls search direction.
17283 * - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
17284 * If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
17285 * - `null` search prev and go all the way to end. Return last value where
17286 * `isStylingValuePresent(value)` is true.
17287 * @param lView `LView` used for retrieving the actual values.
17288 * @param prop Property which we are interested in.
17289 * @param index Starting index in the linked list of styling bindings where the search should start.
17290 * @param isClassBased `true` if `class` (`false` if `style`)
17291 */
17292function findStylingValue(tData, tNode, lView, prop, index, isClassBased) {
17293 // `TNode` to use for resolving static styling. Also controls search direction.
17294 // - `TNode` search next and quit as soon as `isStylingValuePresent(value)` is true.
17295 // If no value found consult `tNode.residualStyle`/`tNode.residualClass` for default value.
17296 // - `null` search prev and go all the way to end. Return last value where
17297 // `isStylingValuePresent(value)` is true.
17298 const isPrevDirection = tNode === null;
17299 let value = undefined;
17300 while (index > 0) {
17301 const rawKey = tData[index];
17302 const containsStatics = Array.isArray(rawKey);
17303 // Unwrap the key if we contain static values.
17304 const key = containsStatics ? rawKey[1] : rawKey;
17305 const isStylingMap = key === null;
17306 let valueAtLViewIndex = lView[index + 1];
17307 if (valueAtLViewIndex === NO_CHANGE) {
17308 // In firstUpdatePass the styling instructions create a linked list of styling.
17309 // On subsequent passes it is possible for a styling instruction to try to read a binding
17310 // which
17311 // has not yet executed. In that case we will find `NO_CHANGE` and we should assume that
17312 // we have `undefined` (or empty array in case of styling-map instruction) instead. This
17313 // allows the resolution to apply the value (which may later be overwritten when the
17314 // binding actually executes.)
17315 valueAtLViewIndex = isStylingMap ? EMPTY_ARRAY : undefined;
17316 }
17317 let currentValue = isStylingMap ? keyValueArrayGet(valueAtLViewIndex, prop) :
17318 key === prop ? valueAtLViewIndex : undefined;
17319 if (containsStatics && !isStylingValuePresent(currentValue)) {
17320 currentValue = keyValueArrayGet(rawKey, prop);
17321 }
17322 if (isStylingValuePresent(currentValue)) {
17323 value = currentValue;
17324 if (isPrevDirection) {
17325 return value;
17326 }
17327 }
17328 const tRange = tData[index + 1];
17329 index = isPrevDirection ? getTStylingRangePrev(tRange) : getTStylingRangeNext(tRange);
17330 }
17331 if (tNode !== null) {
17332 // in case where we are going in next direction AND we did not find anything, we need to
17333 // consult residual styling
17334 let residual = isClassBased ? tNode.residualClasses : tNode.residualStyles;
17335 if (residual != null /** OR residual !=== undefined */) {
17336 value = keyValueArrayGet(residual, prop);
17337 }
17338 }
17339 return value;
17340}
17341/**
17342 * Determines if the binding value should be used (or if the value is 'undefined' and hence priority
17343 * resolution should be used.)
17344 *
17345 * @param value Binding style value.
17346 */
17347function isStylingValuePresent(value) {
17348 // Currently only `undefined` value is considered non-binding. That is `undefined` says I don't
17349 // have an opinion as to what this binding should be and you should consult other bindings by
17350 // priority to determine the valid value.
17351 // This is extracted into a single function so that we have a single place to control this.
17352 return value !== undefined;
17353}
17354/**
17355 * Normalizes and/or adds a suffix to the value.
17356 *
17357 * If value is `null`/`undefined` no suffix is added
17358 * @param value
17359 * @param suffix
17360 */
17361function normalizeSuffix(value, suffix) {
17362 if (value == null /** || value === undefined */) {
17363 // do nothing
17364 }
17365 else if (typeof suffix === 'string') {
17366 value = value + suffix;
17367 }
17368 else if (typeof value === 'object') {
17369 value = stringify(unwrapSafeValue(value));
17370 }
17371 return value;
17372}
17373/**
17374 * Tests if the `TNode` has input shadow.
17375 *
17376 * An input shadow is when a directive steals (shadows) the input by using `@Input('style')` or
17377 * `@Input('class')` as input.
17378 *
17379 * @param tNode `TNode` which we would like to see if it has shadow.
17380 * @param isClassBased `true` if `class` (`false` if `style`)
17381 */
17382function hasStylingInputShadow(tNode, isClassBased) {
17383 return (tNode.flags & (isClassBased ? 16 /* hasClassInput */ : 32 /* hasStyleInput */)) !== 0;
17384}
17385
17386/**
17387 * @license
17388 * Copyright Google LLC All Rights Reserved.
17389 *
17390 * Use of this source code is governed by an MIT-style license that can be
17391 * found in the LICENSE file at https://angular.io/license
17392 */
17393/**
17394 * Create static text node
17395 *
17396 * @param index Index of the node in the data array
17397 * @param value Static string value to write.
17398 *
17399 * @codeGenApi
17400 */
17401function ɵɵtext(index, value = '') {
17402 const lView = getLView();
17403 const tView = getTView();
17404 const adjustedIndex = index + HEADER_OFFSET;
17405 ngDevMode &&
17406 assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings');
17407 ngDevMode && assertIndexInRange(lView, adjustedIndex);
17408 const tNode = tView.firstCreatePass ?
17409 getOrCreateTNode(tView, adjustedIndex, 1 /* Text */, value, null) :
17410 tView.data[adjustedIndex];
17411 const textNative = lView[adjustedIndex] = createTextNode(lView[RENDERER], value);
17412 appendChild(tView, lView, textNative, tNode);
17413 // Text nodes are self closing.
17414 setCurrentTNode(tNode, false);
17415}
17416
17417/**
17418 * @license
17419 * Copyright Google LLC All Rights Reserved.
17420 *
17421 * Use of this source code is governed by an MIT-style license that can be
17422 * found in the LICENSE file at https://angular.io/license
17423 */
17424/**
17425 *
17426 * Update text content with a lone bound value
17427 *
17428 * Used when a text node has 1 interpolated value in it, an no additional text
17429 * surrounds that interpolated value:
17430 *
17431 * ```html
17432 * <div>{{v0}}</div>
17433 * ```
17434 *
17435 * Its compiled representation is:
17436 *
17437 * ```ts
17438 * ɵɵtextInterpolate(v0);
17439 * ```
17440 * @returns itself, so that it may be chained.
17441 * @see textInterpolateV
17442 * @codeGenApi
17443 */
17444function ɵɵtextInterpolate(v0) {
17445 ɵɵtextInterpolate1('', v0, '');
17446 return ɵɵtextInterpolate;
17447}
17448/**
17449 *
17450 * Update text content with single bound value surrounded by other text.
17451 *
17452 * Used when a text node has 1 interpolated value in it:
17453 *
17454 * ```html
17455 * <div>prefix{{v0}}suffix</div>
17456 * ```
17457 *
17458 * Its compiled representation is:
17459 *
17460 * ```ts
17461 * ɵɵtextInterpolate1('prefix', v0, 'suffix');
17462 * ```
17463 * @returns itself, so that it may be chained.
17464 * @see textInterpolateV
17465 * @codeGenApi
17466 */
17467function ɵɵtextInterpolate1(prefix, v0, suffix) {
17468 const lView = getLView();
17469 const interpolated = interpolation1(lView, prefix, v0, suffix);
17470 if (interpolated !== NO_CHANGE) {
17471 textBindingInternal(lView, getSelectedIndex(), interpolated);
17472 }
17473 return ɵɵtextInterpolate1;
17474}
17475/**
17476 *
17477 * Update text content with 2 bound values surrounded by other text.
17478 *
17479 * Used when a text node has 2 interpolated values in it:
17480 *
17481 * ```html
17482 * <div>prefix{{v0}}-{{v1}}suffix</div>
17483 * ```
17484 *
17485 * Its compiled representation is:
17486 *
17487 * ```ts
17488 * ɵɵtextInterpolate2('prefix', v0, '-', v1, 'suffix');
17489 * ```
17490 * @returns itself, so that it may be chained.
17491 * @see textInterpolateV
17492 * @codeGenApi
17493 */
17494function ɵɵtextInterpolate2(prefix, v0, i0, v1, suffix) {
17495 const lView = getLView();
17496 const interpolated = interpolation2(lView, prefix, v0, i0, v1, suffix);
17497 if (interpolated !== NO_CHANGE) {
17498 textBindingInternal(lView, getSelectedIndex(), interpolated);
17499 }
17500 return ɵɵtextInterpolate2;
17501}
17502/**
17503 *
17504 * Update text content with 3 bound values surrounded by other text.
17505 *
17506 * Used when a text node has 3 interpolated values in it:
17507 *
17508 * ```html
17509 * <div>prefix{{v0}}-{{v1}}-{{v2}}suffix</div>
17510 * ```
17511 *
17512 * Its compiled representation is:
17513 *
17514 * ```ts
17515 * ɵɵtextInterpolate3(
17516 * 'prefix', v0, '-', v1, '-', v2, 'suffix');
17517 * ```
17518 * @returns itself, so that it may be chained.
17519 * @see textInterpolateV
17520 * @codeGenApi
17521 */
17522function ɵɵtextInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
17523 const lView = getLView();
17524 const interpolated = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
17525 if (interpolated !== NO_CHANGE) {
17526 textBindingInternal(lView, getSelectedIndex(), interpolated);
17527 }
17528 return ɵɵtextInterpolate3;
17529}
17530/**
17531 *
17532 * Update text content with 4 bound values surrounded by other text.
17533 *
17534 * Used when a text node has 4 interpolated values in it:
17535 *
17536 * ```html
17537 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix</div>
17538 * ```
17539 *
17540 * Its compiled representation is:
17541 *
17542 * ```ts
17543 * ɵɵtextInterpolate4(
17544 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
17545 * ```
17546 * @returns itself, so that it may be chained.
17547 * @see ɵɵtextInterpolateV
17548 * @codeGenApi
17549 */
17550function ɵɵtextInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
17551 const lView = getLView();
17552 const interpolated = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
17553 if (interpolated !== NO_CHANGE) {
17554 textBindingInternal(lView, getSelectedIndex(), interpolated);
17555 }
17556 return ɵɵtextInterpolate4;
17557}
17558/**
17559 *
17560 * Update text content with 5 bound values surrounded by other text.
17561 *
17562 * Used when a text node has 5 interpolated values in it:
17563 *
17564 * ```html
17565 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix</div>
17566 * ```
17567 *
17568 * Its compiled representation is:
17569 *
17570 * ```ts
17571 * ɵɵtextInterpolate5(
17572 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
17573 * ```
17574 * @returns itself, so that it may be chained.
17575 * @see textInterpolateV
17576 * @codeGenApi
17577 */
17578function ɵɵtextInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
17579 const lView = getLView();
17580 const interpolated = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
17581 if (interpolated !== NO_CHANGE) {
17582 textBindingInternal(lView, getSelectedIndex(), interpolated);
17583 }
17584 return ɵɵtextInterpolate5;
17585}
17586/**
17587 *
17588 * Update text content with 6 bound values surrounded by other text.
17589 *
17590 * Used when a text node has 6 interpolated values in it:
17591 *
17592 * ```html
17593 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix</div>
17594 * ```
17595 *
17596 * Its compiled representation is:
17597 *
17598 * ```ts
17599 * ɵɵtextInterpolate6(
17600 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
17601 * ```
17602 *
17603 * @param i4 Static value used for concatenation only.
17604 * @param v5 Value checked for change. @returns itself, so that it may be chained.
17605 * @see textInterpolateV
17606 * @codeGenApi
17607 */
17608function ɵɵtextInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
17609 const lView = getLView();
17610 const interpolated = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
17611 if (interpolated !== NO_CHANGE) {
17612 textBindingInternal(lView, getSelectedIndex(), interpolated);
17613 }
17614 return ɵɵtextInterpolate6;
17615}
17616/**
17617 *
17618 * Update text content with 7 bound values surrounded by other text.
17619 *
17620 * Used when a text node has 7 interpolated values in it:
17621 *
17622 * ```html
17623 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix</div>
17624 * ```
17625 *
17626 * Its compiled representation is:
17627 *
17628 * ```ts
17629 * ɵɵtextInterpolate7(
17630 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
17631 * ```
17632 * @returns itself, so that it may be chained.
17633 * @see textInterpolateV
17634 * @codeGenApi
17635 */
17636function ɵɵtextInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
17637 const lView = getLView();
17638 const interpolated = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
17639 if (interpolated !== NO_CHANGE) {
17640 textBindingInternal(lView, getSelectedIndex(), interpolated);
17641 }
17642 return ɵɵtextInterpolate7;
17643}
17644/**
17645 *
17646 * Update text content with 8 bound values surrounded by other text.
17647 *
17648 * Used when a text node has 8 interpolated values in it:
17649 *
17650 * ```html
17651 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix</div>
17652 * ```
17653 *
17654 * Its compiled representation is:
17655 *
17656 * ```ts
17657 * ɵɵtextInterpolate8(
17658 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
17659 * ```
17660 * @returns itself, so that it may be chained.
17661 * @see textInterpolateV
17662 * @codeGenApi
17663 */
17664function ɵɵtextInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
17665 const lView = getLView();
17666 const interpolated = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
17667 if (interpolated !== NO_CHANGE) {
17668 textBindingInternal(lView, getSelectedIndex(), interpolated);
17669 }
17670 return ɵɵtextInterpolate8;
17671}
17672/**
17673 * Update text content with 9 or more bound values other surrounded by text.
17674 *
17675 * Used when the number of interpolated values exceeds 8.
17676 *
17677 * ```html
17678 * <div>prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix</div>
17679 * ```
17680 *
17681 * Its compiled representation is:
17682 *
17683 * ```ts
17684 * ɵɵtextInterpolateV(
17685 * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
17686 * 'suffix']);
17687 * ```
17688 *.
17689 * @param values The collection of values and the strings in between those values, beginning with
17690 * a string prefix and ending with a string suffix.
17691 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
17692 *
17693 * @returns itself, so that it may be chained.
17694 * @codeGenApi
17695 */
17696function ɵɵtextInterpolateV(values) {
17697 const lView = getLView();
17698 const interpolated = interpolationV(lView, values);
17699 if (interpolated !== NO_CHANGE) {
17700 textBindingInternal(lView, getSelectedIndex(), interpolated);
17701 }
17702 return ɵɵtextInterpolateV;
17703}
17704
17705/**
17706 * @license
17707 * Copyright Google LLC All Rights Reserved.
17708 *
17709 * Use of this source code is governed by an MIT-style license that can be
17710 * found in the LICENSE file at https://angular.io/license
17711 */
17712/**
17713 *
17714 * Update an interpolated class on an element with single bound value surrounded by text.
17715 *
17716 * Used when the value passed to a property has 1 interpolated value in it:
17717 *
17718 * ```html
17719 * <div class="prefix{{v0}}suffix"></div>
17720 * ```
17721 *
17722 * Its compiled representation is:
17723 *
17724 * ```ts
17725 * ɵɵclassMapInterpolate1('prefix', v0, 'suffix');
17726 * ```
17727 *
17728 * @param prefix Static value used for concatenation only.
17729 * @param v0 Value checked for change.
17730 * @param suffix Static value used for concatenation only.
17731 * @codeGenApi
17732 */
17733function ɵɵclassMapInterpolate1(prefix, v0, suffix) {
17734 const lView = getLView();
17735 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
17736 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17737}
17738/**
17739 *
17740 * Update an interpolated class on an element with 2 bound values surrounded by text.
17741 *
17742 * Used when the value passed to a property has 2 interpolated values in it:
17743 *
17744 * ```html
17745 * <div class="prefix{{v0}}-{{v1}}suffix"></div>
17746 * ```
17747 *
17748 * Its compiled representation is:
17749 *
17750 * ```ts
17751 * ɵɵclassMapInterpolate2('prefix', v0, '-', v1, 'suffix');
17752 * ```
17753 *
17754 * @param prefix Static value used for concatenation only.
17755 * @param v0 Value checked for change.
17756 * @param i0 Static value used for concatenation only.
17757 * @param v1 Value checked for change.
17758 * @param suffix Static value used for concatenation only.
17759 * @codeGenApi
17760 */
17761function ɵɵclassMapInterpolate2(prefix, v0, i0, v1, suffix) {
17762 const lView = getLView();
17763 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
17764 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17765}
17766/**
17767 *
17768 * Update an interpolated class on an element with 3 bound values surrounded by text.
17769 *
17770 * Used when the value passed to a property has 3 interpolated values in it:
17771 *
17772 * ```html
17773 * <div class="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
17774 * ```
17775 *
17776 * Its compiled representation is:
17777 *
17778 * ```ts
17779 * ɵɵclassMapInterpolate3(
17780 * 'prefix', v0, '-', v1, '-', v2, 'suffix');
17781 * ```
17782 *
17783 * @param prefix Static value used for concatenation only.
17784 * @param v0 Value checked for change.
17785 * @param i0 Static value used for concatenation only.
17786 * @param v1 Value checked for change.
17787 * @param i1 Static value used for concatenation only.
17788 * @param v2 Value checked for change.
17789 * @param suffix Static value used for concatenation only.
17790 * @codeGenApi
17791 */
17792function ɵɵclassMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
17793 const lView = getLView();
17794 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
17795 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17796}
17797/**
17798 *
17799 * Update an interpolated class on an element with 4 bound values surrounded by text.
17800 *
17801 * Used when the value passed to a property has 4 interpolated values in it:
17802 *
17803 * ```html
17804 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
17805 * ```
17806 *
17807 * Its compiled representation is:
17808 *
17809 * ```ts
17810 * ɵɵclassMapInterpolate4(
17811 * 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
17812 * ```
17813 *
17814 * @param prefix Static value used for concatenation only.
17815 * @param v0 Value checked for change.
17816 * @param i0 Static value used for concatenation only.
17817 * @param v1 Value checked for change.
17818 * @param i1 Static value used for concatenation only.
17819 * @param v2 Value checked for change.
17820 * @param i2 Static value used for concatenation only.
17821 * @param v3 Value checked for change.
17822 * @param suffix Static value used for concatenation only.
17823 * @codeGenApi
17824 */
17825function ɵɵclassMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
17826 const lView = getLView();
17827 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
17828 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17829}
17830/**
17831 *
17832 * Update an interpolated class on an element with 5 bound values surrounded by text.
17833 *
17834 * Used when the value passed to a property has 5 interpolated values in it:
17835 *
17836 * ```html
17837 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
17838 * ```
17839 *
17840 * Its compiled representation is:
17841 *
17842 * ```ts
17843 * ɵɵclassMapInterpolate5(
17844 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
17845 * ```
17846 *
17847 * @param prefix Static value used for concatenation only.
17848 * @param v0 Value checked for change.
17849 * @param i0 Static value used for concatenation only.
17850 * @param v1 Value checked for change.
17851 * @param i1 Static value used for concatenation only.
17852 * @param v2 Value checked for change.
17853 * @param i2 Static value used for concatenation only.
17854 * @param v3 Value checked for change.
17855 * @param i3 Static value used for concatenation only.
17856 * @param v4 Value checked for change.
17857 * @param suffix Static value used for concatenation only.
17858 * @codeGenApi
17859 */
17860function ɵɵclassMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
17861 const lView = getLView();
17862 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
17863 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17864}
17865/**
17866 *
17867 * Update an interpolated class on an element with 6 bound values surrounded by text.
17868 *
17869 * Used when the value passed to a property has 6 interpolated values in it:
17870 *
17871 * ```html
17872 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
17873 * ```
17874 *
17875 * Its compiled representation is:
17876 *
17877 * ```ts
17878 * ɵɵclassMapInterpolate6(
17879 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
17880 * ```
17881 *
17882 * @param prefix Static value used for concatenation only.
17883 * @param v0 Value checked for change.
17884 * @param i0 Static value used for concatenation only.
17885 * @param v1 Value checked for change.
17886 * @param i1 Static value used for concatenation only.
17887 * @param v2 Value checked for change.
17888 * @param i2 Static value used for concatenation only.
17889 * @param v3 Value checked for change.
17890 * @param i3 Static value used for concatenation only.
17891 * @param v4 Value checked for change.
17892 * @param i4 Static value used for concatenation only.
17893 * @param v5 Value checked for change.
17894 * @param suffix Static value used for concatenation only.
17895 * @codeGenApi
17896 */
17897function ɵɵclassMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
17898 const lView = getLView();
17899 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
17900 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17901}
17902/**
17903 *
17904 * Update an interpolated class on an element with 7 bound values surrounded by text.
17905 *
17906 * Used when the value passed to a property has 7 interpolated values in it:
17907 *
17908 * ```html
17909 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
17910 * ```
17911 *
17912 * Its compiled representation is:
17913 *
17914 * ```ts
17915 * ɵɵclassMapInterpolate7(
17916 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
17917 * ```
17918 *
17919 * @param prefix Static value used for concatenation only.
17920 * @param v0 Value checked for change.
17921 * @param i0 Static value used for concatenation only.
17922 * @param v1 Value checked for change.
17923 * @param i1 Static value used for concatenation only.
17924 * @param v2 Value checked for change.
17925 * @param i2 Static value used for concatenation only.
17926 * @param v3 Value checked for change.
17927 * @param i3 Static value used for concatenation only.
17928 * @param v4 Value checked for change.
17929 * @param i4 Static value used for concatenation only.
17930 * @param v5 Value checked for change.
17931 * @param i5 Static value used for concatenation only.
17932 * @param v6 Value checked for change.
17933 * @param suffix Static value used for concatenation only.
17934 * @codeGenApi
17935 */
17936function ɵɵclassMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
17937 const lView = getLView();
17938 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
17939 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17940}
17941/**
17942 *
17943 * Update an interpolated class on an element with 8 bound values surrounded by text.
17944 *
17945 * Used when the value passed to a property has 8 interpolated values in it:
17946 *
17947 * ```html
17948 * <div class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
17949 * ```
17950 *
17951 * Its compiled representation is:
17952 *
17953 * ```ts
17954 * ɵɵclassMapInterpolate8(
17955 * 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, 'suffix');
17956 * ```
17957 *
17958 * @param prefix Static value used for concatenation only.
17959 * @param v0 Value checked for change.
17960 * @param i0 Static value used for concatenation only.
17961 * @param v1 Value checked for change.
17962 * @param i1 Static value used for concatenation only.
17963 * @param v2 Value checked for change.
17964 * @param i2 Static value used for concatenation only.
17965 * @param v3 Value checked for change.
17966 * @param i3 Static value used for concatenation only.
17967 * @param v4 Value checked for change.
17968 * @param i4 Static value used for concatenation only.
17969 * @param v5 Value checked for change.
17970 * @param i5 Static value used for concatenation only.
17971 * @param v6 Value checked for change.
17972 * @param i6 Static value used for concatenation only.
17973 * @param v7 Value checked for change.
17974 * @param suffix Static value used for concatenation only.
17975 * @codeGenApi
17976 */
17977function ɵɵclassMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
17978 const lView = getLView();
17979 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
17980 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
17981}
17982/**
17983 * Update an interpolated class on an element with 9 or more bound values surrounded by text.
17984 *
17985 * Used when the number of interpolated values exceeds 8.
17986 *
17987 * ```html
17988 * <div
17989 * class="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix"></div>
17990 * ```
17991 *
17992 * Its compiled representation is:
17993 *
17994 * ```ts
17995 * ɵɵclassMapInterpolateV(
17996 * ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
17997 * 'suffix']);
17998 * ```
17999 *.
18000 * @param values The collection of values and the strings in-between those values, beginning with
18001 * a string prefix and ending with a string suffix.
18002 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
18003 * @codeGenApi
18004 */
18005function ɵɵclassMapInterpolateV(values) {
18006 const lView = getLView();
18007 const interpolatedValue = interpolationV(lView, values);
18008 checkStylingMap(keyValueArraySet, classStringParser, interpolatedValue, true);
18009}
18010
18011/**
18012 * @license
18013 * Copyright Google LLC All Rights Reserved.
18014 *
18015 * Use of this source code is governed by an MIT-style license that can be
18016 * found in the LICENSE file at https://angular.io/license
18017 */
18018/**
18019 *
18020 * Update an interpolated style on an element with single bound value surrounded by text.
18021 *
18022 * Used when the value passed to a property has 1 interpolated value in it:
18023 *
18024 * ```html
18025 * <div style="key: {{v0}}suffix"></div>
18026 * ```
18027 *
18028 * Its compiled representation is:
18029 *
18030 * ```ts
18031 * ɵɵstyleMapInterpolate1('key: ', v0, 'suffix');
18032 * ```
18033 *
18034 * @param prefix Static value used for concatenation only.
18035 * @param v0 Value checked for change.
18036 * @param suffix Static value used for concatenation only.
18037 * @codeGenApi
18038 */
18039function ɵɵstyleMapInterpolate1(prefix, v0, suffix) {
18040 const lView = getLView();
18041 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
18042 ɵɵstyleMap(interpolatedValue);
18043}
18044/**
18045 *
18046 * Update an interpolated style on an element with 2 bound values surrounded by text.
18047 *
18048 * Used when the value passed to a property has 2 interpolated values in it:
18049 *
18050 * ```html
18051 * <div style="key: {{v0}}; key1: {{v1}}suffix"></div>
18052 * ```
18053 *
18054 * Its compiled representation is:
18055 *
18056 * ```ts
18057 * ɵɵstyleMapInterpolate2('key: ', v0, '; key1: ', v1, 'suffix');
18058 * ```
18059 *
18060 * @param prefix Static value used for concatenation only.
18061 * @param v0 Value checked for change.
18062 * @param i0 Static value used for concatenation only.
18063 * @param v1 Value checked for change.
18064 * @param suffix Static value used for concatenation only.
18065 * @codeGenApi
18066 */
18067function ɵɵstyleMapInterpolate2(prefix, v0, i0, v1, suffix) {
18068 const lView = getLView();
18069 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
18070 ɵɵstyleMap(interpolatedValue);
18071}
18072/**
18073 *
18074 * Update an interpolated style on an element with 3 bound values surrounded by text.
18075 *
18076 * Used when the value passed to a property has 3 interpolated values in it:
18077 *
18078 * ```html
18079 * <div style="key: {{v0}}; key2: {{v1}}; key2: {{v2}}suffix"></div>
18080 * ```
18081 *
18082 * Its compiled representation is:
18083 *
18084 * ```ts
18085 * ɵɵstyleMapInterpolate3(
18086 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, 'suffix');
18087 * ```
18088 *
18089 * @param prefix Static value used for concatenation only.
18090 * @param v0 Value checked for change.
18091 * @param i0 Static value used for concatenation only.
18092 * @param v1 Value checked for change.
18093 * @param i1 Static value used for concatenation only.
18094 * @param v2 Value checked for change.
18095 * @param suffix Static value used for concatenation only.
18096 * @codeGenApi
18097 */
18098function ɵɵstyleMapInterpolate3(prefix, v0, i0, v1, i1, v2, suffix) {
18099 const lView = getLView();
18100 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
18101 ɵɵstyleMap(interpolatedValue);
18102}
18103/**
18104 *
18105 * Update an interpolated style on an element with 4 bound values surrounded by text.
18106 *
18107 * Used when the value passed to a property has 4 interpolated values in it:
18108 *
18109 * ```html
18110 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}suffix"></div>
18111 * ```
18112 *
18113 * Its compiled representation is:
18114 *
18115 * ```ts
18116 * ɵɵstyleMapInterpolate4(
18117 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, 'suffix');
18118 * ```
18119 *
18120 * @param prefix Static value used for concatenation only.
18121 * @param v0 Value checked for change.
18122 * @param i0 Static value used for concatenation only.
18123 * @param v1 Value checked for change.
18124 * @param i1 Static value used for concatenation only.
18125 * @param v2 Value checked for change.
18126 * @param i2 Static value used for concatenation only.
18127 * @param v3 Value checked for change.
18128 * @param suffix Static value used for concatenation only.
18129 * @codeGenApi
18130 */
18131function ɵɵstyleMapInterpolate4(prefix, v0, i0, v1, i1, v2, i2, v3, suffix) {
18132 const lView = getLView();
18133 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
18134 ɵɵstyleMap(interpolatedValue);
18135}
18136/**
18137 *
18138 * Update an interpolated style on an element with 5 bound values surrounded by text.
18139 *
18140 * Used when the value passed to a property has 5 interpolated values in it:
18141 *
18142 * ```html
18143 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}suffix"></div>
18144 * ```
18145 *
18146 * Its compiled representation is:
18147 *
18148 * ```ts
18149 * ɵɵstyleMapInterpolate5(
18150 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, 'suffix');
18151 * ```
18152 *
18153 * @param prefix Static value used for concatenation only.
18154 * @param v0 Value checked for change.
18155 * @param i0 Static value used for concatenation only.
18156 * @param v1 Value checked for change.
18157 * @param i1 Static value used for concatenation only.
18158 * @param v2 Value checked for change.
18159 * @param i2 Static value used for concatenation only.
18160 * @param v3 Value checked for change.
18161 * @param i3 Static value used for concatenation only.
18162 * @param v4 Value checked for change.
18163 * @param suffix Static value used for concatenation only.
18164 * @codeGenApi
18165 */
18166function ɵɵstyleMapInterpolate5(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix) {
18167 const lView = getLView();
18168 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
18169 ɵɵstyleMap(interpolatedValue);
18170}
18171/**
18172 *
18173 * Update an interpolated style on an element with 6 bound values surrounded by text.
18174 *
18175 * Used when the value passed to a property has 6 interpolated values in it:
18176 *
18177 * ```html
18178 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}};
18179 * key5: {{v5}}suffix"></div>
18180 * ```
18181 *
18182 * Its compiled representation is:
18183 *
18184 * ```ts
18185 * ɵɵstyleMapInterpolate6(
18186 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18187 * 'suffix');
18188 * ```
18189 *
18190 * @param prefix Static value used for concatenation only.
18191 * @param v0 Value checked for change.
18192 * @param i0 Static value used for concatenation only.
18193 * @param v1 Value checked for change.
18194 * @param i1 Static value used for concatenation only.
18195 * @param v2 Value checked for change.
18196 * @param i2 Static value used for concatenation only.
18197 * @param v3 Value checked for change.
18198 * @param i3 Static value used for concatenation only.
18199 * @param v4 Value checked for change.
18200 * @param i4 Static value used for concatenation only.
18201 * @param v5 Value checked for change.
18202 * @param suffix Static value used for concatenation only.
18203 * @codeGenApi
18204 */
18205function ɵɵstyleMapInterpolate6(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix) {
18206 const lView = getLView();
18207 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
18208 ɵɵstyleMap(interpolatedValue);
18209}
18210/**
18211 *
18212 * Update an interpolated style on an element with 7 bound values surrounded by text.
18213 *
18214 * Used when the value passed to a property has 7 interpolated values in it:
18215 *
18216 * ```html
18217 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
18218 * key6: {{v6}}suffix"></div>
18219 * ```
18220 *
18221 * Its compiled representation is:
18222 *
18223 * ```ts
18224 * ɵɵstyleMapInterpolate7(
18225 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18226 * '; key6: ', v6, 'suffix');
18227 * ```
18228 *
18229 * @param prefix Static value used for concatenation only.
18230 * @param v0 Value checked for change.
18231 * @param i0 Static value used for concatenation only.
18232 * @param v1 Value checked for change.
18233 * @param i1 Static value used for concatenation only.
18234 * @param v2 Value checked for change.
18235 * @param i2 Static value used for concatenation only.
18236 * @param v3 Value checked for change.
18237 * @param i3 Static value used for concatenation only.
18238 * @param v4 Value checked for change.
18239 * @param i4 Static value used for concatenation only.
18240 * @param v5 Value checked for change.
18241 * @param i5 Static value used for concatenation only.
18242 * @param v6 Value checked for change.
18243 * @param suffix Static value used for concatenation only.
18244 * @codeGenApi
18245 */
18246function ɵɵstyleMapInterpolate7(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix) {
18247 const lView = getLView();
18248 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
18249 ɵɵstyleMap(interpolatedValue);
18250}
18251/**
18252 *
18253 * Update an interpolated style on an element with 8 bound values surrounded by text.
18254 *
18255 * Used when the value passed to a property has 8 interpolated values in it:
18256 *
18257 * ```html
18258 * <div style="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
18259 * key6: {{v6}}; key7: {{v7}}suffix"></div>
18260 * ```
18261 *
18262 * Its compiled representation is:
18263 *
18264 * ```ts
18265 * ɵɵstyleMapInterpolate8(
18266 * 'key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18267 * '; key6: ', v6, '; key7: ', v7, 'suffix');
18268 * ```
18269 *
18270 * @param prefix Static value used for concatenation only.
18271 * @param v0 Value checked for change.
18272 * @param i0 Static value used for concatenation only.
18273 * @param v1 Value checked for change.
18274 * @param i1 Static value used for concatenation only.
18275 * @param v2 Value checked for change.
18276 * @param i2 Static value used for concatenation only.
18277 * @param v3 Value checked for change.
18278 * @param i3 Static value used for concatenation only.
18279 * @param v4 Value checked for change.
18280 * @param i4 Static value used for concatenation only.
18281 * @param v5 Value checked for change.
18282 * @param i5 Static value used for concatenation only.
18283 * @param v6 Value checked for change.
18284 * @param i6 Static value used for concatenation only.
18285 * @param v7 Value checked for change.
18286 * @param suffix Static value used for concatenation only.
18287 * @codeGenApi
18288 */
18289function ɵɵstyleMapInterpolate8(prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix) {
18290 const lView = getLView();
18291 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
18292 ɵɵstyleMap(interpolatedValue);
18293}
18294/**
18295 * Update an interpolated style on an element with 9 or more bound values surrounded by text.
18296 *
18297 * Used when the number of interpolated values exceeds 8.
18298 *
18299 * ```html
18300 * <div
18301 * class="key: {{v0}}; key1: {{v1}}; key2: {{v2}}; key3: {{v3}}; key4: {{v4}}; key5: {{v5}};
18302 * key6: {{v6}}; key7: {{v7}}; key8: {{v8}}; key9: {{v9}}suffix"></div>
18303 * ```
18304 *
18305 * Its compiled representation is:
18306 *
18307 * ```ts
18308 * ɵɵstyleMapInterpolateV(
18309 * ['key: ', v0, '; key1: ', v1, '; key2: ', v2, '; key3: ', v3, '; key4: ', v4, '; key5: ', v5,
18310 * '; key6: ', v6, '; key7: ', v7, '; key8: ', v8, '; key9: ', v9, 'suffix']);
18311 * ```
18312 *.
18313 * @param values The collection of values and the strings in-between those values, beginning with
18314 * a string prefix and ending with a string suffix.
18315 * (e.g. `['prefix', value0, '; key2: ', value1, '; key2: ', value2, ..., value99, 'suffix']`)
18316 * @codeGenApi
18317 */
18318function ɵɵstyleMapInterpolateV(values) {
18319 const lView = getLView();
18320 const interpolatedValue = interpolationV(lView, values);
18321 ɵɵstyleMap(interpolatedValue);
18322}
18323
18324/**
18325 * @license
18326 * Copyright Google LLC All Rights Reserved.
18327 *
18328 * Use of this source code is governed by an MIT-style license that can be
18329 * found in the LICENSE file at https://angular.io/license
18330 */
18331/**
18332 *
18333 * Update an interpolated style property on an element with single bound value surrounded by text.
18334 *
18335 * Used when the value passed to a property has 1 interpolated value in it:
18336 *
18337 * ```html
18338 * <div style.color="prefix{{v0}}suffix"></div>
18339 * ```
18340 *
18341 * Its compiled representation is:
18342 *
18343 * ```ts
18344 * ɵɵstylePropInterpolate1(0, 'prefix', v0, 'suffix');
18345 * ```
18346 *
18347 * @param styleIndex Index of style to update. This index value refers to the
18348 * index of the style in the style bindings array that was passed into
18349 * `styling`.
18350 * @param prefix Static value used for concatenation only.
18351 * @param v0 Value checked for change.
18352 * @param suffix Static value used for concatenation only.
18353 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18354 * @returns itself, so that it may be chained.
18355 * @codeGenApi
18356 */
18357function ɵɵstylePropInterpolate1(prop, prefix, v0, suffix, valueSuffix) {
18358 const lView = getLView();
18359 const interpolatedValue = interpolation1(lView, prefix, v0, suffix);
18360 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18361 return ɵɵstylePropInterpolate1;
18362}
18363/**
18364 *
18365 * Update an interpolated style property on an element with 2 bound values surrounded by text.
18366 *
18367 * Used when the value passed to a property has 2 interpolated values in it:
18368 *
18369 * ```html
18370 * <div style.color="prefix{{v0}}-{{v1}}suffix"></div>
18371 * ```
18372 *
18373 * Its compiled representation is:
18374 *
18375 * ```ts
18376 * ɵɵstylePropInterpolate2(0, 'prefix', v0, '-', v1, 'suffix');
18377 * ```
18378 *
18379 * @param styleIndex Index of style to update. This index value refers to the
18380 * index of the style in the style bindings array that was passed into
18381 * `styling`.
18382 * @param prefix Static value used for concatenation only.
18383 * @param v0 Value checked for change.
18384 * @param i0 Static value used for concatenation only.
18385 * @param v1 Value checked for change.
18386 * @param suffix Static value used for concatenation only.
18387 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18388 * @returns itself, so that it may be chained.
18389 * @codeGenApi
18390 */
18391function ɵɵstylePropInterpolate2(prop, prefix, v0, i0, v1, suffix, valueSuffix) {
18392 const lView = getLView();
18393 const interpolatedValue = interpolation2(lView, prefix, v0, i0, v1, suffix);
18394 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18395 return ɵɵstylePropInterpolate2;
18396}
18397/**
18398 *
18399 * Update an interpolated style property on an element with 3 bound values surrounded by text.
18400 *
18401 * Used when the value passed to a property has 3 interpolated values in it:
18402 *
18403 * ```html
18404 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}suffix"></div>
18405 * ```
18406 *
18407 * Its compiled representation is:
18408 *
18409 * ```ts
18410 * ɵɵstylePropInterpolate3(0, 'prefix', v0, '-', v1, '-', v2, 'suffix');
18411 * ```
18412 *
18413 * @param styleIndex Index of style to update. This index value refers to the
18414 * index of the style in the style bindings array that was passed into
18415 * `styling`.
18416 * @param prefix Static value used for concatenation only.
18417 * @param v0 Value checked for change.
18418 * @param i0 Static value used for concatenation only.
18419 * @param v1 Value checked for change.
18420 * @param i1 Static value used for concatenation only.
18421 * @param v2 Value checked for change.
18422 * @param suffix Static value used for concatenation only.
18423 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18424 * @returns itself, so that it may be chained.
18425 * @codeGenApi
18426 */
18427function ɵɵstylePropInterpolate3(prop, prefix, v0, i0, v1, i1, v2, suffix, valueSuffix) {
18428 const lView = getLView();
18429 const interpolatedValue = interpolation3(lView, prefix, v0, i0, v1, i1, v2, suffix);
18430 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18431 return ɵɵstylePropInterpolate3;
18432}
18433/**
18434 *
18435 * Update an interpolated style property on an element with 4 bound values surrounded by text.
18436 *
18437 * Used when the value passed to a property has 4 interpolated values in it:
18438 *
18439 * ```html
18440 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}suffix"></div>
18441 * ```
18442 *
18443 * Its compiled representation is:
18444 *
18445 * ```ts
18446 * ɵɵstylePropInterpolate4(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, 'suffix');
18447 * ```
18448 *
18449 * @param styleIndex Index of style to update. This index value refers to the
18450 * index of the style in the style bindings array that was passed into
18451 * `styling`.
18452 * @param prefix Static value used for concatenation only.
18453 * @param v0 Value checked for change.
18454 * @param i0 Static value used for concatenation only.
18455 * @param v1 Value checked for change.
18456 * @param i1 Static value used for concatenation only.
18457 * @param v2 Value checked for change.
18458 * @param i2 Static value used for concatenation only.
18459 * @param v3 Value checked for change.
18460 * @param suffix Static value used for concatenation only.
18461 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18462 * @returns itself, so that it may be chained.
18463 * @codeGenApi
18464 */
18465function ɵɵstylePropInterpolate4(prop, prefix, v0, i0, v1, i1, v2, i2, v3, suffix, valueSuffix) {
18466 const lView = getLView();
18467 const interpolatedValue = interpolation4(lView, prefix, v0, i0, v1, i1, v2, i2, v3, suffix);
18468 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18469 return ɵɵstylePropInterpolate4;
18470}
18471/**
18472 *
18473 * Update an interpolated style property on an element with 5 bound values surrounded by text.
18474 *
18475 * Used when the value passed to a property has 5 interpolated values in it:
18476 *
18477 * ```html
18478 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}suffix"></div>
18479 * ```
18480 *
18481 * Its compiled representation is:
18482 *
18483 * ```ts
18484 * ɵɵstylePropInterpolate5(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, 'suffix');
18485 * ```
18486 *
18487 * @param styleIndex Index of style to update. This index value refers to the
18488 * index of the style in the style bindings array that was passed into
18489 * `styling`.
18490 * @param prefix Static value used for concatenation only.
18491 * @param v0 Value checked for change.
18492 * @param i0 Static value used for concatenation only.
18493 * @param v1 Value checked for change.
18494 * @param i1 Static value used for concatenation only.
18495 * @param v2 Value checked for change.
18496 * @param i2 Static value used for concatenation only.
18497 * @param v3 Value checked for change.
18498 * @param i3 Static value used for concatenation only.
18499 * @param v4 Value checked for change.
18500 * @param suffix Static value used for concatenation only.
18501 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18502 * @returns itself, so that it may be chained.
18503 * @codeGenApi
18504 */
18505function ɵɵstylePropInterpolate5(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix, valueSuffix) {
18506 const lView = getLView();
18507 const interpolatedValue = interpolation5(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, suffix);
18508 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18509 return ɵɵstylePropInterpolate5;
18510}
18511/**
18512 *
18513 * Update an interpolated style property on an element with 6 bound values surrounded by text.
18514 *
18515 * Used when the value passed to a property has 6 interpolated values in it:
18516 *
18517 * ```html
18518 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}suffix"></div>
18519 * ```
18520 *
18521 * Its compiled representation is:
18522 *
18523 * ```ts
18524 * ɵɵstylePropInterpolate6(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, 'suffix');
18525 * ```
18526 *
18527 * @param styleIndex Index of style to update. This index value refers to the
18528 * index of the style in the style bindings array that was passed into
18529 * `styling`.
18530 * @param prefix Static value used for concatenation only.
18531 * @param v0 Value checked for change.
18532 * @param i0 Static value used for concatenation only.
18533 * @param v1 Value checked for change.
18534 * @param i1 Static value used for concatenation only.
18535 * @param v2 Value checked for change.
18536 * @param i2 Static value used for concatenation only.
18537 * @param v3 Value checked for change.
18538 * @param i3 Static value used for concatenation only.
18539 * @param v4 Value checked for change.
18540 * @param i4 Static value used for concatenation only.
18541 * @param v5 Value checked for change.
18542 * @param suffix Static value used for concatenation only.
18543 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18544 * @returns itself, so that it may be chained.
18545 * @codeGenApi
18546 */
18547function ɵɵstylePropInterpolate6(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix, valueSuffix) {
18548 const lView = getLView();
18549 const interpolatedValue = interpolation6(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, suffix);
18550 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18551 return ɵɵstylePropInterpolate6;
18552}
18553/**
18554 *
18555 * Update an interpolated style property on an element with 7 bound values surrounded by text.
18556 *
18557 * Used when the value passed to a property has 7 interpolated values in it:
18558 *
18559 * ```html
18560 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}suffix"></div>
18561 * ```
18562 *
18563 * Its compiled representation is:
18564 *
18565 * ```ts
18566 * ɵɵstylePropInterpolate7(
18567 * 0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, 'suffix');
18568 * ```
18569 *
18570 * @param styleIndex Index of style to update. This index value refers to the
18571 * index of the style in the style bindings array that was passed into
18572 * `styling`.
18573 * @param prefix Static value used for concatenation only.
18574 * @param v0 Value checked for change.
18575 * @param i0 Static value used for concatenation only.
18576 * @param v1 Value checked for change.
18577 * @param i1 Static value used for concatenation only.
18578 * @param v2 Value checked for change.
18579 * @param i2 Static value used for concatenation only.
18580 * @param v3 Value checked for change.
18581 * @param i3 Static value used for concatenation only.
18582 * @param v4 Value checked for change.
18583 * @param i4 Static value used for concatenation only.
18584 * @param v5 Value checked for change.
18585 * @param i5 Static value used for concatenation only.
18586 * @param v6 Value checked for change.
18587 * @param suffix Static value used for concatenation only.
18588 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18589 * @returns itself, so that it may be chained.
18590 * @codeGenApi
18591 */
18592function ɵɵstylePropInterpolate7(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix, valueSuffix) {
18593 const lView = getLView();
18594 const interpolatedValue = interpolation7(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, suffix);
18595 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18596 return ɵɵstylePropInterpolate7;
18597}
18598/**
18599 *
18600 * Update an interpolated style property on an element with 8 bound values surrounded by text.
18601 *
18602 * Used when the value passed to a property has 8 interpolated values in it:
18603 *
18604 * ```html
18605 * <div style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}suffix"></div>
18606 * ```
18607 *
18608 * Its compiled representation is:
18609 *
18610 * ```ts
18611 * ɵɵstylePropInterpolate8(0, 'prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6,
18612 * '-', v7, 'suffix');
18613 * ```
18614 *
18615 * @param styleIndex Index of style to update. This index value refers to the
18616 * index of the style in the style bindings array that was passed into
18617 * `styling`.
18618 * @param prefix Static value used for concatenation only.
18619 * @param v0 Value checked for change.
18620 * @param i0 Static value used for concatenation only.
18621 * @param v1 Value checked for change.
18622 * @param i1 Static value used for concatenation only.
18623 * @param v2 Value checked for change.
18624 * @param i2 Static value used for concatenation only.
18625 * @param v3 Value checked for change.
18626 * @param i3 Static value used for concatenation only.
18627 * @param v4 Value checked for change.
18628 * @param i4 Static value used for concatenation only.
18629 * @param v5 Value checked for change.
18630 * @param i5 Static value used for concatenation only.
18631 * @param v6 Value checked for change.
18632 * @param i6 Static value used for concatenation only.
18633 * @param v7 Value checked for change.
18634 * @param suffix Static value used for concatenation only.
18635 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18636 * @returns itself, so that it may be chained.
18637 * @codeGenApi
18638 */
18639function ɵɵstylePropInterpolate8(prop, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix, valueSuffix) {
18640 const lView = getLView();
18641 const interpolatedValue = interpolation8(lView, prefix, v0, i0, v1, i1, v2, i2, v3, i3, v4, i4, v5, i5, v6, i6, v7, suffix);
18642 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18643 return ɵɵstylePropInterpolate8;
18644}
18645/**
18646 * Update an interpolated style property on an element with 9 or more bound values surrounded by
18647 * text.
18648 *
18649 * Used when the number of interpolated values exceeds 8.
18650 *
18651 * ```html
18652 * <div
18653 * style.color="prefix{{v0}}-{{v1}}-{{v2}}-{{v3}}-{{v4}}-{{v5}}-{{v6}}-{{v7}}-{{v8}}-{{v9}}suffix">
18654 * </div>
18655 * ```
18656 *
18657 * Its compiled representation is:
18658 *
18659 * ```ts
18660 * ɵɵstylePropInterpolateV(
18661 * 0, ['prefix', v0, '-', v1, '-', v2, '-', v3, '-', v4, '-', v5, '-', v6, '-', v7, '-', v9,
18662 * 'suffix']);
18663 * ```
18664 *
18665 * @param styleIndex Index of style to update. This index value refers to the
18666 * index of the style in the style bindings array that was passed into
18667 * `styling`..
18668 * @param values The collection of values and the strings in-between those values, beginning with
18669 * a string prefix and ending with a string suffix.
18670 * (e.g. `['prefix', value0, '-', value1, '-', value2, ..., value99, 'suffix']`)
18671 * @param valueSuffix Optional suffix. Used with scalar values to add unit such as `px`.
18672 * @returns itself, so that it may be chained.
18673 * @codeGenApi
18674 */
18675function ɵɵstylePropInterpolateV(prop, values, valueSuffix) {
18676 const lView = getLView();
18677 const interpolatedValue = interpolationV(lView, values);
18678 checkStylingProperty(prop, interpolatedValue, valueSuffix, false);
18679 return ɵɵstylePropInterpolateV;
18680}
18681
18682/**
18683 * @license
18684 * Copyright Google LLC All Rights Reserved.
18685 *
18686 * Use of this source code is governed by an MIT-style license that can be
18687 * found in the LICENSE file at https://angular.io/license
18688 */
18689/**
18690 * Update a property on a host element. Only applies to native node properties, not inputs.
18691 *
18692 * Operates on the element selected by index via the {@link select} instruction.
18693 *
18694 * @param propName Name of property. Because it is going to DOM, this is not subject to
18695 * renaming as part of minification.
18696 * @param value New value to write.
18697 * @param sanitizer An optional function used to sanitize the value.
18698 * @returns This function returns itself so that it may be chained
18699 * (e.g. `property('name', ctx.name)('title', ctx.title)`)
18700 *
18701 * @codeGenApi
18702 */
18703function ɵɵhostProperty(propName, value, sanitizer) {
18704 const lView = getLView();
18705 const bindingIndex = nextBindingIndex();
18706 if (bindingUpdated(lView, bindingIndex, value)) {
18707 const tView = getTView();
18708 const tNode = getSelectedTNode();
18709 elementPropertyInternal(tView, tNode, lView, propName, value, lView[RENDERER], sanitizer, true);
18710 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
18711 }
18712 return ɵɵhostProperty;
18713}
18714/**
18715 * Updates a synthetic host binding (e.g. `[@foo]`) on a component or directive.
18716 *
18717 * This instruction is for compatibility purposes and is designed to ensure that a
18718 * synthetic host binding (e.g. `@HostBinding('@foo')`) properly gets rendered in
18719 * the component's renderer. Normally all host bindings are evaluated with the parent
18720 * component's renderer, but, in the case of animation @triggers, they need to be
18721 * evaluated with the sub component's renderer (because that's where the animation
18722 * triggers are defined).
18723 *
18724 * Do not use this instruction as a replacement for `elementProperty`. This instruction
18725 * only exists to ensure compatibility with the ViewEngine's host binding behavior.
18726 *
18727 * @param index The index of the element to update in the data array
18728 * @param propName Name of property. Because it is going to DOM, this is not subject to
18729 * renaming as part of minification.
18730 * @param value New value to write.
18731 * @param sanitizer An optional function used to sanitize the value.
18732 *
18733 * @codeGenApi
18734 */
18735function ɵɵsyntheticHostProperty(propName, value, sanitizer) {
18736 const lView = getLView();
18737 const bindingIndex = nextBindingIndex();
18738 if (bindingUpdated(lView, bindingIndex, value)) {
18739 const tView = getTView();
18740 const tNode = getSelectedTNode();
18741 const currentDef = getCurrentDirectiveDef(tView.data);
18742 const renderer = loadComponentRenderer(currentDef, tNode, lView);
18743 elementPropertyInternal(tView, tNode, lView, propName, value, renderer, sanitizer, true);
18744 ngDevMode && storePropertyBindingMetadata(tView.data, tNode, propName, bindingIndex);
18745 }
18746 return ɵɵsyntheticHostProperty;
18747}
18748
18749/**
18750 * @license
18751 * Copyright Google LLC All Rights Reserved.
18752 *
18753 * Use of this source code is governed by an MIT-style license that can be
18754 * found in the LICENSE file at https://angular.io/license
18755 */
18756/**
18757 * NOTE: changes to the `ngI18nClosureMode` name must be synced with `compiler-cli/src/tooling.ts`.
18758 */
18759if (typeof ngI18nClosureMode === 'undefined') {
18760 // These property accesses can be ignored because ngI18nClosureMode will be set to false
18761 // when optimizing code and the whole if statement will be dropped.
18762 // Make sure to refer to ngI18nClosureMode as ['ngI18nClosureMode'] for closure.
18763 // NOTE: we need to have it in IIFE so that the tree-shaker is happy.
18764 (function () {
18765 // tslint:disable-next-line:no-toplevel-property-access
18766 _global['ngI18nClosureMode'] =
18767 // TODO(FW-1250): validate that this actually, you know, works.
18768 // tslint:disable-next-line:no-toplevel-property-access
18769 typeof goog !== 'undefined' && typeof goog.getMsg === 'function';
18770 })();
18771}
18772
18773/**
18774 * @license
18775 * Copyright Google LLC All Rights Reserved.
18776 *
18777 * Use of this source code is governed by an MIT-style license that can be
18778 * found in the LICENSE file at https://angular.io/license
18779 */
18780// THIS CODE IS GENERATED - DO NOT MODIFY.
18781const u = undefined;
18782function plural(val) {
18783 const n = val, i = Math.floor(Math.abs(val)), v = val.toString().replace(/^[^.]*\.?/, '').length;
18784 if (i === 1 && v === 0)
18785 return 1;
18786 return 5;
18787}
18788var 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];
18789
18790/**
18791 * @license
18792 * Copyright Google LLC All Rights Reserved.
18793 *
18794 * Use of this source code is governed by an MIT-style license that can be
18795 * found in the LICENSE file at https://angular.io/license
18796 */
18797/**
18798 * This const is used to store the locale data registered with `registerLocaleData`
18799 */
18800let LOCALE_DATA = {};
18801/**
18802 * Register locale data to be used internally by Angular. See the
18803 * ["I18n guide"](guide/i18n-common-format-data-locale) to know how to import additional locale
18804 * data.
18805 *
18806 * The signature `registerLocaleData(data: any, extraData?: any)` is deprecated since v5.1
18807 */
18808function registerLocaleData(data, localeId, extraData) {
18809 if (typeof localeId !== 'string') {
18810 extraData = localeId;
18811 localeId = data[LocaleDataIndex.LocaleId];
18812 }
18813 localeId = localeId.toLowerCase().replace(/_/g, '-');
18814 LOCALE_DATA[localeId] = data;
18815 if (extraData) {
18816 LOCALE_DATA[localeId][LocaleDataIndex.ExtraData] = extraData;
18817 }
18818}
18819/**
18820 * Finds the locale data for a given locale.
18821 *
18822 * @param locale The locale code.
18823 * @returns The locale data.
18824 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
18825 */
18826function findLocaleData(locale) {
18827 const normalizedLocale = normalizeLocale(locale);
18828 let match = getLocaleData(normalizedLocale);
18829 if (match) {
18830 return match;
18831 }
18832 // let's try to find a parent locale
18833 const parentLocale = normalizedLocale.split('-')[0];
18834 match = getLocaleData(parentLocale);
18835 if (match) {
18836 return match;
18837 }
18838 if (parentLocale === 'en') {
18839 return localeEn;
18840 }
18841 throw new Error(`Missing locale data for the locale "${locale}".`);
18842}
18843/**
18844 * Retrieves the default currency code for the given locale.
18845 *
18846 * The default is defined as the first currency which is still in use.
18847 *
18848 * @param locale The code of the locale whose currency code we want.
18849 * @returns The code of the default currency for the given locale.
18850 *
18851 */
18852function getLocaleCurrencyCode(locale) {
18853 const data = findLocaleData(locale);
18854 return data[LocaleDataIndex.CurrencyCode] || null;
18855}
18856/**
18857 * Retrieves the plural function used by ICU expressions to determine the plural case to use
18858 * for a given locale.
18859 * @param locale A locale code for the locale format rules to use.
18860 * @returns The plural function for the locale.
18861 * @see `NgPlural`
18862 * @see [Internationalization (i18n) Guide](https://angular.io/guide/i18n-overview)
18863 */
18864function getLocalePluralCase(locale) {
18865 const data = findLocaleData(locale);
18866 return data[LocaleDataIndex.PluralCase];
18867}
18868/**
18869 * Helper function to get the given `normalizedLocale` from `LOCALE_DATA`
18870 * or from the global `ng.common.locale`.
18871 */
18872function getLocaleData(normalizedLocale) {
18873 if (!(normalizedLocale in LOCALE_DATA)) {
18874 LOCALE_DATA[normalizedLocale] = _global.ng && _global.ng.common && _global.ng.common.locales &&
18875 _global.ng.common.locales[normalizedLocale];
18876 }
18877 return LOCALE_DATA[normalizedLocale];
18878}
18879/**
18880 * Helper function to remove all the locale data from `LOCALE_DATA`.
18881 */
18882function unregisterAllLocaleData() {
18883 LOCALE_DATA = {};
18884}
18885/**
18886 * Index of each type of locale data from the locale data array
18887 */
18888var LocaleDataIndex;
18889(function (LocaleDataIndex) {
18890 LocaleDataIndex[LocaleDataIndex["LocaleId"] = 0] = "LocaleId";
18891 LocaleDataIndex[LocaleDataIndex["DayPeriodsFormat"] = 1] = "DayPeriodsFormat";
18892 LocaleDataIndex[LocaleDataIndex["DayPeriodsStandalone"] = 2] = "DayPeriodsStandalone";
18893 LocaleDataIndex[LocaleDataIndex["DaysFormat"] = 3] = "DaysFormat";
18894 LocaleDataIndex[LocaleDataIndex["DaysStandalone"] = 4] = "DaysStandalone";
18895 LocaleDataIndex[LocaleDataIndex["MonthsFormat"] = 5] = "MonthsFormat";
18896 LocaleDataIndex[LocaleDataIndex["MonthsStandalone"] = 6] = "MonthsStandalone";
18897 LocaleDataIndex[LocaleDataIndex["Eras"] = 7] = "Eras";
18898 LocaleDataIndex[LocaleDataIndex["FirstDayOfWeek"] = 8] = "FirstDayOfWeek";
18899 LocaleDataIndex[LocaleDataIndex["WeekendRange"] = 9] = "WeekendRange";
18900 LocaleDataIndex[LocaleDataIndex["DateFormat"] = 10] = "DateFormat";
18901 LocaleDataIndex[LocaleDataIndex["TimeFormat"] = 11] = "TimeFormat";
18902 LocaleDataIndex[LocaleDataIndex["DateTimeFormat"] = 12] = "DateTimeFormat";
18903 LocaleDataIndex[LocaleDataIndex["NumberSymbols"] = 13] = "NumberSymbols";
18904 LocaleDataIndex[LocaleDataIndex["NumberFormats"] = 14] = "NumberFormats";
18905 LocaleDataIndex[LocaleDataIndex["CurrencyCode"] = 15] = "CurrencyCode";
18906 LocaleDataIndex[LocaleDataIndex["CurrencySymbol"] = 16] = "CurrencySymbol";
18907 LocaleDataIndex[LocaleDataIndex["CurrencyName"] = 17] = "CurrencyName";
18908 LocaleDataIndex[LocaleDataIndex["Currencies"] = 18] = "Currencies";
18909 LocaleDataIndex[LocaleDataIndex["Directionality"] = 19] = "Directionality";
18910 LocaleDataIndex[LocaleDataIndex["PluralCase"] = 20] = "PluralCase";
18911 LocaleDataIndex[LocaleDataIndex["ExtraData"] = 21] = "ExtraData";
18912})(LocaleDataIndex || (LocaleDataIndex = {}));
18913/**
18914 * Returns the canonical form of a locale name - lowercase with `_` replaced with `-`.
18915 */
18916function normalizeLocale(locale) {
18917 return locale.toLowerCase().replace(/_/g, '-');
18918}
18919
18920/**
18921 * @license
18922 * Copyright Google LLC All Rights Reserved.
18923 *
18924 * Use of this source code is governed by an MIT-style license that can be
18925 * found in the LICENSE file at https://angular.io/license
18926 */
18927const pluralMapping = ['zero', 'one', 'two', 'few', 'many'];
18928/**
18929 * Returns the plural case based on the locale
18930 */
18931function getPluralCase(value, locale) {
18932 const plural = getLocalePluralCase(locale)(parseInt(value, 10));
18933 const result = pluralMapping[plural];
18934 return (result !== undefined) ? result : 'other';
18935}
18936/**
18937 * The locale id that the application is using by default (for translations and ICU expressions).
18938 */
18939const DEFAULT_LOCALE_ID = 'en-US';
18940/**
18941 * USD currency code that the application uses by default for CurrencyPipe when no
18942 * DEFAULT_CURRENCY_CODE is provided.
18943 */
18944const USD_CURRENCY_CODE = 'USD';
18945
18946/**
18947 * @license
18948 * Copyright Google LLC All Rights Reserved.
18949 *
18950 * Use of this source code is governed by an MIT-style license that can be
18951 * found in the LICENSE file at https://angular.io/license
18952 */
18953/**
18954 * Marks that the next string is an element name.
18955 *
18956 * See `I18nMutateOpCodes` documentation.
18957 */
18958const ELEMENT_MARKER = {
18959 marker: 'element'
18960};
18961/**
18962 * Marks that the next string is comment text need for ICU.
18963 *
18964 * See `I18nMutateOpCodes` documentation.
18965 */
18966const ICU_MARKER = {
18967 marker: 'ICU'
18968};
18969/**
18970 * See `I18nCreateOpCodes`
18971 */
18972var I18nCreateOpCode;
18973(function (I18nCreateOpCode) {
18974 /**
18975 * Number of bits to shift index so that it can be combined with the `APPEND_EAGERLY` and
18976 * `COMMENT`.
18977 */
18978 I18nCreateOpCode[I18nCreateOpCode["SHIFT"] = 2] = "SHIFT";
18979 /**
18980 * Should the node be appended to parent imedditatly after creation.
18981 */
18982 I18nCreateOpCode[I18nCreateOpCode["APPEND_EAGERLY"] = 1] = "APPEND_EAGERLY";
18983 /**
18984 * If set the node should be comment (rather than a text) node.
18985 */
18986 I18nCreateOpCode[I18nCreateOpCode["COMMENT"] = 2] = "COMMENT";
18987})(I18nCreateOpCode || (I18nCreateOpCode = {}));
18988// Note: This hack is necessary so we don't erroneously get a circular dependency
18989// failure based on types.
18990const unusedValueExportToPlacateAjd$2 = 1;
18991
18992/**
18993 * @license
18994 * Copyright Google LLC All Rights Reserved.
18995 *
18996 * Use of this source code is governed by an MIT-style license that can be
18997 * found in the LICENSE file at https://angular.io/license
18998 */
18999/**
19000 * The locale id that the application is currently using (for translations and ICU expressions).
19001 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
19002 * but is now defined as a global value.
19003 */
19004let LOCALE_ID$1 = DEFAULT_LOCALE_ID;
19005/**
19006 * Sets the locale id that will be used for translations and ICU expressions.
19007 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
19008 * but is now defined as a global value.
19009 *
19010 * @param localeId
19011 */
19012function setLocaleId(localeId) {
19013 assertDefined(localeId, `Expected localeId to be defined`);
19014 if (typeof localeId === 'string') {
19015 LOCALE_ID$1 = localeId.toLowerCase().replace(/_/g, '-');
19016 }
19017}
19018/**
19019 * Gets the locale id that will be used for translations and ICU expressions.
19020 * This is the ivy version of `LOCALE_ID` that was defined as an injection token for the view engine
19021 * but is now defined as a global value.
19022 */
19023function getLocaleId() {
19024 return LOCALE_ID$1;
19025}
19026
19027/**
19028 * @license
19029 * Copyright Google LLC All Rights Reserved.
19030 *
19031 * Use of this source code is governed by an MIT-style license that can be
19032 * found in the LICENSE file at https://angular.io/license
19033 */
19034/**
19035 * Find a node in front of which `currentTNode` should be inserted (takes i18n into account).
19036 *
19037 * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
19038 * takes `TNode.insertBeforeIndex` into account.
19039 *
19040 * @param parentTNode parent `TNode`
19041 * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
19042 * @param lView current `LView`
19043 */
19044function getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView) {
19045 const tNodeInsertBeforeIndex = currentTNode.insertBeforeIndex;
19046 const insertBeforeIndex = Array.isArray(tNodeInsertBeforeIndex) ? tNodeInsertBeforeIndex[0] : tNodeInsertBeforeIndex;
19047 if (insertBeforeIndex === null) {
19048 return getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView);
19049 }
19050 else {
19051 ngDevMode && assertIndexInRange(lView, insertBeforeIndex);
19052 return unwrapRNode(lView[insertBeforeIndex]);
19053 }
19054}
19055/**
19056 * Process `TNode.insertBeforeIndex` by adding i18n text nodes.
19057 *
19058 * See `TNode.insertBeforeIndex`
19059 */
19060function processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRElement) {
19061 const tNodeInsertBeforeIndex = childTNode.insertBeforeIndex;
19062 if (Array.isArray(tNodeInsertBeforeIndex)) {
19063 // An array indicates that there are i18n nodes that need to be added as children of this
19064 // `childRNode`. These i18n nodes were created before this `childRNode` was available and so
19065 // only now can be added. The first element of the array is the normal index where we should
19066 // insert the `childRNode`. Additional elements are the extra nodes to be added as children of
19067 // `childRNode`.
19068 ngDevMode && assertDomNode(childRNode);
19069 let i18nParent = childRNode;
19070 let anchorRNode = null;
19071 if (!(childTNode.type & 3 /* AnyRNode */)) {
19072 anchorRNode = i18nParent;
19073 i18nParent = parentRElement;
19074 }
19075 if (i18nParent !== null && (childTNode.flags & 2 /* isComponentHost */) === 0) {
19076 for (let i = 1; i < tNodeInsertBeforeIndex.length; i++) {
19077 // No need to `unwrapRNode` because all of the indexes point to i18n text nodes.
19078 // see `assertDomNode` below.
19079 const i18nChild = lView[tNodeInsertBeforeIndex[i]];
19080 nativeInsertBefore(renderer, i18nParent, i18nChild, anchorRNode, false);
19081 }
19082 }
19083 }
19084}
19085
19086/**
19087 * @license
19088 * Copyright Google LLC All Rights Reserved.
19089 *
19090 * Use of this source code is governed by an MIT-style license that can be
19091 * found in the LICENSE file at https://angular.io/license
19092 */
19093/**
19094 * Add `tNode` to `previousTNodes` list and update relevant `TNode`s in `previousTNodes` list
19095 * `tNode.insertBeforeIndex`.
19096 *
19097 * Things to keep in mind:
19098 * 1. All i18n text nodes are encoded as `TNodeType.Element` and are created eagerly by the
19099 * `ɵɵi18nStart` instruction.
19100 * 2. All `TNodeType.Placeholder` `TNodes` are elements which will be created later by
19101 * `ɵɵelementStart` instruction.
19102 * 3. `ɵɵelementStart` instruction will create `TNode`s in the ascending `TNode.index` order. (So a
19103 * smaller index `TNode` is guaranteed to be created before a larger one)
19104 *
19105 * We use the above three invariants to determine `TNode.insertBeforeIndex`.
19106 *
19107 * In an ideal world `TNode.insertBeforeIndex` would always be `TNode.next.index`. However,
19108 * this will not work because `TNode.next.index` may be larger than `TNode.index` which means that
19109 * the next node is not yet created and therefore we can't insert in front of it.
19110 *
19111 * Rule1: `TNode.insertBeforeIndex = null` if `TNode.next === null` (Initial condition, as we don't
19112 * know if there will be further `TNode`s inserted after.)
19113 * Rule2: If `previousTNode` is created after the `tNode` being inserted, then
19114 * `previousTNode.insertBeforeNode = tNode.index` (So when a new `tNode` is added we check
19115 * previous to see if we can update its `insertBeforeTNode`)
19116 *
19117 * See `TNode.insertBeforeIndex` for more context.
19118 *
19119 * @param previousTNodes A list of previous TNodes so that we can easily traverse `TNode`s in
19120 * reverse order. (If `TNode` would have `previous` this would not be necessary.)
19121 * @param newTNode A TNode to add to the `previousTNodes` list.
19122 */
19123function addTNodeAndUpdateInsertBeforeIndex(previousTNodes, newTNode) {
19124 // Start with Rule1
19125 ngDevMode &&
19126 assertEqual(newTNode.insertBeforeIndex, null, 'We expect that insertBeforeIndex is not set');
19127 previousTNodes.push(newTNode);
19128 if (previousTNodes.length > 1) {
19129 for (let i = previousTNodes.length - 2; i >= 0; i--) {
19130 const existingTNode = previousTNodes[i];
19131 // Text nodes are created eagerly and so they don't need their `indexBeforeIndex` updated.
19132 // It is safe to ignore them.
19133 if (!isI18nText(existingTNode)) {
19134 if (isNewTNodeCreatedBefore(existingTNode, newTNode) &&
19135 getInsertBeforeIndex(existingTNode) === null) {
19136 // If it was created before us in time, (and it does not yet have `insertBeforeIndex`)
19137 // then add the `insertBeforeIndex`.
19138 setInsertBeforeIndex(existingTNode, newTNode.index);
19139 }
19140 }
19141 }
19142 }
19143}
19144function isI18nText(tNode) {
19145 return !(tNode.type & 64 /* Placeholder */);
19146}
19147function isNewTNodeCreatedBefore(existingTNode, newTNode) {
19148 return isI18nText(newTNode) || existingTNode.index > newTNode.index;
19149}
19150function getInsertBeforeIndex(tNode) {
19151 const index = tNode.insertBeforeIndex;
19152 return Array.isArray(index) ? index[0] : index;
19153}
19154function setInsertBeforeIndex(tNode, value) {
19155 const index = tNode.insertBeforeIndex;
19156 if (Array.isArray(index)) {
19157 // Array is stored if we have to insert child nodes. See `TNode.insertBeforeIndex`
19158 index[0] = value;
19159 }
19160 else {
19161 setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);
19162 tNode.insertBeforeIndex = value;
19163 }
19164}
19165
19166/**
19167 * @license
19168 * Copyright Google LLC All Rights Reserved.
19169 *
19170 * Use of this source code is governed by an MIT-style license that can be
19171 * found in the LICENSE file at https://angular.io/license
19172 */
19173/**
19174 * Retrieve `TIcu` at a given `index`.
19175 *
19176 * The `TIcu` can be stored either directly (if it is nested ICU) OR
19177 * it is stored inside tho `TIcuContainer` if it is top level ICU.
19178 *
19179 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
19180 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is
19181 * expressed (parent ICU may have selected a case which does not contain it.)
19182 *
19183 * @param tView Current `TView`.
19184 * @param index Index where the value should be read from.
19185 */
19186function getTIcu(tView, index) {
19187 const value = tView.data[index];
19188 if (value === null || typeof value === 'string')
19189 return null;
19190 if (ngDevMode &&
19191 !(value.hasOwnProperty('tViews') || value.hasOwnProperty('currentCaseLViewIndex'))) {
19192 throwError('We expect to get \'null\'|\'TIcu\'|\'TIcuContainer\', but got: ' + value);
19193 }
19194 // Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be
19195 // either TIcu or TIcuContainerNode. This is not ideal, but we still think it is OK because it
19196 // will be just two cases which fits into the browser inline cache (inline cache can take up to
19197 // 4)
19198 const tIcu = value.hasOwnProperty('currentCaseLViewIndex') ? value :
19199 value.value;
19200 ngDevMode && assertTIcu(tIcu);
19201 return tIcu;
19202}
19203/**
19204 * Store `TIcu` at a give `index`.
19205 *
19206 * The `TIcu` can be stored either directly (if it is nested ICU) OR
19207 * it is stored inside tho `TIcuContainer` if it is top level ICU.
19208 *
19209 * The reason for this is that the top level ICU need a `TNode` so that they are part of the render
19210 * tree, but nested ICU's have no TNode, because we don't know ahead of time if the nested ICU is
19211 * expressed (parent ICU may have selected a case which does not contain it.)
19212 *
19213 * @param tView Current `TView`.
19214 * @param index Index where the value should be stored at in `Tview.data`
19215 * @param tIcu The TIcu to store.
19216 */
19217function setTIcu(tView, index, tIcu) {
19218 const tNode = tView.data[index];
19219 ngDevMode &&
19220 assertEqual(tNode === null || tNode.hasOwnProperty('tViews'), true, 'We expect to get \'null\'|\'TIcuContainer\'');
19221 if (tNode === null) {
19222 tView.data[index] = tIcu;
19223 }
19224 else {
19225 ngDevMode && assertTNodeType(tNode, 32 /* Icu */);
19226 tNode.value = tIcu;
19227 }
19228}
19229/**
19230 * Set `TNode.insertBeforeIndex` taking the `Array` into account.
19231 *
19232 * See `TNode.insertBeforeIndex`
19233 */
19234function setTNodeInsertBeforeIndex(tNode, index) {
19235 ngDevMode && assertTNode(tNode);
19236 let insertBeforeIndex = tNode.insertBeforeIndex;
19237 if (insertBeforeIndex === null) {
19238 setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore);
19239 insertBeforeIndex = tNode.insertBeforeIndex =
19240 [null /* may be updated to number later */, index];
19241 }
19242 else {
19243 assertEqual(Array.isArray(insertBeforeIndex), true, 'Expecting array here');
19244 insertBeforeIndex.push(index);
19245 }
19246}
19247/**
19248 * Create `TNode.type=TNodeType.Placeholder` node.
19249 *
19250 * See `TNodeType.Placeholder` for more information.
19251 */
19252function createTNodePlaceholder(tView, previousTNodes, index) {
19253 const tNode = createTNodeAtIndex(tView, index, 64 /* Placeholder */, null, null);
19254 addTNodeAndUpdateInsertBeforeIndex(previousTNodes, tNode);
19255 return tNode;
19256}
19257/**
19258 * Returns current ICU case.
19259 *
19260 * ICU cases are stored as index into the `TIcu.cases`.
19261 * At times it is necessary to communicate that the ICU case just switched and that next ICU update
19262 * should update all bindings regardless of the mask. In such a case the we store negative numbers
19263 * for cases which have just been switched. This function removes the negative flag.
19264 */
19265function getCurrentICUCaseIndex(tIcu, lView) {
19266 const currentCase = lView[tIcu.currentCaseLViewIndex];
19267 return currentCase === null ? currentCase : (currentCase < 0 ? ~currentCase : currentCase);
19268}
19269function getParentFromIcuCreateOpCode(mergedCode) {
19270 return mergedCode >>> 17 /* SHIFT_PARENT */;
19271}
19272function getRefFromIcuCreateOpCode(mergedCode) {
19273 return (mergedCode & 131070 /* MASK_REF */) >>> 1 /* SHIFT_REF */;
19274}
19275function getInstructionFromIcuCreateOpCode(mergedCode) {
19276 return mergedCode & 1 /* MASK_INSTRUCTION */;
19277}
19278function icuCreateOpCode(opCode, parentIdx, refIdx) {
19279 ngDevMode && assertGreaterThanOrEqual(parentIdx, 0, 'Missing parent index');
19280 ngDevMode && assertGreaterThan(refIdx, 0, 'Missing ref index');
19281 return opCode | parentIdx << 17 /* SHIFT_PARENT */ | refIdx << 1 /* SHIFT_REF */;
19282}
19283
19284/**
19285 * @license
19286 * Copyright Google LLC All Rights Reserved.
19287 *
19288 * Use of this source code is governed by an MIT-style license that can be
19289 * found in the LICENSE file at https://angular.io/license
19290 */
19291/**
19292 * Keep track of which input bindings in `ɵɵi18nExp` have changed.
19293 *
19294 * This is used to efficiently update expressions in i18n only when the corresponding input has
19295 * changed.
19296 *
19297 * 1) Each bit represents which of the `ɵɵi18nExp` has changed.
19298 * 2) There are 32 bits allowed in JS.
19299 * 3) Bit 32 is special as it is shared for all changes past 32. (In other words if you have more
19300 * than 32 `ɵɵi18nExp` then all changes past 32nd `ɵɵi18nExp` will be mapped to same bit. This means
19301 * that we may end up changing more than we need to. But i18n expressions with 32 bindings is rare
19302 * so in practice it should not be an issue.)
19303 */
19304let changeMask = 0b0;
19305/**
19306 * Keeps track of which bit needs to be updated in `changeMask`
19307 *
19308 * This value gets incremented on every call to `ɵɵi18nExp`
19309 */
19310let changeMaskCounter = 0;
19311/**
19312 * Keep track of which input bindings in `ɵɵi18nExp` have changed.
19313 *
19314 * `setMaskBit` gets invoked by each call to `ɵɵi18nExp`.
19315 *
19316 * @param hasChange did `ɵɵi18nExp` detect a change.
19317 */
19318function setMaskBit(hasChange) {
19319 if (hasChange) {
19320 changeMask = changeMask | (1 << Math.min(changeMaskCounter, 31));
19321 }
19322 changeMaskCounter++;
19323}
19324function applyI18n(tView, lView, index) {
19325 if (changeMaskCounter > 0) {
19326 ngDevMode && assertDefined(tView, `tView should be defined`);
19327 const tI18n = tView.data[index];
19328 // When `index` points to an `ɵɵi18nAttributes` then we have an array otherwise `TI18n`
19329 const updateOpCodes = Array.isArray(tI18n) ? tI18n : tI18n.update;
19330 const bindingsStartIndex = getBindingIndex() - changeMaskCounter - 1;
19331 applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask);
19332 }
19333 // Reset changeMask & maskBit to default for the next update cycle
19334 changeMask = 0b0;
19335 changeMaskCounter = 0;
19336}
19337/**
19338 * Apply `I18nCreateOpCodes` op-codes as stored in `TI18n.create`.
19339 *
19340 * Creates text (and comment) nodes which are internationalized.
19341 *
19342 * @param lView Current lView
19343 * @param createOpCodes Set of op-codes to apply
19344 * @param parentRNode Parent node (so that direct children can be added eagerly) or `null` if it is
19345 * a root node.
19346 * @param insertInFrontOf DOM node that should be used as an anchor.
19347 */
19348function applyCreateOpCodes(lView, createOpCodes, parentRNode, insertInFrontOf) {
19349 const renderer = lView[RENDERER];
19350 for (let i = 0; i < createOpCodes.length; i++) {
19351 const opCode = createOpCodes[i++];
19352 const text = createOpCodes[i];
19353 const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;
19354 const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;
19355 const index = opCode >>> I18nCreateOpCode.SHIFT;
19356 let rNode = lView[index];
19357 if (rNode === null) {
19358 // We only create new DOM nodes if they don't already exist: If ICU switches case back to a
19359 // case which was already instantiated, no need to create new DOM nodes.
19360 rNode = lView[index] =
19361 isComment ? renderer.createComment(text) : createTextNode(renderer, text);
19362 }
19363 if (appendNow && parentRNode !== null) {
19364 nativeInsertBefore(renderer, parentRNode, rNode, insertInFrontOf, false);
19365 }
19366 }
19367}
19368/**
19369 * Apply `I18nMutateOpCodes` OpCodes.
19370 *
19371 * @param tView Current `TView`
19372 * @param mutableOpCodes Mutable OpCodes to process
19373 * @param lView Current `LView`
19374 * @param anchorRNode place where the i18n node should be inserted.
19375 */
19376function applyMutableOpCodes(tView, mutableOpCodes, lView, anchorRNode) {
19377 ngDevMode && assertDomNode(anchorRNode);
19378 const renderer = lView[RENDERER];
19379 // `rootIdx` represents the node into which all inserts happen.
19380 let rootIdx = null;
19381 // `rootRNode` represents the real node into which we insert. This can be different from
19382 // `lView[rootIdx]` if we have projection.
19383 // - null we don't have a parent (as can be the case in when we are inserting into a root of
19384 // LView which has no parent.)
19385 // - `RElement` The element representing the root after taking projection into account.
19386 let rootRNode;
19387 for (let i = 0; i < mutableOpCodes.length; i++) {
19388 const opCode = mutableOpCodes[i];
19389 if (typeof opCode == 'string') {
19390 const textNodeIndex = mutableOpCodes[++i];
19391 if (lView[textNodeIndex] === null) {
19392 ngDevMode && ngDevMode.rendererCreateTextNode++;
19393 ngDevMode && assertIndexInRange(lView, textNodeIndex);
19394 lView[textNodeIndex] = createTextNode(renderer, opCode);
19395 }
19396 }
19397 else if (typeof opCode == 'number') {
19398 switch (opCode & 1 /* MASK_INSTRUCTION */) {
19399 case 0 /* AppendChild */:
19400 const parentIdx = getParentFromIcuCreateOpCode(opCode);
19401 if (rootIdx === null) {
19402 // The first operation should save the `rootIdx` because the first operation
19403 // must insert into the root. (Only subsequent operations can insert into a dynamic
19404 // parent)
19405 rootIdx = parentIdx;
19406 rootRNode = nativeParentNode(renderer, anchorRNode);
19407 }
19408 let insertInFrontOf;
19409 let parentRNode;
19410 if (parentIdx === rootIdx) {
19411 insertInFrontOf = anchorRNode;
19412 parentRNode = rootRNode;
19413 }
19414 else {
19415 insertInFrontOf = null;
19416 parentRNode = unwrapRNode(lView[parentIdx]);
19417 }
19418 // FIXME(misko): Refactor with `processI18nText`
19419 if (parentRNode !== null) {
19420 // This can happen if the `LView` we are adding to is not attached to a parent `LView`.
19421 // In such a case there is no "root" we can attach to. This is fine, as we still need to
19422 // create the elements. When the `LView` gets later added to a parent these "root" nodes
19423 // get picked up and added.
19424 ngDevMode && assertDomNode(parentRNode);
19425 const refIdx = getRefFromIcuCreateOpCode(opCode);
19426 ngDevMode && assertGreaterThan(refIdx, HEADER_OFFSET, 'Missing ref');
19427 // `unwrapRNode` is not needed here as all of these point to RNodes as part of the i18n
19428 // which can't have components.
19429 const child = lView[refIdx];
19430 ngDevMode && assertDomNode(child);
19431 nativeInsertBefore(renderer, parentRNode, child, insertInFrontOf, false);
19432 const tIcu = getTIcu(tView, refIdx);
19433 if (tIcu !== null && typeof tIcu === 'object') {
19434 // If we just added a comment node which has ICU then that ICU may have already been
19435 // rendered and therefore we need to re-add it here.
19436 ngDevMode && assertTIcu(tIcu);
19437 const caseIndex = getCurrentICUCaseIndex(tIcu, lView);
19438 if (caseIndex !== null) {
19439 applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, lView[tIcu.anchorIdx]);
19440 }
19441 }
19442 }
19443 break;
19444 case 1 /* Attr */:
19445 const elementNodeIndex = opCode >>> 1 /* SHIFT_REF */;
19446 const attrName = mutableOpCodes[++i];
19447 const attrValue = mutableOpCodes[++i];
19448 // This code is used for ICU expressions only, since we don't support
19449 // directives/components in ICUs, we don't need to worry about inputs here
19450 setElementAttribute$1(renderer, getNativeByIndex(elementNodeIndex, lView), null, null, attrName, attrValue, null);
19451 break;
19452 default:
19453 throw new Error(`Unable to determine the type of mutate operation for "${opCode}"`);
19454 }
19455 }
19456 else {
19457 switch (opCode) {
19458 case ICU_MARKER:
19459 const commentValue = mutableOpCodes[++i];
19460 const commentNodeIndex = mutableOpCodes[++i];
19461 if (lView[commentNodeIndex] === null) {
19462 ngDevMode &&
19463 assertEqual(typeof commentValue, 'string', `Expected "${commentValue}" to be a comment node value`);
19464 ngDevMode && ngDevMode.rendererCreateComment++;
19465 ngDevMode && assertIndexInExpandoRange(lView, commentNodeIndex);
19466 const commentRNode = lView[commentNodeIndex] =
19467 createCommentNode(renderer, commentValue);
19468 // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)
19469 attachPatchData(commentRNode, lView);
19470 }
19471 break;
19472 case ELEMENT_MARKER:
19473 const tagName = mutableOpCodes[++i];
19474 const elementNodeIndex = mutableOpCodes[++i];
19475 if (lView[elementNodeIndex] === null) {
19476 ngDevMode &&
19477 assertEqual(typeof tagName, 'string', `Expected "${tagName}" to be an element node tag name`);
19478 ngDevMode && ngDevMode.rendererCreateElement++;
19479 ngDevMode && assertIndexInExpandoRange(lView, elementNodeIndex);
19480 const elementRNode = lView[elementNodeIndex] =
19481 createElementNode(renderer, tagName, null);
19482 // FIXME(misko): Attaching patch data is only needed for the root (Also add tests)
19483 attachPatchData(elementRNode, lView);
19484 }
19485 break;
19486 default:
19487 ngDevMode &&
19488 throwError(`Unable to determine the type of mutate operation for "${opCode}"`);
19489 }
19490 }
19491 }
19492}
19493/**
19494 * Apply `I18nUpdateOpCodes` OpCodes
19495 *
19496 * @param tView Current `TView`
19497 * @param lView Current `LView`
19498 * @param updateOpCodes OpCodes to process
19499 * @param bindingsStartIndex Location of the first `ɵɵi18nApply`
19500 * @param changeMask Each bit corresponds to a `ɵɵi18nExp` (Counting backwards from
19501 * `bindingsStartIndex`)
19502 */
19503function applyUpdateOpCodes(tView, lView, updateOpCodes, bindingsStartIndex, changeMask) {
19504 for (let i = 0; i < updateOpCodes.length; i++) {
19505 // bit code to check if we should apply the next update
19506 const checkBit = updateOpCodes[i];
19507 // Number of opCodes to skip until next set of update codes
19508 const skipCodes = updateOpCodes[++i];
19509 if (checkBit & changeMask) {
19510 // The value has been updated since last checked
19511 let value = '';
19512 for (let j = i + 1; j <= (i + skipCodes); j++) {
19513 const opCode = updateOpCodes[j];
19514 if (typeof opCode == 'string') {
19515 value += opCode;
19516 }
19517 else if (typeof opCode == 'number') {
19518 if (opCode < 0) {
19519 // Negative opCode represent `i18nExp` values offset.
19520 value += renderStringify(lView[bindingsStartIndex - opCode]);
19521 }
19522 else {
19523 const nodeIndex = (opCode >>> 2 /* SHIFT_REF */);
19524 switch (opCode & 3 /* MASK_OPCODE */) {
19525 case 1 /* Attr */:
19526 const propName = updateOpCodes[++j];
19527 const sanitizeFn = updateOpCodes[++j];
19528 const tNodeOrTagName = tView.data[nodeIndex];
19529 ngDevMode && assertDefined(tNodeOrTagName, 'Experting TNode or string');
19530 if (typeof tNodeOrTagName === 'string') {
19531 // IF we don't have a `TNode`, then we are an element in ICU (as ICU content does
19532 // not have TNode), in which case we know that there are no directives, and hence
19533 // we use attribute setting.
19534 setElementAttribute$1(lView[RENDERER], lView[nodeIndex], null, tNodeOrTagName, propName, value, sanitizeFn);
19535 }
19536 else {
19537 elementPropertyInternal(tView, tNodeOrTagName, lView, propName, value, lView[RENDERER], sanitizeFn, false);
19538 }
19539 break;
19540 case 0 /* Text */:
19541 const rText = lView[nodeIndex];
19542 rText !== null && updateTextNode(lView[RENDERER], rText, value);
19543 break;
19544 case 2 /* IcuSwitch */:
19545 applyIcuSwitchCase(tView, getTIcu(tView, nodeIndex), lView, value);
19546 break;
19547 case 3 /* IcuUpdate */:
19548 applyIcuUpdateCase(tView, getTIcu(tView, nodeIndex), bindingsStartIndex, lView);
19549 break;
19550 }
19551 }
19552 }
19553 }
19554 }
19555 else {
19556 const opCode = updateOpCodes[i + 1];
19557 if (opCode > 0 && (opCode & 3 /* MASK_OPCODE */) === 3 /* IcuUpdate */) {
19558 // Special case for the `icuUpdateCase`. It could be that the mask did not match, but
19559 // we still need to execute `icuUpdateCase` because the case has changed recently due to
19560 // previous `icuSwitchCase` instruction. (`icuSwitchCase` and `icuUpdateCase` always come in
19561 // pairs.)
19562 const nodeIndex = (opCode >>> 2 /* SHIFT_REF */);
19563 const tIcu = getTIcu(tView, nodeIndex);
19564 const currentIndex = lView[tIcu.currentCaseLViewIndex];
19565 if (currentIndex < 0) {
19566 applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView);
19567 }
19568 }
19569 }
19570 i += skipCodes;
19571 }
19572}
19573/**
19574 * Apply OpCodes associated with updating an existing ICU.
19575 *
19576 * @param tView Current `TView`
19577 * @param tIcu Current `TIcu`
19578 * @param bindingsStartIndex Location of the first `ɵɵi18nApply`
19579 * @param lView Current `LView`
19580 */
19581function applyIcuUpdateCase(tView, tIcu, bindingsStartIndex, lView) {
19582 ngDevMode && assertIndexInRange(lView, tIcu.currentCaseLViewIndex);
19583 let activeCaseIndex = lView[tIcu.currentCaseLViewIndex];
19584 if (activeCaseIndex !== null) {
19585 let mask = changeMask;
19586 if (activeCaseIndex < 0) {
19587 // Clear the flag.
19588 // Negative number means that the ICU was freshly created and we need to force the update.
19589 activeCaseIndex = lView[tIcu.currentCaseLViewIndex] = ~activeCaseIndex;
19590 // -1 is same as all bits on, which simulates creation since it marks all bits dirty
19591 mask = -1;
19592 }
19593 applyUpdateOpCodes(tView, lView, tIcu.update[activeCaseIndex], bindingsStartIndex, mask);
19594 }
19595}
19596/**
19597 * Apply OpCodes associated with switching a case on ICU.
19598 *
19599 * This involves tearing down existing case and than building up a new case.
19600 *
19601 * @param tView Current `TView`
19602 * @param tIcu Current `TIcu`
19603 * @param lView Current `LView`
19604 * @param value Value of the case to update to.
19605 */
19606function applyIcuSwitchCase(tView, tIcu, lView, value) {
19607 // Rebuild a new case for this ICU
19608 const caseIndex = getCaseIndex(tIcu, value);
19609 let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);
19610 if (activeCaseIndex !== caseIndex) {
19611 applyIcuSwitchCaseRemove(tView, tIcu, lView);
19612 lView[tIcu.currentCaseLViewIndex] = caseIndex === null ? null : ~caseIndex;
19613 if (caseIndex !== null) {
19614 // Add the nodes for the new case
19615 const anchorRNode = lView[tIcu.anchorIdx];
19616 if (anchorRNode) {
19617 ngDevMode && assertDomNode(anchorRNode);
19618 applyMutableOpCodes(tView, tIcu.create[caseIndex], lView, anchorRNode);
19619 }
19620 }
19621 }
19622}
19623/**
19624 * Apply OpCodes associated with tearing ICU case.
19625 *
19626 * This involves tearing down existing case and than building up a new case.
19627 *
19628 * @param tView Current `TView`
19629 * @param tIcu Current `TIcu`
19630 * @param lView Current `LView`
19631 */
19632function applyIcuSwitchCaseRemove(tView, tIcu, lView) {
19633 let activeCaseIndex = getCurrentICUCaseIndex(tIcu, lView);
19634 if (activeCaseIndex !== null) {
19635 const removeCodes = tIcu.remove[activeCaseIndex];
19636 for (let i = 0; i < removeCodes.length; i++) {
19637 const nodeOrIcuIndex = removeCodes[i];
19638 if (nodeOrIcuIndex > 0) {
19639 // Positive numbers are `RNode`s.
19640 const rNode = getNativeByIndex(nodeOrIcuIndex, lView);
19641 rNode !== null && nativeRemoveNode(lView[RENDERER], rNode);
19642 }
19643 else {
19644 // Negative numbers are ICUs
19645 applyIcuSwitchCaseRemove(tView, getTIcu(tView, ~nodeOrIcuIndex), lView);
19646 }
19647 }
19648 }
19649}
19650/**
19651 * Returns the index of the current case of an ICU expression depending on the main binding value
19652 *
19653 * @param icuExpression
19654 * @param bindingValue The value of the main binding used by this ICU expression
19655 */
19656function getCaseIndex(icuExpression, bindingValue) {
19657 let index = icuExpression.cases.indexOf(bindingValue);
19658 if (index === -1) {
19659 switch (icuExpression.type) {
19660 case 1 /* plural */: {
19661 const resolvedCase = getPluralCase(bindingValue, getLocaleId());
19662 index = icuExpression.cases.indexOf(resolvedCase);
19663 if (index === -1 && resolvedCase !== 'other') {
19664 index = icuExpression.cases.indexOf('other');
19665 }
19666 break;
19667 }
19668 case 0 /* select */: {
19669 index = icuExpression.cases.indexOf('other');
19670 break;
19671 }
19672 }
19673 }
19674 return index === -1 ? null : index;
19675}
19676
19677/**
19678 * @license
19679 * Copyright Google LLC All Rights Reserved.
19680 *
19681 * Use of this source code is governed by an MIT-style license that can be
19682 * found in the LICENSE file at https://angular.io/license
19683 */
19684function loadIcuContainerVisitor() {
19685 const _stack = [];
19686 let _index = -1;
19687 let _lView;
19688 let _removes;
19689 /**
19690 * Retrieves a set of root nodes from `TIcu.remove`. Used by `TNodeType.ICUContainer`
19691 * to determine which root belong to the ICU.
19692 *
19693 * Example of usage.
19694 * ```
19695 * const nextRNode = icuContainerIteratorStart(tIcuContainerNode, lView);
19696 * let rNode: RNode|null;
19697 * while(rNode = nextRNode()) {
19698 * console.log(rNode);
19699 * }
19700 * ```
19701 *
19702 * @param tIcuContainerNode Current `TIcuContainerNode`
19703 * @param lView `LView` where the `RNode`s should be looked up.
19704 */
19705 function icuContainerIteratorStart(tIcuContainerNode, lView) {
19706 _lView = lView;
19707 while (_stack.length)
19708 _stack.pop();
19709 ngDevMode && assertTNodeForLView(tIcuContainerNode, lView);
19710 enterIcu(tIcuContainerNode.value, lView);
19711 return icuContainerIteratorNext;
19712 }
19713 function enterIcu(tIcu, lView) {
19714 _index = 0;
19715 const currentCase = getCurrentICUCaseIndex(tIcu, lView);
19716 if (currentCase !== null) {
19717 ngDevMode && assertNumberInRange(currentCase, 0, tIcu.cases.length - 1);
19718 _removes = tIcu.remove[currentCase];
19719 }
19720 else {
19721 _removes = EMPTY_ARRAY;
19722 }
19723 }
19724 function icuContainerIteratorNext() {
19725 if (_index < _removes.length) {
19726 const removeOpCode = _removes[_index++];
19727 ngDevMode && assertNumber(removeOpCode, 'Expecting OpCode number');
19728 if (removeOpCode > 0) {
19729 const rNode = _lView[removeOpCode];
19730 ngDevMode && assertDomNode(rNode);
19731 return rNode;
19732 }
19733 else {
19734 _stack.push(_index, _removes);
19735 // ICUs are represented by negative indices
19736 const tIcuIndex = ~removeOpCode;
19737 const tIcu = _lView[TVIEW].data[tIcuIndex];
19738 ngDevMode && assertTIcu(tIcu);
19739 enterIcu(tIcu, _lView);
19740 return icuContainerIteratorNext();
19741 }
19742 }
19743 else {
19744 if (_stack.length === 0) {
19745 return null;
19746 }
19747 else {
19748 _removes = _stack.pop();
19749 _index = _stack.pop();
19750 return icuContainerIteratorNext();
19751 }
19752 }
19753 }
19754 return icuContainerIteratorStart;
19755}
19756
19757/**
19758 * @license
19759 * Copyright Google LLC All Rights Reserved.
19760 *
19761 * Use of this source code is governed by an MIT-style license that can be
19762 * found in the LICENSE file at https://angular.io/license
19763 */
19764/**
19765 * Converts `I18nCreateOpCodes` array into a human readable format.
19766 *
19767 * This function is attached to the `I18nCreateOpCodes.debug` property if `ngDevMode` is enabled.
19768 * This function provides a human readable view of the opcodes. This is useful when debugging the
19769 * application as well as writing more readable tests.
19770 *
19771 * @param this `I18nCreateOpCodes` if attached as a method.
19772 * @param opcodes `I18nCreateOpCodes` if invoked as a function.
19773 */
19774function i18nCreateOpCodesToString(opcodes) {
19775 const createOpCodes = opcodes || (Array.isArray(this) ? this : []);
19776 let lines = [];
19777 for (let i = 0; i < createOpCodes.length; i++) {
19778 const opCode = createOpCodes[i++];
19779 const text = createOpCodes[i];
19780 const isComment = (opCode & I18nCreateOpCode.COMMENT) === I18nCreateOpCode.COMMENT;
19781 const appendNow = (opCode & I18nCreateOpCode.APPEND_EAGERLY) === I18nCreateOpCode.APPEND_EAGERLY;
19782 const index = opCode >>> I18nCreateOpCode.SHIFT;
19783 lines.push(`lView[${index}] = document.${isComment ? 'createComment' : 'createText'}(${JSON.stringify(text)});`);
19784 if (appendNow) {
19785 lines.push(`parent.appendChild(lView[${index}]);`);
19786 }
19787 }
19788 return lines;
19789}
19790/**
19791 * Converts `I18nUpdateOpCodes` array into a human readable format.
19792 *
19793 * This function is attached to the `I18nUpdateOpCodes.debug` property if `ngDevMode` is enabled.
19794 * This function provides a human readable view of the opcodes. This is useful when debugging the
19795 * application as well as writing more readable tests.
19796 *
19797 * @param this `I18nUpdateOpCodes` if attached as a method.
19798 * @param opcodes `I18nUpdateOpCodes` if invoked as a function.
19799 */
19800function i18nUpdateOpCodesToString(opcodes) {
19801 const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : []));
19802 let lines = [];
19803 function consumeOpCode(value) {
19804 const ref = value >>> 2 /* SHIFT_REF */;
19805 const opCode = value & 3 /* MASK_OPCODE */;
19806 switch (opCode) {
19807 case 0 /* Text */:
19808 return `(lView[${ref}] as Text).textContent = $$$`;
19809 case 1 /* Attr */:
19810 const attrName = parser.consumeString();
19811 const sanitizationFn = parser.consumeFunction();
19812 const value = sanitizationFn ? `(${sanitizationFn})($$$)` : '$$$';
19813 return `(lView[${ref}] as Element).setAttribute('${attrName}', ${value})`;
19814 case 2 /* IcuSwitch */:
19815 return `icuSwitchCase(${ref}, $$$)`;
19816 case 3 /* IcuUpdate */:
19817 return `icuUpdateCase(${ref})`;
19818 }
19819 throw new Error('unexpected OpCode');
19820 }
19821 while (parser.hasMore()) {
19822 let mask = parser.consumeNumber();
19823 let size = parser.consumeNumber();
19824 const end = parser.i + size;
19825 const statements = [];
19826 let statement = '';
19827 while (parser.i < end) {
19828 let value = parser.consumeNumberOrString();
19829 if (typeof value === 'string') {
19830 statement += value;
19831 }
19832 else if (value < 0) {
19833 // Negative numbers are ref indexes
19834 // Here `i` refers to current binding index. It is to signify that the value is relative,
19835 // rather than absolute.
19836 statement += '${lView[i' + value + ']}';
19837 }
19838 else {
19839 // Positive numbers are operations.
19840 const opCodeText = consumeOpCode(value);
19841 statements.push(opCodeText.replace('$$$', '`' + statement + '`') + ';');
19842 statement = '';
19843 }
19844 }
19845 lines.push(`if (mask & 0b${mask.toString(2)}) { ${statements.join(' ')} }`);
19846 }
19847 return lines;
19848}
19849/**
19850 * Converts `I18nCreateOpCodes` array into a human readable format.
19851 *
19852 * This function is attached to the `I18nCreateOpCodes.debug` if `ngDevMode` is enabled. This
19853 * function provides a human readable view of the opcodes. This is useful when debugging the
19854 * application as well as writing more readable tests.
19855 *
19856 * @param this `I18nCreateOpCodes` if attached as a method.
19857 * @param opcodes `I18nCreateOpCodes` if invoked as a function.
19858 */
19859function icuCreateOpCodesToString(opcodes) {
19860 const parser = new OpCodeParser(opcodes || (Array.isArray(this) ? this : []));
19861 let lines = [];
19862 function consumeOpCode(opCode) {
19863 const parent = getParentFromIcuCreateOpCode(opCode);
19864 const ref = getRefFromIcuCreateOpCode(opCode);
19865 switch (getInstructionFromIcuCreateOpCode(opCode)) {
19866 case 0 /* AppendChild */:
19867 return `(lView[${parent}] as Element).appendChild(lView[${lastRef}])`;
19868 case 1 /* Attr */:
19869 return `(lView[${ref}] as Element).setAttribute("${parser.consumeString()}", "${parser.consumeString()}")`;
19870 }
19871 throw new Error('Unexpected OpCode: ' + getInstructionFromIcuCreateOpCode(opCode));
19872 }
19873 let lastRef = -1;
19874 while (parser.hasMore()) {
19875 let value = parser.consumeNumberStringOrMarker();
19876 if (value === ICU_MARKER) {
19877 const text = parser.consumeString();
19878 lastRef = parser.consumeNumber();
19879 lines.push(`lView[${lastRef}] = document.createComment("${text}")`);
19880 }
19881 else if (value === ELEMENT_MARKER) {
19882 const text = parser.consumeString();
19883 lastRef = parser.consumeNumber();
19884 lines.push(`lView[${lastRef}] = document.createElement("${text}")`);
19885 }
19886 else if (typeof value === 'string') {
19887 lastRef = parser.consumeNumber();
19888 lines.push(`lView[${lastRef}] = document.createTextNode("${value}")`);
19889 }
19890 else if (typeof value === 'number') {
19891 const line = consumeOpCode(value);
19892 line && lines.push(line);
19893 }
19894 else {
19895 throw new Error('Unexpected value');
19896 }
19897 }
19898 return lines;
19899}
19900/**
19901 * Converts `I18nRemoveOpCodes` array into a human readable format.
19902 *
19903 * This function is attached to the `I18nRemoveOpCodes.debug` if `ngDevMode` is enabled. This
19904 * function provides a human readable view of the opcodes. This is useful when debugging the
19905 * application as well as writing more readable tests.
19906 *
19907 * @param this `I18nRemoveOpCodes` if attached as a method.
19908 * @param opcodes `I18nRemoveOpCodes` if invoked as a function.
19909 */
19910function i18nRemoveOpCodesToString(opcodes) {
19911 const removeCodes = opcodes || (Array.isArray(this) ? this : []);
19912 let lines = [];
19913 for (let i = 0; i < removeCodes.length; i++) {
19914 const nodeOrIcuIndex = removeCodes[i];
19915 if (nodeOrIcuIndex > 0) {
19916 // Positive numbers are `RNode`s.
19917 lines.push(`remove(lView[${nodeOrIcuIndex}])`);
19918 }
19919 else {
19920 // Negative numbers are ICUs
19921 lines.push(`removeNestedICU(${~nodeOrIcuIndex})`);
19922 }
19923 }
19924 return lines;
19925}
19926class OpCodeParser {
19927 constructor(codes) {
19928 this.i = 0;
19929 this.codes = codes;
19930 }
19931 hasMore() {
19932 return this.i < this.codes.length;
19933 }
19934 consumeNumber() {
19935 let value = this.codes[this.i++];
19936 assertNumber(value, 'expecting number in OpCode');
19937 return value;
19938 }
19939 consumeString() {
19940 let value = this.codes[this.i++];
19941 assertString(value, 'expecting string in OpCode');
19942 return value;
19943 }
19944 consumeFunction() {
19945 let value = this.codes[this.i++];
19946 if (value === null || typeof value === 'function') {
19947 return value;
19948 }
19949 throw new Error('expecting function in OpCode');
19950 }
19951 consumeNumberOrString() {
19952 let value = this.codes[this.i++];
19953 if (typeof value === 'string') {
19954 return value;
19955 }
19956 assertNumber(value, 'expecting number or string in OpCode');
19957 return value;
19958 }
19959 consumeNumberStringOrMarker() {
19960 let value = this.codes[this.i++];
19961 if (typeof value === 'string' || typeof value === 'number' || value == ICU_MARKER ||
19962 value == ELEMENT_MARKER) {
19963 return value;
19964 }
19965 assertNumber(value, 'expecting number, string, ICU_MARKER or ELEMENT_MARKER in OpCode');
19966 return value;
19967 }
19968}
19969
19970/**
19971 * @license
19972 * Copyright Google LLC All Rights Reserved.
19973 *
19974 * Use of this source code is governed by an MIT-style license that can be
19975 * found in the LICENSE file at https://angular.io/license
19976 */
19977const BINDING_REGEXP = /�(\d+):?\d*�/gi;
19978const ICU_REGEXP = /({\s*�\d+:?\d*�\s*,\s*\S{6}\s*,[\s\S]*})/gi;
19979const NESTED_ICU = /�(\d+)�/;
19980const ICU_BLOCK_REGEXP = /^\s*(�\d+:?\d*�)\s*,\s*(select|plural)\s*,/;
19981const MARKER = `�`;
19982const SUBTEMPLATE_REGEXP = /�\/?\*(\d+:\d+)�/gi;
19983const PH_REGEXP = /�(\/?[#*]\d+):?\d*�/gi;
19984/**
19985 * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
19986 * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
19987 * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
19988 * and later on replaced by a space. We are re-implementing the same idea here, since translations
19989 * might contain this special character.
19990 */
19991const NGSP_UNICODE_REGEXP = /\uE500/g;
19992function replaceNgsp(value) {
19993 return value.replace(NGSP_UNICODE_REGEXP, ' ');
19994}
19995/**
19996 * Create dynamic nodes from i18n translation block.
19997 *
19998 * - Text nodes are created synchronously
19999 * - TNodes are linked into tree lazily
20000 *
20001 * @param tView Current `TView`
20002 * @parentTNodeIndex index to the parent TNode of this i18n block
20003 * @param lView Current `LView`
20004 * @param index Index of `ɵɵi18nStart` instruction.
20005 * @param message Message to translate.
20006 * @param subTemplateIndex Index into the sub template of message translation. (ie in case of
20007 * `ngIf`) (-1 otherwise)
20008 */
20009function i18nStartFirstCreatePass(tView, parentTNodeIndex, lView, index, message, subTemplateIndex) {
20010 const rootTNode = getCurrentParentTNode();
20011 const createOpCodes = [];
20012 const updateOpCodes = [];
20013 const existingTNodeStack = [[]];
20014 if (ngDevMode) {
20015 attachDebugGetter(createOpCodes, i18nCreateOpCodesToString);
20016 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
20017 }
20018 message = getTranslationForTemplate(message, subTemplateIndex);
20019 const msgParts = replaceNgsp(message).split(PH_REGEXP);
20020 for (let i = 0; i < msgParts.length; i++) {
20021 let value = msgParts[i];
20022 if ((i & 1) === 0) {
20023 // Even indexes are text (including bindings & ICU expressions)
20024 const parts = i18nParseTextIntoPartsAndICU(value);
20025 for (let j = 0; j < parts.length; j++) {
20026 let part = parts[j];
20027 if ((j & 1) === 0) {
20028 // `j` is odd therefore `part` is string
20029 const text = part;
20030 ngDevMode && assertString(text, 'Parsed ICU part should be string');
20031 if (text !== '') {
20032 i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodeStack[0], createOpCodes, updateOpCodes, lView, text);
20033 }
20034 }
20035 else {
20036 // `j` is Even therefor `part` is an `ICUExpression`
20037 const icuExpression = part;
20038 // Verify that ICU expression has the right shape. Translations might contain invalid
20039 // constructions (while original messages were correct), so ICU parsing at runtime may
20040 // not succeed (thus `icuExpression` remains a string).
20041 // Note: we intentionally retain the error here by not using `ngDevMode`, because
20042 // the value can change based on the locale and users aren't guaranteed to hit
20043 // an invalid string while they're developing.
20044 if (typeof icuExpression !== 'object') {
20045 throw new Error(`Unable to parse ICU expression in "${message}" message.`);
20046 }
20047 const icuContainerTNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodeStack[0], lView, createOpCodes, ngDevMode ? `ICU ${index}:${icuExpression.mainBinding}` : '', true);
20048 const icuNodeIndex = icuContainerTNode.index;
20049 ngDevMode &&
20050 assertGreaterThanOrEqual(icuNodeIndex, HEADER_OFFSET, 'Index must be in absolute LView offset');
20051 icuStart(tView, lView, updateOpCodes, parentTNodeIndex, icuExpression, icuNodeIndex);
20052 }
20053 }
20054 }
20055 else {
20056 // Odd indexes are placeholders (elements and sub-templates)
20057 // At this point value is something like: '/#1:2' (originally coming from '�/#1:2�')
20058 const isClosing = value.charCodeAt(0) === 47 /* SLASH */;
20059 const type = value.charCodeAt(isClosing ? 1 : 0);
20060 ngDevMode && assertOneOf(type, 42 /* STAR */, 35 /* HASH */);
20061 const index = HEADER_OFFSET + Number.parseInt(value.substring((isClosing ? 2 : 1)));
20062 if (isClosing) {
20063 existingTNodeStack.shift();
20064 setCurrentTNode(getCurrentParentTNode(), false);
20065 }
20066 else {
20067 const tNode = createTNodePlaceholder(tView, existingTNodeStack[0], index);
20068 existingTNodeStack.unshift([]);
20069 setCurrentTNode(tNode, true);
20070 }
20071 }
20072 }
20073 tView.data[index] = {
20074 create: createOpCodes,
20075 update: updateOpCodes,
20076 };
20077}
20078/**
20079 * Allocate space in i18n Range add create OpCode instruction to crete a text or comment node.
20080 *
20081 * @param tView Current `TView` needed to allocate space in i18n range.
20082 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will be
20083 * added as part of the `i18nStart` instruction or as part of the `TNode.insertBeforeIndex`.
20084 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.
20085 * @param lView Current `LView` needed to allocate space in i18n range.
20086 * @param createOpCodes Array storing `I18nCreateOpCodes` where new opCodes will be added.
20087 * @param text Text to be added when the `Text` or `Comment` node will be created.
20088 * @param isICU true if a `Comment` node for ICU (instead of `Text`) node should be created.
20089 */
20090function createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, text, isICU) {
20091 const i18nNodeIdx = allocExpando(tView, lView, 1, null);
20092 let opCode = i18nNodeIdx << I18nCreateOpCode.SHIFT;
20093 let parentTNode = getCurrentParentTNode();
20094 if (rootTNode === parentTNode) {
20095 // FIXME(misko): A null `parentTNode` should represent when we fall of the `LView` boundary.
20096 // (there is no parent), but in some circumstances (because we are inconsistent about how we set
20097 // `previousOrParentTNode`) it could point to `rootTNode` So this is a work around.
20098 parentTNode = null;
20099 }
20100 if (parentTNode === null) {
20101 // If we don't have a parent that means that we can eagerly add nodes.
20102 // If we have a parent than these nodes can't be added now (as the parent has not been created
20103 // yet) and instead the `parentTNode` is responsible for adding it. See
20104 // `TNode.insertBeforeIndex`
20105 opCode |= I18nCreateOpCode.APPEND_EAGERLY;
20106 }
20107 if (isICU) {
20108 opCode |= I18nCreateOpCode.COMMENT;
20109 ensureIcuContainerVisitorLoaded(loadIcuContainerVisitor);
20110 }
20111 createOpCodes.push(opCode, text === null ? '' : text);
20112 // We store `{{?}}` so that when looking at debug `TNodeType.template` we can see where the
20113 // bindings are.
20114 const tNode = createTNodeAtIndex(tView, i18nNodeIdx, isICU ? 32 /* Icu */ : 1 /* Text */, text === null ? (ngDevMode ? '{{?}}' : '') : text, null);
20115 addTNodeAndUpdateInsertBeforeIndex(existingTNodes, tNode);
20116 const tNodeIdx = tNode.index;
20117 setCurrentTNode(tNode, false /* Text nodes are self closing */);
20118 if (parentTNode !== null && rootTNode !== parentTNode) {
20119 // We are a child of deeper node (rather than a direct child of `i18nStart` instruction.)
20120 // We have to make sure to add ourselves to the parent.
20121 setTNodeInsertBeforeIndex(parentTNode, tNodeIdx);
20122 }
20123 return tNode;
20124}
20125/**
20126 * Processes text node in i18n block.
20127 *
20128 * Text nodes can have:
20129 * - Create instruction in `createOpCodes` for creating the text node.
20130 * - Allocate spec for text node in i18n range of `LView`
20131 * - If contains binding:
20132 * - bindings => allocate space in i18n range of `LView` to store the binding value.
20133 * - populate `updateOpCodes` with update instructions.
20134 *
20135 * @param tView Current `TView`
20136 * @param rootTNode Root `TNode` of the i18n block. This node determines if the new TNode will
20137 * be added as part of the `i18nStart` instruction or as part of the
20138 * `TNode.insertBeforeIndex`.
20139 * @param existingTNodes internal state for `addTNodeAndUpdateInsertBeforeIndex`.
20140 * @param createOpCodes Location where the creation OpCodes will be stored.
20141 * @param lView Current `LView`
20142 * @param text The translated text (which may contain binding)
20143 */
20144function i18nStartFirstCreatePassProcessTextNode(tView, rootTNode, existingTNodes, createOpCodes, updateOpCodes, lView, text) {
20145 const hasBinding = text.match(BINDING_REGEXP);
20146 const tNode = createTNodeAndAddOpCode(tView, rootTNode, existingTNodes, lView, createOpCodes, hasBinding ? null : text, false);
20147 if (hasBinding) {
20148 generateBindingUpdateOpCodes(updateOpCodes, text, tNode.index, null, 0, null);
20149 }
20150}
20151/**
20152 * See `i18nAttributes` above.
20153 */
20154function i18nAttributesFirstPass(tView, index, values) {
20155 const previousElement = getCurrentTNode();
20156 const previousElementIndex = previousElement.index;
20157 const updateOpCodes = [];
20158 if (ngDevMode) {
20159 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
20160 }
20161 if (tView.firstCreatePass && tView.data[index] === null) {
20162 for (let i = 0; i < values.length; i += 2) {
20163 const attrName = values[i];
20164 const message = values[i + 1];
20165 if (message !== '') {
20166 // Check if attribute value contains an ICU and throw an error if that's the case.
20167 // ICUs in element attributes are not supported.
20168 // Note: we intentionally retain the error here by not using `ngDevMode`, because
20169 // the `value` can change based on the locale and users aren't guaranteed to hit
20170 // an invalid string while they're developing.
20171 if (ICU_REGEXP.test(message)) {
20172 throw new Error(`ICU expressions are not supported in attributes. Message: "${message}".`);
20173 }
20174 // i18n attributes that hit this code path are guaranteed to have bindings, because
20175 // the compiler treats static i18n attributes as regular attribute bindings.
20176 // Since this may not be the first i18n attribute on this element we need to pass in how
20177 // many previous bindings there have already been.
20178 generateBindingUpdateOpCodes(updateOpCodes, message, previousElementIndex, attrName, countBindings(updateOpCodes), null);
20179 }
20180 }
20181 tView.data[index] = updateOpCodes;
20182 }
20183}
20184/**
20185 * Generate the OpCodes to update the bindings of a string.
20186 *
20187 * @param updateOpCodes Place where the update opcodes will be stored.
20188 * @param str The string containing the bindings.
20189 * @param destinationNode Index of the destination node which will receive the binding.
20190 * @param attrName Name of the attribute, if the string belongs to an attribute.
20191 * @param sanitizeFn Sanitization function used to sanitize the string after update, if necessary.
20192 * @param bindingStart The lView index of the next expression that can be bound via an opCode.
20193 * @returns The mask value for these bindings
20194 */
20195function generateBindingUpdateOpCodes(updateOpCodes, str, destinationNode, attrName, bindingStart, sanitizeFn) {
20196 ngDevMode &&
20197 assertGreaterThanOrEqual(destinationNode, HEADER_OFFSET, 'Index must be in absolute LView offset');
20198 const maskIndex = updateOpCodes.length; // Location of mask
20199 const sizeIndex = maskIndex + 1; // location of size for skipping
20200 updateOpCodes.push(null, null); // Alloc space for mask and size
20201 const startIndex = maskIndex + 2; // location of first allocation.
20202 if (ngDevMode) {
20203 attachDebugGetter(updateOpCodes, i18nUpdateOpCodesToString);
20204 }
20205 const textParts = str.split(BINDING_REGEXP);
20206 let mask = 0;
20207 for (let j = 0; j < textParts.length; j++) {
20208 const textValue = textParts[j];
20209 if (j & 1) {
20210 // Odd indexes are bindings
20211 const bindingIndex = bindingStart + parseInt(textValue, 10);
20212 updateOpCodes.push(-1 - bindingIndex);
20213 mask = mask | toMaskBit(bindingIndex);
20214 }
20215 else if (textValue !== '') {
20216 // Even indexes are text
20217 updateOpCodes.push(textValue);
20218 }
20219 }
20220 updateOpCodes.push(destinationNode << 2 /* SHIFT_REF */ |
20221 (attrName ? 1 /* Attr */ : 0 /* Text */));
20222 if (attrName) {
20223 updateOpCodes.push(attrName, sanitizeFn);
20224 }
20225 updateOpCodes[maskIndex] = mask;
20226 updateOpCodes[sizeIndex] = updateOpCodes.length - startIndex;
20227 return mask;
20228}
20229/**
20230 * Count the number of bindings in the given `opCodes`.
20231 *
20232 * It could be possible to speed this up, by passing the number of bindings found back from
20233 * `generateBindingUpdateOpCodes()` to `i18nAttributesFirstPass()` but this would then require more
20234 * complexity in the code and/or transient objects to be created.
20235 *
20236 * Since this function is only called once when the template is instantiated, is trivial in the
20237 * first instance (since `opCodes` will be an empty array), and it is not common for elements to
20238 * contain multiple i18n bound attributes, it seems like this is a reasonable compromise.
20239 */
20240function countBindings(opCodes) {
20241 let count = 0;
20242 for (let i = 0; i < opCodes.length; i++) {
20243 const opCode = opCodes[i];
20244 // Bindings are negative numbers.
20245 if (typeof opCode === 'number' && opCode < 0) {
20246 count++;
20247 }
20248 }
20249 return count;
20250}
20251/**
20252 * Convert binding index to mask bit.
20253 *
20254 * Each index represents a single bit on the bit-mask. Because bit-mask only has 32 bits, we make
20255 * the 32nd bit share all masks for all bindings higher than 32. Since it is extremely rare to
20256 * have more than 32 bindings this will be hit very rarely. The downside of hitting this corner
20257 * case is that we will execute binding code more often than necessary. (penalty of performance)
20258 */
20259function toMaskBit(bindingIndex) {
20260 return 1 << Math.min(bindingIndex, 31);
20261}
20262function isRootTemplateMessage(subTemplateIndex) {
20263 return subTemplateIndex === -1;
20264}
20265/**
20266 * Removes everything inside the sub-templates of a message.
20267 */
20268function removeInnerTemplateTranslation(message) {
20269 let match;
20270 let res = '';
20271 let index = 0;
20272 let inTemplate = false;
20273 let tagMatched;
20274 while ((match = SUBTEMPLATE_REGEXP.exec(message)) !== null) {
20275 if (!inTemplate) {
20276 res += message.substring(index, match.index + match[0].length);
20277 tagMatched = match[1];
20278 inTemplate = true;
20279 }
20280 else {
20281 if (match[0] === `${MARKER}/*${tagMatched}${MARKER}`) {
20282 index = match.index;
20283 inTemplate = false;
20284 }
20285 }
20286 }
20287 ngDevMode &&
20288 assertEqual(inTemplate, false, `Tag mismatch: unable to find the end of the sub-template in the translation "${message}"`);
20289 res += message.substr(index);
20290 return res;
20291}
20292/**
20293 * Extracts a part of a message and removes the rest.
20294 *
20295 * This method is used for extracting a part of the message associated with a template. A
20296 * translated message can span multiple templates.
20297 *
20298 * Example:
20299 * ```
20300 * <div i18n>Translate <span *ngIf>me</span>!</div>
20301 * ```
20302 *
20303 * @param message The message to crop
20304 * @param subTemplateIndex Index of the sub-template to extract. If undefined it returns the
20305 * external template and removes all sub-templates.
20306 */
20307function getTranslationForTemplate(message, subTemplateIndex) {
20308 if (isRootTemplateMessage(subTemplateIndex)) {
20309 // We want the root template message, ignore all sub-templates
20310 return removeInnerTemplateTranslation(message);
20311 }
20312 else {
20313 // We want a specific sub-template
20314 const start = message.indexOf(`:${subTemplateIndex}${MARKER}`) + 2 + subTemplateIndex.toString().length;
20315 const end = message.search(new RegExp(`${MARKER}\\/\\*\\d+:${subTemplateIndex}${MARKER}`));
20316 return removeInnerTemplateTranslation(message.substring(start, end));
20317 }
20318}
20319/**
20320 * Generate the OpCodes for ICU expressions.
20321 *
20322 * @param icuExpression
20323 * @param index Index where the anchor is stored and an optional `TIcuContainerNode`
20324 * - `lView[anchorIdx]` points to a `Comment` node representing the anchor for the ICU.
20325 * - `tView.data[anchorIdx]` points to the `TIcuContainerNode` if ICU is root (`null` otherwise)
20326 */
20327function icuStart(tView, lView, updateOpCodes, parentIdx, icuExpression, anchorIdx) {
20328 ngDevMode && assertDefined(icuExpression, 'ICU expression must be defined');
20329 let bindingMask = 0;
20330 const tIcu = {
20331 type: icuExpression.type,
20332 currentCaseLViewIndex: allocExpando(tView, lView, 1, null),
20333 anchorIdx,
20334 cases: [],
20335 create: [],
20336 remove: [],
20337 update: []
20338 };
20339 addUpdateIcuSwitch(updateOpCodes, icuExpression, anchorIdx);
20340 setTIcu(tView, anchorIdx, tIcu);
20341 const values = icuExpression.values;
20342 for (let i = 0; i < values.length; i++) {
20343 // Each value is an array of strings & other ICU expressions
20344 const valueArr = values[i];
20345 const nestedIcus = [];
20346 for (let j = 0; j < valueArr.length; j++) {
20347 const value = valueArr[j];
20348 if (typeof value !== 'string') {
20349 // It is an nested ICU expression
20350 const icuIndex = nestedIcus.push(value) - 1;
20351 // Replace nested ICU expression by a comment node
20352 valueArr[j] = `<!--�${icuIndex}�-->`;
20353 }
20354 }
20355 bindingMask = parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, icuExpression.cases[i], valueArr.join(''), nestedIcus) |
20356 bindingMask;
20357 }
20358 if (bindingMask) {
20359 addUpdateIcuUpdate(updateOpCodes, bindingMask, anchorIdx);
20360 }
20361}
20362/**
20363 * Parses text containing an ICU expression and produces a JSON object for it.
20364 * Original code from closure library, modified for Angular.
20365 *
20366 * @param pattern Text containing an ICU expression that needs to be parsed.
20367 *
20368 */
20369function parseICUBlock(pattern) {
20370 const cases = [];
20371 const values = [];
20372 let icuType = 1 /* plural */;
20373 let mainBinding = 0;
20374 pattern = pattern.replace(ICU_BLOCK_REGEXP, function (str, binding, type) {
20375 if (type === 'select') {
20376 icuType = 0 /* select */;
20377 }
20378 else {
20379 icuType = 1 /* plural */;
20380 }
20381 mainBinding = parseInt(binding.substr(1), 10);
20382 return '';
20383 });
20384 const parts = i18nParseTextIntoPartsAndICU(pattern);
20385 // Looking for (key block)+ sequence. One of the keys has to be "other".
20386 for (let pos = 0; pos < parts.length;) {
20387 let key = parts[pos++].trim();
20388 if (icuType === 1 /* plural */) {
20389 // Key can be "=x", we just want "x"
20390 key = key.replace(/\s*(?:=)?(\w+)\s*/, '$1');
20391 }
20392 if (key.length) {
20393 cases.push(key);
20394 }
20395 const blocks = i18nParseTextIntoPartsAndICU(parts[pos++]);
20396 if (cases.length > values.length) {
20397 values.push(blocks);
20398 }
20399 }
20400 // TODO(ocombe): support ICU expressions in attributes, see #21615
20401 return { type: icuType, mainBinding: mainBinding, cases, values };
20402}
20403/**
20404 * Breaks pattern into strings and top level {...} blocks.
20405 * Can be used to break a message into text and ICU expressions, or to break an ICU expression
20406 * into keys and cases. Original code from closure library, modified for Angular.
20407 *
20408 * @param pattern (sub)Pattern to be broken.
20409 * @returns An `Array<string|IcuExpression>` where:
20410 * - odd positions: `string` => text between ICU expressions
20411 * - even positions: `ICUExpression` => ICU expression parsed into `ICUExpression` record.
20412 */
20413function i18nParseTextIntoPartsAndICU(pattern) {
20414 if (!pattern) {
20415 return [];
20416 }
20417 let prevPos = 0;
20418 const braceStack = [];
20419 const results = [];
20420 const braces = /[{}]/g;
20421 // lastIndex doesn't get set to 0 so we have to.
20422 braces.lastIndex = 0;
20423 let match;
20424 while (match = braces.exec(pattern)) {
20425 const pos = match.index;
20426 if (match[0] == '}') {
20427 braceStack.pop();
20428 if (braceStack.length == 0) {
20429 // End of the block.
20430 const block = pattern.substring(prevPos, pos);
20431 if (ICU_BLOCK_REGEXP.test(block)) {
20432 results.push(parseICUBlock(block));
20433 }
20434 else {
20435 results.push(block);
20436 }
20437 prevPos = pos + 1;
20438 }
20439 }
20440 else {
20441 if (braceStack.length == 0) {
20442 const substring = pattern.substring(prevPos, pos);
20443 results.push(substring);
20444 prevPos = pos + 1;
20445 }
20446 braceStack.push('{');
20447 }
20448 }
20449 const substring = pattern.substring(prevPos);
20450 results.push(substring);
20451 return results;
20452}
20453/**
20454 * Parses a node, its children and its siblings, and generates the mutate & update OpCodes.
20455 *
20456 */
20457function parseIcuCase(tView, tIcu, lView, updateOpCodes, parentIdx, caseName, unsafeCaseHtml, nestedIcus) {
20458 const create = [];
20459 const remove = [];
20460 const update = [];
20461 if (ngDevMode) {
20462 attachDebugGetter(create, icuCreateOpCodesToString);
20463 attachDebugGetter(remove, i18nRemoveOpCodesToString);
20464 attachDebugGetter(update, i18nUpdateOpCodesToString);
20465 }
20466 tIcu.cases.push(caseName);
20467 tIcu.create.push(create);
20468 tIcu.remove.push(remove);
20469 tIcu.update.push(update);
20470 const inertBodyHelper = getInertBodyHelper(getDocument());
20471 const inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeCaseHtml);
20472 ngDevMode && assertDefined(inertBodyElement, 'Unable to generate inert body element');
20473 const inertRootNode = getTemplateContent(inertBodyElement) || inertBodyElement;
20474 if (inertRootNode) {
20475 return walkIcuTree(tView, tIcu, lView, updateOpCodes, create, remove, update, inertRootNode, parentIdx, nestedIcus, 0);
20476 }
20477 else {
20478 return 0;
20479 }
20480}
20481function walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, parentNode, parentIdx, nestedIcus, depth) {
20482 let bindingMask = 0;
20483 let currentNode = parentNode.firstChild;
20484 while (currentNode) {
20485 const newIndex = allocExpando(tView, lView, 1, null);
20486 switch (currentNode.nodeType) {
20487 case Node.ELEMENT_NODE:
20488 const element = currentNode;
20489 const tagName = element.tagName.toLowerCase();
20490 if (VALID_ELEMENTS.hasOwnProperty(tagName)) {
20491 addCreateNodeAndAppend(create, ELEMENT_MARKER, tagName, parentIdx, newIndex);
20492 tView.data[newIndex] = tagName;
20493 const elAttrs = element.attributes;
20494 for (let i = 0; i < elAttrs.length; i++) {
20495 const attr = elAttrs.item(i);
20496 const lowerAttrName = attr.name.toLowerCase();
20497 const hasBinding = !!attr.value.match(BINDING_REGEXP);
20498 // we assume the input string is safe, unless it's using a binding
20499 if (hasBinding) {
20500 if (VALID_ATTRS.hasOwnProperty(lowerAttrName)) {
20501 if (URI_ATTRS[lowerAttrName]) {
20502 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, _sanitizeUrl);
20503 }
20504 else if (SRCSET_ATTRS[lowerAttrName]) {
20505 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, sanitizeSrcset);
20506 }
20507 else {
20508 generateBindingUpdateOpCodes(update, attr.value, newIndex, attr.name, 0, null);
20509 }
20510 }
20511 else {
20512 ngDevMode &&
20513 console.warn(`WARNING: ignoring unsafe attribute value ` +
20514 `${lowerAttrName} on element ${tagName} ` +
20515 `(see https://g.co/ng/security#xss)`);
20516 }
20517 }
20518 else {
20519 addCreateAttribute(create, newIndex, attr);
20520 }
20521 }
20522 // Parse the children of this node (if any)
20523 bindingMask = walkIcuTree(tView, tIcu, lView, sharedUpdateOpCodes, create, remove, update, currentNode, newIndex, nestedIcus, depth + 1) |
20524 bindingMask;
20525 addRemoveNode(remove, newIndex, depth);
20526 }
20527 break;
20528 case Node.TEXT_NODE:
20529 const value = currentNode.textContent || '';
20530 const hasBinding = value.match(BINDING_REGEXP);
20531 addCreateNodeAndAppend(create, null, hasBinding ? '' : value, parentIdx, newIndex);
20532 addRemoveNode(remove, newIndex, depth);
20533 if (hasBinding) {
20534 bindingMask =
20535 generateBindingUpdateOpCodes(update, value, newIndex, null, 0, null) | bindingMask;
20536 }
20537 break;
20538 case Node.COMMENT_NODE:
20539 // Check if the comment node is a placeholder for a nested ICU
20540 const isNestedIcu = NESTED_ICU.exec(currentNode.textContent || '');
20541 if (isNestedIcu) {
20542 const nestedIcuIndex = parseInt(isNestedIcu[1], 10);
20543 const icuExpression = nestedIcus[nestedIcuIndex];
20544 // Create the comment node that will anchor the ICU expression
20545 addCreateNodeAndAppend(create, ICU_MARKER, ngDevMode ? `nested ICU ${nestedIcuIndex}` : '', parentIdx, newIndex);
20546 icuStart(tView, lView, sharedUpdateOpCodes, parentIdx, icuExpression, newIndex);
20547 addRemoveNestedIcu(remove, newIndex, depth);
20548 }
20549 break;
20550 }
20551 currentNode = currentNode.nextSibling;
20552 }
20553 return bindingMask;
20554}
20555function addRemoveNode(remove, index, depth) {
20556 if (depth === 0) {
20557 remove.push(index);
20558 }
20559}
20560function addRemoveNestedIcu(remove, index, depth) {
20561 if (depth === 0) {
20562 remove.push(~index); // remove ICU at `index`
20563 remove.push(index); // remove ICU comment at `index`
20564 }
20565}
20566function addUpdateIcuSwitch(update, icuExpression, index) {
20567 update.push(toMaskBit(icuExpression.mainBinding), 2, -1 - icuExpression.mainBinding, index << 2 /* SHIFT_REF */ | 2 /* IcuSwitch */);
20568}
20569function addUpdateIcuUpdate(update, bindingMask, index) {
20570 update.push(bindingMask, 1, index << 2 /* SHIFT_REF */ | 3 /* IcuUpdate */);
20571}
20572function addCreateNodeAndAppend(create, marker, text, appendToParentIdx, createAtIdx) {
20573 if (marker !== null) {
20574 create.push(marker);
20575 }
20576 create.push(text, createAtIdx, icuCreateOpCode(0 /* AppendChild */, appendToParentIdx, createAtIdx));
20577}
20578function addCreateAttribute(create, newIndex, attr) {
20579 create.push(newIndex << 1 /* SHIFT_REF */ | 1 /* Attr */, attr.name, attr.value);
20580}
20581
20582/**
20583 * @license
20584 * Copyright Google LLC All Rights Reserved.
20585 *
20586 * Use of this source code is governed by an MIT-style license that can be
20587 * found in the LICENSE file at https://angular.io/license
20588 */
20589// i18nPostprocess consts
20590const ROOT_TEMPLATE_ID = 0;
20591const PP_MULTI_VALUE_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]/;
20592const PP_PLACEHOLDERS_REGEXP = /\[(�.+?�?)\]|(�\/?\*\d+:\d+�)/g;
20593const PP_ICU_VARS_REGEXP = /({\s*)(VAR_(PLURAL|SELECT)(_\d+)?)(\s*,)/g;
20594const PP_ICU_PLACEHOLDERS_REGEXP = /{([A-Z0-9_]+)}/g;
20595const PP_ICUS_REGEXP = /�I18N_EXP_(ICU(_\d+)?)�/g;
20596const PP_CLOSE_TEMPLATE_REGEXP = /\/\*/;
20597const PP_TEMPLATE_ID_REGEXP = /\d+\:(\d+)/;
20598/**
20599 * Handles message string post-processing for internationalization.
20600 *
20601 * Handles message string post-processing by transforming it from intermediate
20602 * format (that might contain some markers that we need to replace) to the final
20603 * form, consumable by i18nStart instruction. Post processing steps include:
20604 *
20605 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
20606 * 2. Replace all ICU vars (like "VAR_PLURAL")
20607 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
20608 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
20609 * in case multiple ICUs have the same placeholder name
20610 *
20611 * @param message Raw translation string for post processing
20612 * @param replacements Set of replacements that should be applied
20613 *
20614 * @returns Transformed string that can be consumed by i18nStart instruction
20615 *
20616 * @codeGenApi
20617 */
20618function i18nPostprocess(message, replacements = {}) {
20619 /**
20620 * Step 1: resolve all multi-value placeholders like [�#5�|�*1:1��#2:1�|�#4:1�]
20621 *
20622 * Note: due to the way we process nested templates (BFS), multi-value placeholders are typically
20623 * grouped by templates, for example: [�#5�|�#6�|�#1:1�|�#3:2�] where �#5� and �#6� belong to root
20624 * template, �#1:1� belong to nested template with index 1 and �#1:2� - nested template with index
20625 * 3. However in real templates the order might be different: i.e. �#1:1� and/or �#3:2� may go in
20626 * front of �#6�. The post processing step restores the right order by keeping track of the
20627 * template id stack and looks for placeholders that belong to the currently active template.
20628 */
20629 let result = message;
20630 if (PP_MULTI_VALUE_PLACEHOLDERS_REGEXP.test(message)) {
20631 const matches = {};
20632 const templateIdsStack = [ROOT_TEMPLATE_ID];
20633 result = result.replace(PP_PLACEHOLDERS_REGEXP, (m, phs, tmpl) => {
20634 const content = phs || tmpl;
20635 const placeholders = matches[content] || [];
20636 if (!placeholders.length) {
20637 content.split('|').forEach((placeholder) => {
20638 const match = placeholder.match(PP_TEMPLATE_ID_REGEXP);
20639 const templateId = match ? parseInt(match[1], 10) : ROOT_TEMPLATE_ID;
20640 const isCloseTemplateTag = PP_CLOSE_TEMPLATE_REGEXP.test(placeholder);
20641 placeholders.push([templateId, isCloseTemplateTag, placeholder]);
20642 });
20643 matches[content] = placeholders;
20644 }
20645 if (!placeholders.length) {
20646 throw new Error(`i18n postprocess: unmatched placeholder - ${content}`);
20647 }
20648 const currentTemplateId = templateIdsStack[templateIdsStack.length - 1];
20649 let idx = 0;
20650 // find placeholder index that matches current template id
20651 for (let i = 0; i < placeholders.length; i++) {
20652 if (placeholders[i][0] === currentTemplateId) {
20653 idx = i;
20654 break;
20655 }
20656 }
20657 // update template id stack based on the current tag extracted
20658 const [templateId, isCloseTemplateTag, placeholder] = placeholders[idx];
20659 if (isCloseTemplateTag) {
20660 templateIdsStack.pop();
20661 }
20662 else if (currentTemplateId !== templateId) {
20663 templateIdsStack.push(templateId);
20664 }
20665 // remove processed tag from the list
20666 placeholders.splice(idx, 1);
20667 return placeholder;
20668 });
20669 }
20670 // return current result if no replacements specified
20671 if (!Object.keys(replacements).length) {
20672 return result;
20673 }
20674 /**
20675 * Step 2: replace all ICU vars (like "VAR_PLURAL")
20676 */
20677 result = result.replace(PP_ICU_VARS_REGEXP, (match, start, key, _type, _idx, end) => {
20678 return replacements.hasOwnProperty(key) ? `${start}${replacements[key]}${end}` : match;
20679 });
20680 /**
20681 * Step 3: replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
20682 */
20683 result = result.replace(PP_ICU_PLACEHOLDERS_REGEXP, (match, key) => {
20684 return replacements.hasOwnProperty(key) ? replacements[key] : match;
20685 });
20686 /**
20687 * Step 4: replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�) in case
20688 * multiple ICUs have the same placeholder name
20689 */
20690 result = result.replace(PP_ICUS_REGEXP, (match, key) => {
20691 if (replacements.hasOwnProperty(key)) {
20692 const list = replacements[key];
20693 if (!list.length) {
20694 throw new Error(`i18n postprocess: unmatched ICU - ${match} with key: ${key}`);
20695 }
20696 return list.shift();
20697 }
20698 return match;
20699 });
20700 return result;
20701}
20702
20703/**
20704 * @license
20705 * Copyright Google LLC All Rights Reserved.
20706 *
20707 * Use of this source code is governed by an MIT-style license that can be
20708 * found in the LICENSE file at https://angular.io/license
20709 */
20710/**
20711 * Marks a block of text as translatable.
20712 *
20713 * The instructions `i18nStart` and `i18nEnd` mark the translation block in the template.
20714 * The translation `message` is the value which is locale specific. The translation string may
20715 * contain placeholders which associate inner elements and sub-templates within the translation.
20716 *
20717 * The translation `message` placeholders are:
20718 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
20719 * interpolated into. The placeholder `index` points to the expression binding index. An optional
20720 * `block` that matches the sub-template in which it was declared.
20721 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning
20722 * and end of DOM element that were embedded in the original translation block. The placeholder
20723 * `index` points to the element index in the template instructions set. An optional `block` that
20724 * matches the sub-template in which it was declared.
20725 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
20726 * split up and translated separately in each angular template function. The `index` points to the
20727 * `template` instruction index. A `block` that matches the sub-template in which it was declared.
20728 *
20729 * @param index A unique index of the translation in the static block.
20730 * @param messageIndex An index of the translation message from the `def.consts` array.
20731 * @param subTemplateIndex Optional sub-template index in the `message`.
20732 *
20733 * @codeGenApi
20734 */
20735function ɵɵi18nStart(index, messageIndex, subTemplateIndex = -1) {
20736 const tView = getTView();
20737 const lView = getLView();
20738 const adjustedIndex = HEADER_OFFSET + index;
20739 ngDevMode && assertDefined(tView, `tView should be defined`);
20740 const message = getConstant(tView.consts, messageIndex);
20741 const parentTNode = getCurrentParentTNode();
20742 if (tView.firstCreatePass) {
20743 i18nStartFirstCreatePass(tView, parentTNode === null ? 0 : parentTNode.index, lView, adjustedIndex, message, subTemplateIndex);
20744 }
20745 const tI18n = tView.data[adjustedIndex];
20746 const sameViewParentTNode = parentTNode === lView[T_HOST] ? null : parentTNode;
20747 const parentRNode = getClosestRElement(tView, sameViewParentTNode, lView);
20748 // If `parentTNode` is an `ElementContainer` than it has `<!--ng-container--->`.
20749 // When we do inserts we have to make sure to insert in front of `<!--ng-container--->`.
20750 const insertInFrontOf = parentTNode && (parentTNode.type & 8 /* ElementContainer */) ?
20751 lView[parentTNode.index] :
20752 null;
20753 applyCreateOpCodes(lView, tI18n.create, parentRNode, insertInFrontOf);
20754 setInI18nBlock(true);
20755}
20756/**
20757 * Translates a translation block marked by `i18nStart` and `i18nEnd`. It inserts the text/ICU nodes
20758 * into the render tree, moves the placeholder nodes and removes the deleted nodes.
20759 *
20760 * @codeGenApi
20761 */
20762function ɵɵi18nEnd() {
20763 setInI18nBlock(false);
20764}
20765/**
20766 *
20767 * Use this instruction to create a translation block that doesn't contain any placeholder.
20768 * It calls both {@link i18nStart} and {@link i18nEnd} in one instruction.
20769 *
20770 * The translation `message` is the value which is locale specific. The translation string may
20771 * contain placeholders which associate inner elements and sub-templates within the translation.
20772 *
20773 * The translation `message` placeholders are:
20774 * - `�{index}(:{block})�`: *Binding Placeholder*: Marks a location where an expression will be
20775 * interpolated into. The placeholder `index` points to the expression binding index. An optional
20776 * `block` that matches the sub-template in which it was declared.
20777 * - `�#{index}(:{block})�`/`�/#{index}(:{block})�`: *Element Placeholder*: Marks the beginning
20778 * and end of DOM element that were embedded in the original translation block. The placeholder
20779 * `index` points to the element index in the template instructions set. An optional `block` that
20780 * matches the sub-template in which it was declared.
20781 * - `�*{index}:{block}�`/`�/*{index}:{block}�`: *Sub-template Placeholder*: Sub-templates must be
20782 * split up and translated separately in each angular template function. The `index` points to the
20783 * `template` instruction index. A `block` that matches the sub-template in which it was declared.
20784 *
20785 * @param index A unique index of the translation in the static block.
20786 * @param messageIndex An index of the translation message from the `def.consts` array.
20787 * @param subTemplateIndex Optional sub-template index in the `message`.
20788 *
20789 * @codeGenApi
20790 */
20791function ɵɵi18n(index, messageIndex, subTemplateIndex) {
20792 ɵɵi18nStart(index, messageIndex, subTemplateIndex);
20793 ɵɵi18nEnd();
20794}
20795/**
20796 * Marks a list of attributes as translatable.
20797 *
20798 * @param index A unique index in the static block
20799 * @param values
20800 *
20801 * @codeGenApi
20802 */
20803function ɵɵi18nAttributes(index, attrsIndex) {
20804 const tView = getTView();
20805 ngDevMode && assertDefined(tView, `tView should be defined`);
20806 const attrs = getConstant(tView.consts, attrsIndex);
20807 i18nAttributesFirstPass(tView, index + HEADER_OFFSET, attrs);
20808}
20809/**
20810 * Stores the values of the bindings during each update cycle in order to determine if we need to
20811 * update the translated nodes.
20812 *
20813 * @param value The binding's value
20814 * @returns This function returns itself so that it may be chained
20815 * (e.g. `i18nExp(ctx.name)(ctx.title)`)
20816 *
20817 * @codeGenApi
20818 */
20819function ɵɵi18nExp(value) {
20820 const lView = getLView();
20821 setMaskBit(bindingUpdated(lView, nextBindingIndex(), value));
20822 return ɵɵi18nExp;
20823}
20824/**
20825 * Updates a translation block or an i18n attribute when the bindings have changed.
20826 *
20827 * @param index Index of either {@link i18nStart} (translation block) or {@link i18nAttributes}
20828 * (i18n attribute) on which it should update the content.
20829 *
20830 * @codeGenApi
20831 */
20832function ɵɵi18nApply(index) {
20833 applyI18n(getTView(), getLView(), index + HEADER_OFFSET);
20834}
20835/**
20836 * Handles message string post-processing for internationalization.
20837 *
20838 * Handles message string post-processing by transforming it from intermediate
20839 * format (that might contain some markers that we need to replace) to the final
20840 * form, consumable by i18nStart instruction. Post processing steps include:
20841 *
20842 * 1. Resolve all multi-value cases (like [�*1:1��#2:1�|�#4:1�|�5�])
20843 * 2. Replace all ICU vars (like "VAR_PLURAL")
20844 * 3. Replace all placeholders used inside ICUs in a form of {PLACEHOLDER}
20845 * 4. Replace all ICU references with corresponding values (like �ICU_EXP_ICU_1�)
20846 * in case multiple ICUs have the same placeholder name
20847 *
20848 * @param message Raw translation string for post processing
20849 * @param replacements Set of replacements that should be applied
20850 *
20851 * @returns Transformed string that can be consumed by i18nStart instruction
20852 *
20853 * @codeGenApi
20854 */
20855function ɵɵi18nPostprocess(message, replacements = {}) {
20856 return i18nPostprocess(message, replacements);
20857}
20858
20859/**
20860 * @license
20861 * Copyright Google LLC All Rights Reserved.
20862 *
20863 * Use of this source code is governed by an MIT-style license that can be
20864 * found in the LICENSE file at https://angular.io/license
20865 */
20866
20867/**
20868 * @license
20869 * Copyright Google LLC All Rights Reserved.
20870 *
20871 * Use of this source code is governed by an MIT-style license that can be
20872 * found in the LICENSE file at https://angular.io/license
20873 */
20874/**
20875 * Resolves the providers which are defined in the DirectiveDef.
20876 *
20877 * When inserting the tokens and the factories in their respective arrays, we can assume that
20878 * this method is called first for the component (if any), and then for other directives on the same
20879 * node.
20880 * As a consequence,the providers are always processed in that order:
20881 * 1) The view providers of the component
20882 * 2) The providers of the component
20883 * 3) The providers of the other directives
20884 * This matches the structure of the injectables arrays of a view (for each node).
20885 * So the tokens and the factories can be pushed at the end of the arrays, except
20886 * in one case for multi providers.
20887 *
20888 * @param def the directive definition
20889 * @param providers: Array of `providers`.
20890 * @param viewProviders: Array of `viewProviders`.
20891 */
20892function providersResolver(def, providers, viewProviders) {
20893 const tView = getTView();
20894 if (tView.firstCreatePass) {
20895 const isComponent = isComponentDef(def);
20896 // The list of view providers is processed first, and the flags are updated
20897 resolveProvider(viewProviders, tView.data, tView.blueprint, isComponent, true);
20898 // Then, the list of providers is processed, and the flags are updated
20899 resolveProvider(providers, tView.data, tView.blueprint, isComponent, false);
20900 }
20901}
20902/**
20903 * Resolves a provider and publishes it to the DI system.
20904 */
20905function resolveProvider(provider, tInjectables, lInjectablesBlueprint, isComponent, isViewProvider) {
20906 provider = resolveForwardRef(provider);
20907 if (Array.isArray(provider)) {
20908 // Recursively call `resolveProvider`
20909 // Recursion is OK in this case because this code will not be in hot-path once we implement
20910 // cloning of the initial state.
20911 for (let i = 0; i < provider.length; i++) {
20912 resolveProvider(provider[i], tInjectables, lInjectablesBlueprint, isComponent, isViewProvider);
20913 }
20914 }
20915 else {
20916 const tView = getTView();
20917 const lView = getLView();
20918 let token = isTypeProvider(provider) ? provider : resolveForwardRef(provider.provide);
20919 let providerFactory = providerToFactory(provider);
20920 const tNode = getCurrentTNode();
20921 const beginIndex = tNode.providerIndexes & 1048575 /* ProvidersStartIndexMask */;
20922 const endIndex = tNode.directiveStart;
20923 const cptViewProvidersCount = tNode.providerIndexes >> 20 /* CptViewProvidersCountShift */;
20924 if (isTypeProvider(provider) || !provider.multi) {
20925 // Single provider case: the factory is created and pushed immediately
20926 const factory = new NodeInjectorFactory(providerFactory, isViewProvider, ɵɵdirectiveInject);
20927 const existingFactoryIndex = indexOf(token, tInjectables, isViewProvider ? beginIndex : beginIndex + cptViewProvidersCount, endIndex);
20928 if (existingFactoryIndex === -1) {
20929 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
20930 registerDestroyHooksIfSupported(tView, provider, tInjectables.length);
20931 tInjectables.push(token);
20932 tNode.directiveStart++;
20933 tNode.directiveEnd++;
20934 if (isViewProvider) {
20935 tNode.providerIndexes += 1048576 /* CptViewProvidersCountShifter */;
20936 }
20937 lInjectablesBlueprint.push(factory);
20938 lView.push(factory);
20939 }
20940 else {
20941 lInjectablesBlueprint[existingFactoryIndex] = factory;
20942 lView[existingFactoryIndex] = factory;
20943 }
20944 }
20945 else {
20946 // Multi provider case:
20947 // We create a multi factory which is going to aggregate all the values.
20948 // Since the output of such a factory depends on content or view injection,
20949 // we create two of them, which are linked together.
20950 //
20951 // The first one (for view providers) is always in the first block of the injectables array,
20952 // and the second one (for providers) is always in the second block.
20953 // This is important because view providers have higher priority. When a multi token
20954 // is being looked up, the view providers should be found first.
20955 // Note that it is not possible to have a multi factory in the third block (directive block).
20956 //
20957 // The algorithm to process multi providers is as follows:
20958 // 1) If the multi provider comes from the `viewProviders` of the component:
20959 // a) If the special view providers factory doesn't exist, it is created and pushed.
20960 // b) Else, the multi provider is added to the existing multi factory.
20961 // 2) If the multi provider comes from the `providers` of the component or of another
20962 // directive:
20963 // a) If the multi factory doesn't exist, it is created and provider pushed into it.
20964 // It is also linked to the multi factory for view providers, if it exists.
20965 // b) Else, the multi provider is added to the existing multi factory.
20966 const existingProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex + cptViewProvidersCount, endIndex);
20967 const existingViewProvidersFactoryIndex = indexOf(token, tInjectables, beginIndex, beginIndex + cptViewProvidersCount);
20968 const doesProvidersFactoryExist = existingProvidersFactoryIndex >= 0 &&
20969 lInjectablesBlueprint[existingProvidersFactoryIndex];
20970 const doesViewProvidersFactoryExist = existingViewProvidersFactoryIndex >= 0 &&
20971 lInjectablesBlueprint[existingViewProvidersFactoryIndex];
20972 if (isViewProvider && !doesViewProvidersFactoryExist ||
20973 !isViewProvider && !doesProvidersFactoryExist) {
20974 // Cases 1.a and 2.a
20975 diPublicInInjector(getOrCreateNodeInjectorForNode(tNode, lView), tView, token);
20976 const factory = multiFactory(isViewProvider ? multiViewProvidersFactoryResolver : multiProvidersFactoryResolver, lInjectablesBlueprint.length, isViewProvider, isComponent, providerFactory);
20977 if (!isViewProvider && doesViewProvidersFactoryExist) {
20978 lInjectablesBlueprint[existingViewProvidersFactoryIndex].providerFactory = factory;
20979 }
20980 registerDestroyHooksIfSupported(tView, provider, tInjectables.length, 0);
20981 tInjectables.push(token);
20982 tNode.directiveStart++;
20983 tNode.directiveEnd++;
20984 if (isViewProvider) {
20985 tNode.providerIndexes += 1048576 /* CptViewProvidersCountShifter */;
20986 }
20987 lInjectablesBlueprint.push(factory);
20988 lView.push(factory);
20989 }
20990 else {
20991 // Cases 1.b and 2.b
20992 const indexInFactory = multiFactoryAdd(lInjectablesBlueprint[isViewProvider ? existingViewProvidersFactoryIndex :
20993 existingProvidersFactoryIndex], providerFactory, !isViewProvider && isComponent);
20994 registerDestroyHooksIfSupported(tView, provider, existingProvidersFactoryIndex > -1 ? existingProvidersFactoryIndex :
20995 existingViewProvidersFactoryIndex, indexInFactory);
20996 }
20997 if (!isViewProvider && isComponent && doesViewProvidersFactoryExist) {
20998 lInjectablesBlueprint[existingViewProvidersFactoryIndex].componentProviders++;
20999 }
21000 }
21001 }
21002}
21003/**
21004 * Registers the `ngOnDestroy` hook of a provider, if the provider supports destroy hooks.
21005 * @param tView `TView` in which to register the hook.
21006 * @param provider Provider whose hook should be registered.
21007 * @param contextIndex Index under which to find the context for the hook when it's being invoked.
21008 * @param indexInFactory Only required for `multi` providers. Index of the provider in the multi
21009 * provider factory.
21010 */
21011function registerDestroyHooksIfSupported(tView, provider, contextIndex, indexInFactory) {
21012 const providerIsTypeProvider = isTypeProvider(provider);
21013 if (providerIsTypeProvider || isClassProvider(provider)) {
21014 const prototype = (provider.useClass || provider).prototype;
21015 const ngOnDestroy = prototype.ngOnDestroy;
21016 if (ngOnDestroy) {
21017 const hooks = tView.destroyHooks || (tView.destroyHooks = []);
21018 if (!providerIsTypeProvider && provider.multi) {
21019 ngDevMode &&
21020 assertDefined(indexInFactory, 'indexInFactory when registering multi factory destroy hook');
21021 const existingCallbacksIndex = hooks.indexOf(contextIndex);
21022 if (existingCallbacksIndex === -1) {
21023 hooks.push(contextIndex, [indexInFactory, ngOnDestroy]);
21024 }
21025 else {
21026 hooks[existingCallbacksIndex + 1].push(indexInFactory, ngOnDestroy);
21027 }
21028 }
21029 else {
21030 hooks.push(contextIndex, ngOnDestroy);
21031 }
21032 }
21033 }
21034}
21035/**
21036 * Add a factory in a multi factory.
21037 * @returns Index at which the factory was inserted.
21038 */
21039function multiFactoryAdd(multiFactory, factory, isComponentProvider) {
21040 if (isComponentProvider) {
21041 multiFactory.componentProviders++;
21042 }
21043 return multiFactory.multi.push(factory) - 1;
21044}
21045/**
21046 * Returns the index of item in the array, but only in the begin to end range.
21047 */
21048function indexOf(item, arr, begin, end) {
21049 for (let i = begin; i < end; i++) {
21050 if (arr[i] === item)
21051 return i;
21052 }
21053 return -1;
21054}
21055/**
21056 * Use this with `multi` `providers`.
21057 */
21058function multiProvidersFactoryResolver(_, tData, lData, tNode) {
21059 return multiResolve(this.multi, []);
21060}
21061/**
21062 * Use this with `multi` `viewProviders`.
21063 *
21064 * This factory knows how to concatenate itself with the existing `multi` `providers`.
21065 */
21066function multiViewProvidersFactoryResolver(_, tData, lView, tNode) {
21067 const factories = this.multi;
21068 let result;
21069 if (this.providerFactory) {
21070 const componentCount = this.providerFactory.componentProviders;
21071 const multiProviders = getNodeInjectable(lView, lView[TVIEW], this.providerFactory.index, tNode);
21072 // Copy the section of the array which contains `multi` `providers` from the component
21073 result = multiProviders.slice(0, componentCount);
21074 // Insert the `viewProvider` instances.
21075 multiResolve(factories, result);
21076 // Copy the section of the array which contains `multi` `providers` from other directives
21077 for (let i = componentCount; i < multiProviders.length; i++) {
21078 result.push(multiProviders[i]);
21079 }
21080 }
21081 else {
21082 result = [];
21083 // Insert the `viewProvider` instances.
21084 multiResolve(factories, result);
21085 }
21086 return result;
21087}
21088/**
21089 * Maps an array of factories into an array of values.
21090 */
21091function multiResolve(factories, result) {
21092 for (let i = 0; i < factories.length; i++) {
21093 const factory = factories[i];
21094 result.push(factory());
21095 }
21096 return result;
21097}
21098/**
21099 * Creates a multi factory.
21100 */
21101function multiFactory(factoryFn, index, isViewProvider, isComponent, f) {
21102 const factory = new NodeInjectorFactory(factoryFn, isViewProvider, ɵɵdirectiveInject);
21103 factory.multi = [];
21104 factory.index = index;
21105 factory.componentProviders = 0;
21106 multiFactoryAdd(factory, f, isComponent && !isViewProvider);
21107 return factory;
21108}
21109
21110/**
21111 * This feature resolves the providers of a directive (or component),
21112 * and publish them into the DI system, making it visible to others for injection.
21113 *
21114 * For example:
21115 * ```ts
21116 * class ComponentWithProviders {
21117 * constructor(private greeter: GreeterDE) {}
21118 *
21119 * static ɵcmp = defineComponent({
21120 * type: ComponentWithProviders,
21121 * selectors: [['component-with-providers']],
21122 * factory: () => new ComponentWithProviders(directiveInject(GreeterDE as any)),
21123 * decls: 1,
21124 * vars: 1,
21125 * template: function(fs: RenderFlags, ctx: ComponentWithProviders) {
21126 * if (fs & RenderFlags.Create) {
21127 * ɵɵtext(0);
21128 * }
21129 * if (fs & RenderFlags.Update) {
21130 * ɵɵtextInterpolate(ctx.greeter.greet());
21131 * }
21132 * },
21133 * features: [ɵɵProvidersFeature([GreeterDE])]
21134 * });
21135 * }
21136 * ```
21137 *
21138 * @param definition
21139 *
21140 * @codeGenApi
21141 */
21142function ɵɵProvidersFeature(providers, viewProviders = []) {
21143 return (definition) => {
21144 definition.providersResolver =
21145 (def, processProvidersFn) => {
21146 return providersResolver(def, //
21147 processProvidersFn ? processProvidersFn(providers) : providers, //
21148 viewProviders);
21149 };
21150 };
21151}
21152
21153/**
21154 * @license
21155 * Copyright Google LLC All Rights Reserved.
21156 *
21157 * Use of this source code is governed by an MIT-style license that can be
21158 * found in the LICENSE file at https://angular.io/license
21159 */
21160/**
21161 * Represents a component created by a `ComponentFactory`.
21162 * Provides access to the component instance and related objects,
21163 * and provides the means of destroying the instance.
21164 *
21165 * @publicApi
21166 */
21167class ComponentRef$1 {
21168}
21169/**
21170 * Base class for a factory that can create a component dynamically.
21171 * Instantiate a factory for a given type of component with `resolveComponentFactory()`.
21172 * Use the resulting `ComponentFactory.create()` method to create a component of that type.
21173 *
21174 * @see [Dynamic Components](guide/dynamic-component-loader)
21175 *
21176 * @publicApi
21177 */
21178class ComponentFactory$1 {
21179}
21180
21181/**
21182 * @license
21183 * Copyright Google LLC All Rights Reserved.
21184 *
21185 * Use of this source code is governed by an MIT-style license that can be
21186 * found in the LICENSE file at https://angular.io/license
21187 */
21188function noComponentFactoryError(component) {
21189 const error = Error(`No component factory found for ${stringify(component)}. Did you add it to @NgModule.entryComponents?`);
21190 error[ERROR_COMPONENT] = component;
21191 return error;
21192}
21193const ERROR_COMPONENT = 'ngComponent';
21194function getComponent(error) {
21195 return error[ERROR_COMPONENT];
21196}
21197class _NullComponentFactoryResolver {
21198 resolveComponentFactory(component) {
21199 throw noComponentFactoryError(component);
21200 }
21201}
21202/**
21203 * A simple registry that maps `Components` to generated `ComponentFactory` classes
21204 * that can be used to create instances of components.
21205 * Use to obtain the factory for a given component type,
21206 * then use the factory's `create()` method to create a component of that type.
21207 *
21208 * Note: since v13, dynamic component creation via
21209 * [`ViewContainerRef.createComponent`](api/core/ViewContainerRef#createComponent)
21210 * does **not** require resolving component factory: component class can be used directly.
21211 *
21212 * @publicApi
21213 */
21214class ComponentFactoryResolver$1 {
21215}
21216ComponentFactoryResolver$1.NULL = ( /* @__PURE__ */new _NullComponentFactoryResolver());
21217class CodegenComponentFactoryResolver {
21218 constructor(factories, _parent, _ngModule) {
21219 this._parent = _parent;
21220 this._ngModule = _ngModule;
21221 this._factories = new Map();
21222 for (let i = 0; i < factories.length; i++) {
21223 const factory = factories[i];
21224 this._factories.set(factory.componentType, factory);
21225 }
21226 }
21227 resolveComponentFactory(component) {
21228 let factory = this._factories.get(component);
21229 if (!factory && this._parent) {
21230 factory = this._parent.resolveComponentFactory(component);
21231 }
21232 if (!factory) {
21233 throw noComponentFactoryError(component);
21234 }
21235 return new ComponentFactoryBoundToModule(factory, this._ngModule);
21236 }
21237}
21238class ComponentFactoryBoundToModule extends ComponentFactory$1 {
21239 constructor(factory, ngModule) {
21240 super();
21241 this.factory = factory;
21242 this.ngModule = ngModule;
21243 this.selector = factory.selector;
21244 this.componentType = factory.componentType;
21245 this.ngContentSelectors = factory.ngContentSelectors;
21246 this.inputs = factory.inputs;
21247 this.outputs = factory.outputs;
21248 }
21249 create(injector, projectableNodes, rootSelectorOrNode, ngModule) {
21250 return this.factory.create(injector, projectableNodes, rootSelectorOrNode, ngModule || this.ngModule);
21251 }
21252}
21253
21254/**
21255 * @license
21256 * Copyright Google LLC All Rights Reserved.
21257 *
21258 * Use of this source code is governed by an MIT-style license that can be
21259 * found in the LICENSE file at https://angular.io/license
21260 */
21261function noop(...args) {
21262 // Do nothing.
21263}
21264
21265/**
21266 * Creates an ElementRef from the most recent node.
21267 *
21268 * @returns The ElementRef instance to use
21269 */
21270function injectElementRef() {
21271 return createElementRef(getCurrentTNode(), getLView());
21272}
21273/**
21274 * Creates an ElementRef given a node.
21275 *
21276 * @param tNode The node for which you'd like an ElementRef
21277 * @param lView The view to which the node belongs
21278 * @returns The ElementRef instance to use
21279 */
21280function createElementRef(tNode, lView) {
21281 return new ElementRef(getNativeByTNode(tNode, lView));
21282}
21283const SWITCH_ELEMENT_REF_FACTORY__POST_R3__ = injectElementRef;
21284const SWITCH_ELEMENT_REF_FACTORY__PRE_R3__ = noop;
21285const SWITCH_ELEMENT_REF_FACTORY = SWITCH_ELEMENT_REF_FACTORY__POST_R3__;
21286/**
21287 * A wrapper around a native element inside of a View.
21288 *
21289 * An `ElementRef` is backed by a render-specific element. In the browser, this is usually a DOM
21290 * element.
21291 *
21292 * @security Permitting direct access to the DOM can make your application more vulnerable to
21293 * XSS attacks. Carefully review any use of `ElementRef` in your code. For more detail, see the
21294 * [Security Guide](https://g.co/ng/security).
21295 *
21296 * @publicApi
21297 */
21298// Note: We don't expose things like `Injector`, `ViewContainer`, ... here,
21299// i.e. users have to ask for what they need. With that, we can build better analysis tools
21300// and could do better codegen in the future.
21301class ElementRef {
21302 constructor(nativeElement) {
21303 this.nativeElement = nativeElement;
21304 }
21305}
21306/**
21307 * @internal
21308 * @nocollapse
21309 */
21310ElementRef.__NG_ELEMENT_ID__ = SWITCH_ELEMENT_REF_FACTORY;
21311/**
21312 * Unwraps `ElementRef` and return the `nativeElement`.
21313 *
21314 * @param value value to unwrap
21315 * @returns `nativeElement` if `ElementRef` otherwise returns value as is.
21316 */
21317function unwrapElementRef(value) {
21318 return value instanceof ElementRef ? value.nativeElement : value;
21319}
21320
21321/**
21322 * @license
21323 * Copyright Google LLC All Rights Reserved.
21324 *
21325 * Use of this source code is governed by an MIT-style license that can be
21326 * found in the LICENSE file at https://angular.io/license
21327 */
21328const Renderer2Interceptor = new InjectionToken('Renderer2Interceptor');
21329/**
21330 * Creates and initializes a custom renderer that implements the `Renderer2` base class.
21331 *
21332 * @publicApi
21333 */
21334class RendererFactory2 {
21335}
21336/**
21337 * Extend this base class to implement custom rendering. By default, Angular
21338 * renders a template into DOM. You can use custom rendering to intercept
21339 * rendering calls, or to render to something other than DOM.
21340 *
21341 * Create your custom renderer using `RendererFactory2`.
21342 *
21343 * Use a custom renderer to bypass Angular's templating and
21344 * make custom UI changes that can't be expressed declaratively.
21345 * For example if you need to set a property or an attribute whose name is
21346 * not statically known, use the `setProperty()` or
21347 * `setAttribute()` method.
21348 *
21349 * @publicApi
21350 */
21351class Renderer2 {
21352}
21353/**
21354 * @internal
21355 * @nocollapse
21356 */
21357Renderer2.__NG_ELEMENT_ID__ = () => SWITCH_RENDERER2_FACTORY();
21358const SWITCH_RENDERER2_FACTORY__POST_R3__ = injectRenderer2;
21359const SWITCH_RENDERER2_FACTORY__PRE_R3__ = noop;
21360const SWITCH_RENDERER2_FACTORY = SWITCH_RENDERER2_FACTORY__POST_R3__;
21361/** Returns a Renderer2 (or throws when application was bootstrapped with Renderer3) */
21362function getOrCreateRenderer2(lView) {
21363 const renderer = lView[RENDERER];
21364 if (ngDevMode && !isProceduralRenderer(renderer)) {
21365 throw new Error('Cannot inject Renderer2 when the application uses Renderer3!');
21366 }
21367 return renderer;
21368}
21369/** Injects a Renderer2 for the current component. */
21370function injectRenderer2() {
21371 // We need the Renderer to be based on the component that it's being injected into, however since
21372 // DI happens before we've entered its view, `getLView` will return the parent view instead.
21373 const lView = getLView();
21374 const tNode = getCurrentTNode();
21375 const nodeAtIndex = getComponentLViewByIndex(tNode.index, lView);
21376 return getOrCreateRenderer2(isLView(nodeAtIndex) ? nodeAtIndex : lView);
21377}
21378
21379/**
21380 * @license
21381 * Copyright Google LLC All Rights Reserved.
21382 *
21383 * Use of this source code is governed by an MIT-style license that can be
21384 * found in the LICENSE file at https://angular.io/license
21385 */
21386/**
21387 * Sanitizer is used by the views to sanitize potentially dangerous values.
21388 *
21389 * @publicApi
21390 */
21391class Sanitizer {
21392}
21393/** @nocollapse */
21394Sanitizer.ɵprov = ɵɵdefineInjectable({
21395 token: Sanitizer,
21396 providedIn: 'root',
21397 factory: () => null,
21398});
21399
21400/**
21401 * @license
21402 * Copyright Google LLC All Rights Reserved.
21403 *
21404 * Use of this source code is governed by an MIT-style license that can be
21405 * found in the LICENSE file at https://angular.io/license
21406 */
21407/**
21408 * @description Represents the version of Angular
21409 *
21410 * @publicApi
21411 */
21412class Version {
21413 constructor(full) {
21414 this.full = full;
21415 this.major = full.split('.')[0];
21416 this.minor = full.split('.')[1];
21417 this.patch = full.split('.').slice(2).join('.');
21418 }
21419}
21420/**
21421 * @publicApi
21422 */
21423const VERSION = new Version('13.0.2');
21424
21425/**
21426 * @license
21427 * Copyright Google LLC All Rights Reserved.
21428 *
21429 * Use of this source code is governed by an MIT-style license that can be
21430 * found in the LICENSE file at https://angular.io/license
21431 */
21432// This default value is when checking the hierarchy for a token.
21433//
21434// It means both:
21435// - the token is not provided by the current injector,
21436// - only the element injectors should be checked (ie do not check module injectors
21437//
21438// mod1
21439// /
21440// el1 mod2
21441// \ /
21442// el2
21443//
21444// When requesting el2.injector.get(token), we should check in the following order and return the
21445// first found value:
21446// - el2.injector.get(token, default)
21447// - el1.injector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) -> do not check the module
21448// - mod2.injector.get(token, default)
21449const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
21450
21451/**
21452 * @license
21453 * Copyright Google LLC All Rights Reserved.
21454 *
21455 * Use of this source code is governed by an MIT-style license that can be
21456 * found in the LICENSE file at https://angular.io/license
21457 */
21458function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
21459 while (tNode !== null) {
21460 ngDevMode &&
21461 assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */ | 16 /* Projection */ | 32 /* Icu */);
21462 const lNode = lView[tNode.index];
21463 if (lNode !== null) {
21464 result.push(unwrapRNode(lNode));
21465 }
21466 // A given lNode can represent either a native node or a LContainer (when it is a host of a
21467 // ViewContainerRef). When we find a LContainer we need to descend into it to collect root nodes
21468 // from the views in this container.
21469 if (isLContainer(lNode)) {
21470 for (let i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) {
21471 const lViewInAContainer = lNode[i];
21472 const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;
21473 if (lViewFirstChildTNode !== null) {
21474 collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
21475 }
21476 }
21477 }
21478 const tNodeType = tNode.type;
21479 if (tNodeType & 8 /* ElementContainer */) {
21480 collectNativeNodes(tView, lView, tNode.child, result);
21481 }
21482 else if (tNodeType & 32 /* Icu */) {
21483 const nextRNode = icuContainerIterate(tNode, lView);
21484 let rNode;
21485 while (rNode = nextRNode()) {
21486 result.push(rNode);
21487 }
21488 }
21489 else if (tNodeType & 16 /* Projection */) {
21490 const nodesInSlot = getProjectionNodes(lView, tNode);
21491 if (Array.isArray(nodesInSlot)) {
21492 result.push(...nodesInSlot);
21493 }
21494 else {
21495 const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
21496 ngDevMode && assertParentView(parentView);
21497 collectNativeNodes(parentView[TVIEW], parentView, nodesInSlot, result, true);
21498 }
21499 }
21500 tNode = isProjection ? tNode.projectionNext : tNode.next;
21501 }
21502 return result;
21503}
21504
21505/**
21506 * @license
21507 * Copyright Google LLC All Rights Reserved.
21508 *
21509 * Use of this source code is governed by an MIT-style license that can be
21510 * found in the LICENSE file at https://angular.io/license
21511 */
21512class ViewRef$1 {
21513 constructor(
21514 /**
21515 * This represents `LView` associated with the component when ViewRef is a ChangeDetectorRef.
21516 *
21517 * When ViewRef is created for a dynamic component, this also represents the `LView` for the
21518 * component.
21519 *
21520 * For a "regular" ViewRef created for an embedded view, this is the `LView` for the embedded
21521 * view.
21522 *
21523 * @internal
21524 */
21525 _lView,
21526 /**
21527 * This represents the `LView` associated with the point where `ChangeDetectorRef` was
21528 * requested.
21529 *
21530 * This may be different from `_lView` if the `_cdRefInjectingView` is an embedded view.
21531 */
21532 _cdRefInjectingView) {
21533 this._lView = _lView;
21534 this._cdRefInjectingView = _cdRefInjectingView;
21535 this._appRef = null;
21536 this._attachedToViewContainer = false;
21537 }
21538 get rootNodes() {
21539 const lView = this._lView;
21540 const tView = lView[TVIEW];
21541 return collectNativeNodes(tView, lView, tView.firstChild, []);
21542 }
21543 get context() {
21544 return this._lView[CONTEXT];
21545 }
21546 set context(value) {
21547 this._lView[CONTEXT] = value;
21548 }
21549 get destroyed() {
21550 return (this._lView[FLAGS] & 256 /* Destroyed */) === 256 /* Destroyed */;
21551 }
21552 destroy() {
21553 if (this._appRef) {
21554 this._appRef.detachView(this);
21555 }
21556 else if (this._attachedToViewContainer) {
21557 const parent = this._lView[PARENT];
21558 if (isLContainer(parent)) {
21559 const viewRefs = parent[VIEW_REFS];
21560 const index = viewRefs ? viewRefs.indexOf(this) : -1;
21561 if (index > -1) {
21562 ngDevMode &&
21563 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.');
21564 detachView(parent, index);
21565 removeFromArray(viewRefs, index);
21566 }
21567 }
21568 this._attachedToViewContainer = false;
21569 }
21570 destroyLView(this._lView[TVIEW], this._lView);
21571 }
21572 onDestroy(callback) {
21573 storeCleanupWithContext(this._lView[TVIEW], this._lView, null, callback);
21574 }
21575 /**
21576 * Marks a view and all of its ancestors dirty.
21577 *
21578 * This can be used to ensure an {@link ChangeDetectionStrategy#OnPush OnPush} component is
21579 * checked when it needs to be re-rendered but the two normal triggers haven't marked it
21580 * dirty (i.e. inputs haven't changed and events haven't fired in the view).
21581 *
21582 * <!-- TODO: Add a link to a chapter on OnPush components -->
21583 *
21584 * @usageNotes
21585 * ### Example
21586 *
21587 * ```typescript
21588 * @Component({
21589 * selector: 'app-root',
21590 * template: `Number of ticks: {{numberOfTicks}}`
21591 * changeDetection: ChangeDetectionStrategy.OnPush,
21592 * })
21593 * class AppComponent {
21594 * numberOfTicks = 0;
21595 *
21596 * constructor(private ref: ChangeDetectorRef) {
21597 * setInterval(() => {
21598 * this.numberOfTicks++;
21599 * // the following is required, otherwise the view will not be updated
21600 * this.ref.markForCheck();
21601 * }, 1000);
21602 * }
21603 * }
21604 * ```
21605 */
21606 markForCheck() {
21607 markViewDirty(this._cdRefInjectingView || this._lView);
21608 }
21609 /**
21610 * Detaches the view from the change detection tree.
21611 *
21612 * Detached views will not be checked during change detection runs until they are
21613 * re-attached, even if they are dirty. `detach` can be used in combination with
21614 * {@link ChangeDetectorRef#detectChanges detectChanges} to implement local change
21615 * detection checks.
21616 *
21617 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
21618 * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->
21619 *
21620 * @usageNotes
21621 * ### Example
21622 *
21623 * The following example defines a component with a large list of readonly data.
21624 * Imagine the data changes constantly, many times per second. For performance reasons,
21625 * we want to check and update the list every five seconds. We can do that by detaching
21626 * the component's change detector and doing a local check every five seconds.
21627 *
21628 * ```typescript
21629 * class DataProvider {
21630 * // in a real application the returned data will be different every time
21631 * get data() {
21632 * return [1,2,3,4,5];
21633 * }
21634 * }
21635 *
21636 * @Component({
21637 * selector: 'giant-list',
21638 * template: `
21639 * <li *ngFor="let d of dataProvider.data">Data {{d}}</li>
21640 * `,
21641 * })
21642 * class GiantList {
21643 * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {
21644 * ref.detach();
21645 * setInterval(() => {
21646 * this.ref.detectChanges();
21647 * }, 5000);
21648 * }
21649 * }
21650 *
21651 * @Component({
21652 * selector: 'app',
21653 * providers: [DataProvider],
21654 * template: `
21655 * <giant-list><giant-list>
21656 * `,
21657 * })
21658 * class App {
21659 * }
21660 * ```
21661 */
21662 detach() {
21663 this._lView[FLAGS] &= ~128 /* Attached */;
21664 }
21665 /**
21666 * Re-attaches a view to the change detection tree.
21667 *
21668 * This can be used to re-attach views that were previously detached from the tree
21669 * using {@link ChangeDetectorRef#detach detach}. Views are attached to the tree by default.
21670 *
21671 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
21672 *
21673 * @usageNotes
21674 * ### Example
21675 *
21676 * The following example creates a component displaying `live` data. The component will detach
21677 * its change detector from the main change detector tree when the component's live property
21678 * is set to false.
21679 *
21680 * ```typescript
21681 * class DataProvider {
21682 * data = 1;
21683 *
21684 * constructor() {
21685 * setInterval(() => {
21686 * this.data = this.data * 2;
21687 * }, 500);
21688 * }
21689 * }
21690 *
21691 * @Component({
21692 * selector: 'live-data',
21693 * inputs: ['live'],
21694 * template: 'Data: {{dataProvider.data}}'
21695 * })
21696 * class LiveData {
21697 * constructor(private ref: ChangeDetectorRef, private dataProvider: DataProvider) {}
21698 *
21699 * set live(value) {
21700 * if (value) {
21701 * this.ref.reattach();
21702 * } else {
21703 * this.ref.detach();
21704 * }
21705 * }
21706 * }
21707 *
21708 * @Component({
21709 * selector: 'app-root',
21710 * providers: [DataProvider],
21711 * template: `
21712 * Live Update: <input type="checkbox" [(ngModel)]="live">
21713 * <live-data [live]="live"><live-data>
21714 * `,
21715 * })
21716 * class AppComponent {
21717 * live = true;
21718 * }
21719 * ```
21720 */
21721 reattach() {
21722 this._lView[FLAGS] |= 128 /* Attached */;
21723 }
21724 /**
21725 * Checks the view and its children.
21726 *
21727 * This can also be used in combination with {@link ChangeDetectorRef#detach detach} to implement
21728 * local change detection checks.
21729 *
21730 * <!-- TODO: Add a link to a chapter on detach/reattach/local digest -->
21731 * <!-- TODO: Add a live demo once ref.detectChanges is merged into master -->
21732 *
21733 * @usageNotes
21734 * ### Example
21735 *
21736 * The following example defines a component with a large list of readonly data.
21737 * Imagine, the data changes constantly, many times per second. For performance reasons,
21738 * we want to check and update the list every five seconds.
21739 *
21740 * We can do that by detaching the component's change detector and doing a local change detection
21741 * check every five seconds.
21742 *
21743 * See {@link ChangeDetectorRef#detach detach} for more information.
21744 */
21745 detectChanges() {
21746 detectChangesInternal(this._lView[TVIEW], this._lView, this.context);
21747 }
21748 /**
21749 * Checks the change detector and its children, and throws if any changes are detected.
21750 *
21751 * This is used in development mode to verify that running change detection doesn't
21752 * introduce other changes.
21753 */
21754 checkNoChanges() {
21755 checkNoChangesInternal(this._lView[TVIEW], this._lView, this.context);
21756 }
21757 attachToViewContainerRef() {
21758 if (this._appRef) {
21759 throw new Error('This view is already attached directly to the ApplicationRef!');
21760 }
21761 this._attachedToViewContainer = true;
21762 }
21763 detachFromAppRef() {
21764 this._appRef = null;
21765 renderDetachView$1(this._lView[TVIEW], this._lView);
21766 }
21767 attachToAppRef(appRef) {
21768 if (this._attachedToViewContainer) {
21769 throw new Error('This view is already attached to a ViewContainer!');
21770 }
21771 this._appRef = appRef;
21772 }
21773}
21774/** @internal */
21775class RootViewRef extends ViewRef$1 {
21776 constructor(_view) {
21777 super(_view);
21778 this._view = _view;
21779 }
21780 detectChanges() {
21781 detectChangesInRootView(this._view);
21782 }
21783 checkNoChanges() {
21784 checkNoChangesInRootView(this._view);
21785 }
21786 get context() {
21787 return null;
21788 }
21789}
21790
21791/**
21792 * @license
21793 * Copyright Google LLC All Rights Reserved.
21794 *
21795 * Use of this source code is governed by an MIT-style license that can be
21796 * found in the LICENSE file at https://angular.io/license
21797 */
21798class ComponentFactoryResolver extends ComponentFactoryResolver$1 {
21799 /**
21800 * @param ngModule The NgModuleRef to which all resolved factories are bound.
21801 */
21802 constructor(ngModule) {
21803 super();
21804 this.ngModule = ngModule;
21805 }
21806 resolveComponentFactory(component) {
21807 ngDevMode && assertComponentType(component);
21808 const componentDef = getComponentDef(component);
21809 return new ComponentFactory(componentDef, this.ngModule);
21810 }
21811}
21812function toRefArray(map) {
21813 const array = [];
21814 for (let nonMinified in map) {
21815 if (map.hasOwnProperty(nonMinified)) {
21816 const minified = map[nonMinified];
21817 array.push({ propName: minified, templateName: nonMinified });
21818 }
21819 }
21820 return array;
21821}
21822function getNamespace(elementName) {
21823 const name = elementName.toLowerCase();
21824 return name === 'svg' ? SVG_NAMESPACE : (name === 'math' ? MATH_ML_NAMESPACE : null);
21825}
21826/**
21827 * A change detection scheduler token for {@link RootContext}. This token is the default value used
21828 * for the default `RootContext` found in the {@link ROOT_CONTEXT} token.
21829 */
21830const SCHEDULER = new InjectionToken('SCHEDULER_TOKEN', {
21831 providedIn: 'root',
21832 factory: () => defaultScheduler,
21833});
21834function createChainedInjector(rootViewInjector, moduleInjector) {
21835 return {
21836 get: (token, notFoundValue, flags) => {
21837 const value = rootViewInjector.get(token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, flags);
21838 if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
21839 notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
21840 // Return the value from the root element injector when
21841 // - it provides it
21842 // (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
21843 // - the module injector should not be checked
21844 // (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
21845 return value;
21846 }
21847 return moduleInjector.get(token, notFoundValue, flags);
21848 }
21849 };
21850}
21851/**
21852 * Render3 implementation of {@link viewEngine_ComponentFactory}.
21853 */
21854class ComponentFactory extends ComponentFactory$1 {
21855 /**
21856 * @param componentDef The component definition.
21857 * @param ngModule The NgModuleRef to which the factory is bound.
21858 */
21859 constructor(componentDef, ngModule) {
21860 super();
21861 this.componentDef = componentDef;
21862 this.ngModule = ngModule;
21863 this.componentType = componentDef.type;
21864 this.selector = stringifyCSSSelectorList(componentDef.selectors);
21865 this.ngContentSelectors =
21866 componentDef.ngContentSelectors ? componentDef.ngContentSelectors : [];
21867 this.isBoundToModule = !!ngModule;
21868 }
21869 get inputs() {
21870 return toRefArray(this.componentDef.inputs);
21871 }
21872 get outputs() {
21873 return toRefArray(this.componentDef.outputs);
21874 }
21875 create(injector, projectableNodes, rootSelectorOrNode, ngModule) {
21876 ngModule = ngModule || this.ngModule;
21877 const rootViewInjector = ngModule ? createChainedInjector(injector, ngModule.injector) : injector;
21878 const rendererFactory = rootViewInjector.get(RendererFactory2, domRendererFactory3);
21879 const sanitizer = rootViewInjector.get(Sanitizer, null);
21880 const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);
21881 // Determine a tag name used for creating host elements when this component is created
21882 // dynamically. Default to 'div' if this component did not specify any tag name in its selector.
21883 const elementName = this.componentDef.selectors[0][0] || 'div';
21884 const hostRNode = rootSelectorOrNode ?
21885 locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :
21886 createElementNode(rendererFactory.createRenderer(null, this.componentDef), elementName, getNamespace(elementName));
21887 const rootFlags = this.componentDef.onPush ? 64 /* Dirty */ | 512 /* IsRoot */ :
21888 16 /* CheckAlways */ | 512 /* IsRoot */;
21889 const rootContext = createRootContext();
21890 // Create the root view. Uses empty TView and ContentTemplate.
21891 const rootTView = createTView(0 /* Root */, null, null, 1, 0, null, null, null, null, null);
21892 const rootLView = createLView(null, rootTView, rootContext, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector);
21893 // rootView is the parent when bootstrapping
21894 // TODO(misko): it looks like we are entering view here but we don't really need to as
21895 // `renderView` does that. However as the code is written it is needed because
21896 // `createRootComponentView` and `createRootComponent` both read global state. Fixing those
21897 // issues would allow us to drop this.
21898 enterView(rootLView);
21899 let component;
21900 let tElementNode;
21901 try {
21902 const componentView = createRootComponentView(hostRNode, this.componentDef, rootLView, rendererFactory, hostRenderer);
21903 if (hostRNode) {
21904 if (rootSelectorOrNode) {
21905 setUpAttributes(hostRenderer, hostRNode, ['ng-version', VERSION.full]);
21906 }
21907 else {
21908 // If host element is created as a part of this function call (i.e. `rootSelectorOrNode`
21909 // is not defined), also apply attributes and classes extracted from component selector.
21910 // Extract attributes and classes from the first selector only to match VE behavior.
21911 const { attrs, classes } = extractAttrsAndClassesFromSelector(this.componentDef.selectors[0]);
21912 if (attrs) {
21913 setUpAttributes(hostRenderer, hostRNode, attrs);
21914 }
21915 if (classes && classes.length > 0) {
21916 writeDirectClass(hostRenderer, hostRNode, classes.join(' '));
21917 }
21918 }
21919 }
21920 tElementNode = getTNode(rootTView, HEADER_OFFSET);
21921 if (projectableNodes !== undefined) {
21922 const projection = tElementNode.projection = [];
21923 for (let i = 0; i < this.ngContentSelectors.length; i++) {
21924 const nodesforSlot = projectableNodes[i];
21925 // Projectable nodes can be passed as array of arrays or an array of iterables (ngUpgrade
21926 // case). Here we do normalize passed data structure to be an array of arrays to avoid
21927 // complex checks down the line.
21928 // We also normalize the length of the passed in projectable nodes (to match the number of
21929 // <ng-container> slots defined by a component).
21930 projection.push(nodesforSlot != null ? Array.from(nodesforSlot) : null);
21931 }
21932 }
21933 // TODO: should LifecycleHooksFeature and other host features be generated by the compiler and
21934 // executed here?
21935 // Angular 5 reference: https://stackblitz.com/edit/lifecycle-hooks-vcref
21936 component = createRootComponent(componentView, this.componentDef, rootLView, rootContext, [LifecycleHooksFeature]);
21937 renderView(rootTView, rootLView, null);
21938 }
21939 finally {
21940 leaveView();
21941 }
21942 return new ComponentRef(this.componentType, component, createElementRef(tElementNode, rootLView), rootLView, tElementNode);
21943 }
21944}
21945const componentFactoryResolver = new ComponentFactoryResolver();
21946/**
21947 * Creates a ComponentFactoryResolver and stores it on the injector. Or, if the
21948 * ComponentFactoryResolver
21949 * already exists, retrieves the existing ComponentFactoryResolver.
21950 *
21951 * @returns The ComponentFactoryResolver instance to use
21952 */
21953function injectComponentFactoryResolver() {
21954 return componentFactoryResolver;
21955}
21956/**
21957 * Represents an instance of a Component created via a {@link ComponentFactory}.
21958 *
21959 * `ComponentRef` provides access to the Component Instance as well other objects related to this
21960 * Component Instance and allows you to destroy the Component Instance via the {@link #destroy}
21961 * method.
21962 *
21963 */
21964class ComponentRef extends ComponentRef$1 {
21965 constructor(componentType, instance, location, _rootLView, _tNode) {
21966 super();
21967 this.location = location;
21968 this._rootLView = _rootLView;
21969 this._tNode = _tNode;
21970 this.instance = instance;
21971 this.hostView = this.changeDetectorRef = new RootViewRef(_rootLView);
21972 this.componentType = componentType;
21973 }
21974 get injector() {
21975 return new NodeInjector(this._tNode, this._rootLView);
21976 }
21977 destroy() {
21978 this.hostView.destroy();
21979 }
21980 onDestroy(callback) {
21981 this.hostView.onDestroy(callback);
21982 }
21983}
21984
21985/**
21986 * @license
21987 * Copyright Google LLC All Rights Reserved.
21988 *
21989 * Use of this source code is governed by an MIT-style license that can be
21990 * found in the LICENSE file at https://angular.io/license
21991 */
21992/**
21993 * Adds decorator, constructor, and property metadata to a given type via static metadata fields
21994 * on the type.
21995 *
21996 * These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
21997 *
21998 * Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments
21999 * being tree-shaken away during production builds.
22000 */
22001function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
22002 return noSideEffects(() => {
22003 const clazz = type;
22004 if (decorators !== null) {
22005 if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
22006 clazz.decorators.push(...decorators);
22007 }
22008 else {
22009 clazz.decorators = decorators;
22010 }
22011 }
22012 if (ctorParameters !== null) {
22013 // Rather than merging, clobber the existing parameters. If other projects exist which
22014 // use tsickle-style annotations and reflect over them in the same way, this could
22015 // cause issues, but that is vanishingly unlikely.
22016 clazz.ctorParameters = ctorParameters;
22017 }
22018 if (propDecorators !== null) {
22019 // The property decorator objects are merged as it is possible different fields have
22020 // different decorator types. Decorators on individual fields are not merged, as it's
22021 // also incredibly unlikely that a field will be decorated both with an Angular
22022 // decorator and a non-Angular decorator that's also been downleveled.
22023 if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
22024 clazz.propDecorators = Object.assign(Object.assign({}, clazz.propDecorators), propDecorators);
22025 }
22026 else {
22027 clazz.propDecorators = propDecorators;
22028 }
22029 }
22030 });
22031}
22032
22033/**
22034 * @license
22035 * Copyright Google LLC All Rights Reserved.
22036 *
22037 * Use of this source code is governed by an MIT-style license that can be
22038 * found in the LICENSE file at https://angular.io/license
22039 */
22040/**
22041 * Represents an instance of an `NgModule` created by an `NgModuleFactory`.
22042 * Provides access to the `NgModule` instance and related objects.
22043 *
22044 * @publicApi
22045 */
22046class NgModuleRef$1 {
22047}
22048/**
22049 * @publicApi
22050 *
22051 * @deprecated
22052 * This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy
22053 * JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes)
22054 * for additional context. Angular provides APIs that accept NgModule classes directly (such as
22055 * [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and
22056 * [createNgModuleRef](api/core/createNgModuleRef)), consider switching to those APIs instead of
22057 * using factory-based ones.
22058 */
22059class NgModuleFactory$1 {
22060}
22061
22062/**
22063 * @license
22064 * Copyright Google LLC All Rights Reserved.
22065 *
22066 * Use of this source code is governed by an MIT-style license that can be
22067 * found in the LICENSE file at https://angular.io/license
22068 */
22069/**
22070 * Map of module-id to the corresponding NgModule.
22071 * - In pre Ivy we track NgModuleFactory,
22072 * - In post Ivy we track the NgModuleType
22073 */
22074const modules = new Map();
22075/**
22076 * Registers a loaded module. Should only be called from generated NgModuleFactory code.
22077 * @publicApi
22078 */
22079function registerModuleFactory(id, factory) {
22080 const existing = modules.get(id);
22081 assertSameOrNotExisting(id, existing && existing.moduleType, factory.moduleType);
22082 modules.set(id, factory);
22083}
22084function assertSameOrNotExisting(id, type, incoming) {
22085 if (type && type !== incoming) {
22086 throw new Error(`Duplicate module registered for ${id} - ${stringify(type)} vs ${stringify(type.name)}`);
22087 }
22088}
22089function registerNgModuleType(ngModuleType) {
22090 const visited = new Set();
22091 recurse(ngModuleType);
22092 function recurse(ngModuleType) {
22093 // The imports array of an NgModule must refer to other NgModules,
22094 // so an error is thrown if no module definition is available.
22095 const def = getNgModuleDef(ngModuleType, /* throwNotFound */ true);
22096 const id = def.id;
22097 if (id !== null) {
22098 const existing = modules.get(id);
22099 assertSameOrNotExisting(id, existing, ngModuleType);
22100 modules.set(id, ngModuleType);
22101 }
22102 const imports = maybeUnwrapFn(def.imports);
22103 for (const i of imports) {
22104 if (!visited.has(i)) {
22105 visited.add(i);
22106 recurse(i);
22107 }
22108 }
22109 }
22110}
22111function clearModulesForTest() {
22112 modules.clear();
22113}
22114function getRegisteredNgModuleType(id) {
22115 return (modules.get(id) || autoRegisterModuleById[id]);
22116}
22117
22118/**
22119 * @license
22120 * Copyright Google LLC All Rights Reserved.
22121 *
22122 * Use of this source code is governed by an MIT-style license that can be
22123 * found in the LICENSE file at https://angular.io/license
22124 */
22125function createNgModuleRef__PRE_R3__(ngModule, parentInjector) {
22126 throw new Error(`This API is Ivy-only and is not supported in ViewEngine`);
22127}
22128function createNgModuleRef__POST_R3__(ngModule, parentInjector) {
22129 return new NgModuleRef(ngModule, parentInjector !== null && parentInjector !== void 0 ? parentInjector : null);
22130}
22131/**
22132 * Returns a new NgModuleRef instance based on the NgModule class and parent injector provided.
22133 * @param ngModule NgModule class.
22134 * @param parentInjector Optional injector instance to use as a parent for the module injector. If
22135 * not provided, `NullInjector` will be used instead.
22136 * @publicApi
22137 */
22138const createNgModuleRef$1 = createNgModuleRef__POST_R3__;
22139class NgModuleRef extends NgModuleRef$1 {
22140 constructor(ngModuleType, _parent) {
22141 super();
22142 this._parent = _parent;
22143 // tslint:disable-next-line:require-internal-with-underscore
22144 this._bootstrapComponents = [];
22145 this.injector = this;
22146 this.destroyCbs = [];
22147 // When bootstrapping a module we have a dependency graph that looks like this:
22148 // ApplicationRef -> ComponentFactoryResolver -> NgModuleRef. The problem is that if the
22149 // module being resolved tries to inject the ComponentFactoryResolver, it'll create a
22150 // circular dependency which will result in a runtime error, because the injector doesn't
22151 // exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves
22152 // and providing it, rather than letting the injector resolve it.
22153 this.componentFactoryResolver = new ComponentFactoryResolver(this);
22154 const ngModuleDef = getNgModuleDef(ngModuleType);
22155 ngDevMode &&
22156 assertDefined(ngModuleDef, `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`);
22157 this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap);
22158 this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [
22159 { provide: NgModuleRef$1, useValue: this }, {
22160 provide: ComponentFactoryResolver$1,
22161 useValue: this.componentFactoryResolver
22162 }
22163 ], stringify(ngModuleType));
22164 // We need to resolve the injector types separately from the injector creation, because
22165 // the module might be trying to use this ref in its contructor for DI which will cause a
22166 // circular error that will eventually error out, because the injector isn't created yet.
22167 this._r3Injector._resolveInjectorDefTypes();
22168 this.instance = this.get(ngModuleType);
22169 }
22170 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, injectFlags = InjectFlags.Default) {
22171 if (token === Injector || token === NgModuleRef$1 || token === INJECTOR) {
22172 return this;
22173 }
22174 return this._r3Injector.get(token, notFoundValue, injectFlags);
22175 }
22176 destroy() {
22177 ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
22178 const injector = this._r3Injector;
22179 !injector.destroyed && injector.destroy();
22180 this.destroyCbs.forEach(fn => fn());
22181 this.destroyCbs = null;
22182 }
22183 onDestroy(callback) {
22184 ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
22185 this.destroyCbs.push(callback);
22186 }
22187}
22188class NgModuleFactory extends NgModuleFactory$1 {
22189 constructor(moduleType) {
22190 super();
22191 this.moduleType = moduleType;
22192 const ngModuleDef = getNgModuleDef(moduleType);
22193 if (ngModuleDef !== null) {
22194 // Register the NgModule with Angular's module registry. The location (and hence timing) of
22195 // this call is critical to ensure this works correctly (modules get registered when expected)
22196 // without bloating bundles (modules are registered when otherwise not referenced).
22197 //
22198 // In View Engine, registration occurs in the .ngfactory.js file as a side effect. This has
22199 // several practical consequences:
22200 //
22201 // - If an .ngfactory file is not imported from, the module won't be registered (and can be
22202 // tree shaken).
22203 // - If an .ngfactory file is imported from, the module will be registered even if an instance
22204 // is not actually created (via `create` below).
22205 // - Since an .ngfactory file in View Engine references the .ngfactory files of the NgModule's
22206 // imports,
22207 //
22208 // In Ivy, things are a bit different. .ngfactory files still exist for compatibility, but are
22209 // not a required API to use - there are other ways to obtain an NgModuleFactory for a given
22210 // NgModule. Thus, relying on a side effect in the .ngfactory file is not sufficient. Instead,
22211 // the side effect of registration is added here, in the constructor of NgModuleFactory,
22212 // ensuring no matter how a factory is created, the module is registered correctly.
22213 //
22214 // An alternative would be to include the registration side effect inline following the actual
22215 // NgModule definition. This also has the correct timing, but breaks tree-shaking - modules
22216 // will be registered and retained even if they're otherwise never referenced.
22217 registerNgModuleType(moduleType);
22218 }
22219 }
22220 create(parentInjector) {
22221 return new NgModuleRef(this.moduleType, parentInjector);
22222 }
22223}
22224
22225/**
22226 * @license
22227 * Copyright Google LLC All Rights Reserved.
22228 *
22229 * Use of this source code is governed by an MIT-style license that can be
22230 * found in the LICENSE file at https://angular.io/license
22231 */
22232/**
22233 * Bindings for pure functions are stored after regular bindings.
22234 *
22235 * |-------decls------|---------vars---------| |----- hostVars (dir1) ------|
22236 * ------------------------------------------------------------------------------------------
22237 * | nodes/refs/pipes | bindings | fn slots | injector | dir1 | host bindings | host slots |
22238 * ------------------------------------------------------------------------------------------
22239 * ^ ^
22240 * TView.bindingStartIndex TView.expandoStartIndex
22241 *
22242 * Pure function instructions are given an offset from the binding root. Adding the offset to the
22243 * binding root gives the first index where the bindings are stored. In component views, the binding
22244 * root is the bindingStartIndex. In host bindings, the binding root is the expandoStartIndex +
22245 * any directive instances + any hostVars in directives evaluated before it.
22246 *
22247 * See VIEW_DATA.md for more information about host binding resolution.
22248 */
22249/**
22250 * If the value hasn't been saved, calls the pure function to store and return the
22251 * value. If it has been saved, returns the saved value.
22252 *
22253 * @param slotOffset the offset from binding root to the reserved slot
22254 * @param pureFn Function that returns a value
22255 * @param thisArg Optional calling context of pureFn
22256 * @returns value
22257 *
22258 * @codeGenApi
22259 */
22260function ɵɵpureFunction0(slotOffset, pureFn, thisArg) {
22261 const bindingIndex = getBindingRoot() + slotOffset;
22262 const lView = getLView();
22263 return lView[bindingIndex] === NO_CHANGE ?
22264 updateBinding(lView, bindingIndex, thisArg ? pureFn.call(thisArg) : pureFn()) :
22265 getBinding(lView, bindingIndex);
22266}
22267/**
22268 * If the value of the provided exp has changed, calls the pure function to return
22269 * an updated value. Or if the value has not changed, returns cached value.
22270 *
22271 * @param slotOffset the offset from binding root to the reserved slot
22272 * @param pureFn Function that returns an updated value
22273 * @param exp Updated expression value
22274 * @param thisArg Optional calling context of pureFn
22275 * @returns Updated or cached value
22276 *
22277 * @codeGenApi
22278 */
22279function ɵɵpureFunction1(slotOffset, pureFn, exp, thisArg) {
22280 return pureFunction1Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp, thisArg);
22281}
22282/**
22283 * If the value of any provided exp has changed, calls the pure function to return
22284 * an updated value. Or if no values have changed, returns cached value.
22285 *
22286 * @param slotOffset the offset from binding root to the reserved slot
22287 * @param pureFn
22288 * @param exp1
22289 * @param exp2
22290 * @param thisArg Optional calling context of pureFn
22291 * @returns Updated or cached value
22292 *
22293 * @codeGenApi
22294 */
22295function ɵɵpureFunction2(slotOffset, pureFn, exp1, exp2, thisArg) {
22296 return pureFunction2Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, thisArg);
22297}
22298/**
22299 * If the value of any provided exp has changed, calls the pure function to return
22300 * an updated value. Or if no values have changed, returns cached value.
22301 *
22302 * @param slotOffset the offset from binding root to the reserved slot
22303 * @param pureFn
22304 * @param exp1
22305 * @param exp2
22306 * @param exp3
22307 * @param thisArg Optional calling context of pureFn
22308 * @returns Updated or cached value
22309 *
22310 * @codeGenApi
22311 */
22312function ɵɵpureFunction3(slotOffset, pureFn, exp1, exp2, exp3, thisArg) {
22313 return pureFunction3Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, thisArg);
22314}
22315/**
22316 * If the value of any provided exp has changed, calls the pure function to return
22317 * an updated value. Or if no values have changed, returns cached value.
22318 *
22319 * @param slotOffset the offset from binding root to the reserved slot
22320 * @param pureFn
22321 * @param exp1
22322 * @param exp2
22323 * @param exp3
22324 * @param exp4
22325 * @param thisArg Optional calling context of pureFn
22326 * @returns Updated or cached value
22327 *
22328 * @codeGenApi
22329 */
22330function ɵɵpureFunction4(slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) {
22331 return pureFunction4Internal(getLView(), getBindingRoot(), slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg);
22332}
22333/**
22334 * If the value of any provided exp has changed, calls the pure function to return
22335 * an updated value. Or if no values have changed, returns cached value.
22336 *
22337 * @param slotOffset the offset from binding root to the reserved slot
22338 * @param pureFn
22339 * @param exp1
22340 * @param exp2
22341 * @param exp3
22342 * @param exp4
22343 * @param exp5
22344 * @param thisArg Optional calling context of pureFn
22345 * @returns Updated or cached value
22346 *
22347 * @codeGenApi
22348 */
22349function ɵɵpureFunction5(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, thisArg) {
22350 const bindingIndex = getBindingRoot() + slotOffset;
22351 const lView = getLView();
22352 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22353 return bindingUpdated(lView, bindingIndex + 4, exp5) || different ?
22354 updateBinding(lView, bindingIndex + 5, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5) :
22355 pureFn(exp1, exp2, exp3, exp4, exp5)) :
22356 getBinding(lView, bindingIndex + 5);
22357}
22358/**
22359 * If the value of any provided exp has changed, calls the pure function to return
22360 * an updated value. Or if no values have changed, returns cached value.
22361 *
22362 * @param slotOffset the offset from binding root to the reserved slot
22363 * @param pureFn
22364 * @param exp1
22365 * @param exp2
22366 * @param exp3
22367 * @param exp4
22368 * @param exp5
22369 * @param exp6
22370 * @param thisArg Optional calling context of pureFn
22371 * @returns Updated or cached value
22372 *
22373 * @codeGenApi
22374 */
22375function ɵɵpureFunction6(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, thisArg) {
22376 const bindingIndex = getBindingRoot() + slotOffset;
22377 const lView = getLView();
22378 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22379 return bindingUpdated2(lView, bindingIndex + 4, exp5, exp6) || different ?
22380 updateBinding(lView, bindingIndex + 6, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6) :
22381 pureFn(exp1, exp2, exp3, exp4, exp5, exp6)) :
22382 getBinding(lView, bindingIndex + 6);
22383}
22384/**
22385 * If the value of any provided exp has changed, calls the pure function to return
22386 * an updated value. Or if no values have changed, returns cached value.
22387 *
22388 * @param slotOffset the offset from binding root to the reserved slot
22389 * @param pureFn
22390 * @param exp1
22391 * @param exp2
22392 * @param exp3
22393 * @param exp4
22394 * @param exp5
22395 * @param exp6
22396 * @param exp7
22397 * @param thisArg Optional calling context of pureFn
22398 * @returns Updated or cached value
22399 *
22400 * @codeGenApi
22401 */
22402function ɵɵpureFunction7(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, thisArg) {
22403 const bindingIndex = getBindingRoot() + slotOffset;
22404 const lView = getLView();
22405 let different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22406 return bindingUpdated3(lView, bindingIndex + 4, exp5, exp6, exp7) || different ?
22407 updateBinding(lView, bindingIndex + 7, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7) :
22408 pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7)) :
22409 getBinding(lView, bindingIndex + 7);
22410}
22411/**
22412 * If the value of any provided exp has changed, calls the pure function to return
22413 * an updated value. Or if no values have changed, returns cached value.
22414 *
22415 * @param slotOffset the offset from binding root to the reserved slot
22416 * @param pureFn
22417 * @param exp1
22418 * @param exp2
22419 * @param exp3
22420 * @param exp4
22421 * @param exp5
22422 * @param exp6
22423 * @param exp7
22424 * @param exp8
22425 * @param thisArg Optional calling context of pureFn
22426 * @returns Updated or cached value
22427 *
22428 * @codeGenApi
22429 */
22430function ɵɵpureFunction8(slotOffset, pureFn, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, thisArg) {
22431 const bindingIndex = getBindingRoot() + slotOffset;
22432 const lView = getLView();
22433 const different = bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4);
22434 return bindingUpdated4(lView, bindingIndex + 4, exp5, exp6, exp7, exp8) || different ?
22435 updateBinding(lView, bindingIndex + 8, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8) :
22436 pureFn(exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8)) :
22437 getBinding(lView, bindingIndex + 8);
22438}
22439/**
22440 * pureFunction instruction that can support any number of bindings.
22441 *
22442 * If the value of any provided exp has changed, calls the pure function to return
22443 * an updated value. Or if no values have changed, returns cached value.
22444 *
22445 * @param slotOffset the offset from binding root to the reserved slot
22446 * @param pureFn A pure function that takes binding values and builds an object or array
22447 * containing those values.
22448 * @param exps An array of binding values
22449 * @param thisArg Optional calling context of pureFn
22450 * @returns Updated or cached value
22451 *
22452 * @codeGenApi
22453 */
22454function ɵɵpureFunctionV(slotOffset, pureFn, exps, thisArg) {
22455 return pureFunctionVInternal(getLView(), getBindingRoot(), slotOffset, pureFn, exps, thisArg);
22456}
22457/**
22458 * Results of a pure function invocation are stored in LView in a dedicated slot that is initialized
22459 * to NO_CHANGE. In rare situations a pure pipe might throw an exception on the very first
22460 * invocation and not produce any valid results. In this case LView would keep holding the NO_CHANGE
22461 * value. The NO_CHANGE is not something that we can use in expressions / bindings thus we convert
22462 * it to `undefined`.
22463 */
22464function getPureFunctionReturnValue(lView, returnValueIndex) {
22465 ngDevMode && assertIndexInRange(lView, returnValueIndex);
22466 const lastReturnValue = lView[returnValueIndex];
22467 return lastReturnValue === NO_CHANGE ? undefined : lastReturnValue;
22468}
22469/**
22470 * If the value of the provided exp has changed, calls the pure function to return
22471 * an updated value. Or if the value has not changed, returns cached value.
22472 *
22473 * @param lView LView in which the function is being executed.
22474 * @param bindingRoot Binding root index.
22475 * @param slotOffset the offset from binding root to the reserved slot
22476 * @param pureFn Function that returns an updated value
22477 * @param exp Updated expression value
22478 * @param thisArg Optional calling context of pureFn
22479 * @returns Updated or cached value
22480 */
22481function pureFunction1Internal(lView, bindingRoot, slotOffset, pureFn, exp, thisArg) {
22482 const bindingIndex = bindingRoot + slotOffset;
22483 return bindingUpdated(lView, bindingIndex, exp) ?
22484 updateBinding(lView, bindingIndex + 1, thisArg ? pureFn.call(thisArg, exp) : pureFn(exp)) :
22485 getPureFunctionReturnValue(lView, bindingIndex + 1);
22486}
22487/**
22488 * If the value of any provided exp has changed, calls the pure function to return
22489 * an updated value. Or if no values have changed, returns cached value.
22490 *
22491 * @param lView LView in which the function is being executed.
22492 * @param bindingRoot Binding root index.
22493 * @param slotOffset the offset from binding root to the reserved slot
22494 * @param pureFn
22495 * @param exp1
22496 * @param exp2
22497 * @param thisArg Optional calling context of pureFn
22498 * @returns Updated or cached value
22499 */
22500function pureFunction2Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, thisArg) {
22501 const bindingIndex = bindingRoot + slotOffset;
22502 return bindingUpdated2(lView, bindingIndex, exp1, exp2) ?
22503 updateBinding(lView, bindingIndex + 2, thisArg ? pureFn.call(thisArg, exp1, exp2) : pureFn(exp1, exp2)) :
22504 getPureFunctionReturnValue(lView, bindingIndex + 2);
22505}
22506/**
22507 * If the value of any provided exp has changed, calls the pure function to return
22508 * an updated value. Or if no values have changed, returns cached value.
22509 *
22510 * @param lView LView in which the function is being executed.
22511 * @param bindingRoot Binding root index.
22512 * @param slotOffset the offset from binding root to the reserved slot
22513 * @param pureFn
22514 * @param exp1
22515 * @param exp2
22516 * @param exp3
22517 * @param thisArg Optional calling context of pureFn
22518 * @returns Updated or cached value
22519 */
22520function pureFunction3Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, thisArg) {
22521 const bindingIndex = bindingRoot + slotOffset;
22522 return bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) ?
22523 updateBinding(lView, bindingIndex + 3, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3) : pureFn(exp1, exp2, exp3)) :
22524 getPureFunctionReturnValue(lView, bindingIndex + 3);
22525}
22526/**
22527 * If the value of any provided exp has changed, calls the pure function to return
22528 * an updated value. Or if no values have changed, returns cached value.
22529 *
22530 * @param lView LView in which the function is being executed.
22531 * @param bindingRoot Binding root index.
22532 * @param slotOffset the offset from binding root to the reserved slot
22533 * @param pureFn
22534 * @param exp1
22535 * @param exp2
22536 * @param exp3
22537 * @param exp4
22538 * @param thisArg Optional calling context of pureFn
22539 * @returns Updated or cached value
22540 *
22541 */
22542function pureFunction4Internal(lView, bindingRoot, slotOffset, pureFn, exp1, exp2, exp3, exp4, thisArg) {
22543 const bindingIndex = bindingRoot + slotOffset;
22544 return bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) ?
22545 updateBinding(lView, bindingIndex + 4, thisArg ? pureFn.call(thisArg, exp1, exp2, exp3, exp4) : pureFn(exp1, exp2, exp3, exp4)) :
22546 getPureFunctionReturnValue(lView, bindingIndex + 4);
22547}
22548/**
22549 * pureFunction instruction that can support any number of bindings.
22550 *
22551 * If the value of any provided exp has changed, calls the pure function to return
22552 * an updated value. Or if no values have changed, returns cached value.
22553 *
22554 * @param lView LView in which the function is being executed.
22555 * @param bindingRoot Binding root index.
22556 * @param slotOffset the offset from binding root to the reserved slot
22557 * @param pureFn A pure function that takes binding values and builds an object or array
22558 * containing those values.
22559 * @param exps An array of binding values
22560 * @param thisArg Optional calling context of pureFn
22561 * @returns Updated or cached value
22562 */
22563function pureFunctionVInternal(lView, bindingRoot, slotOffset, pureFn, exps, thisArg) {
22564 let bindingIndex = bindingRoot + slotOffset;
22565 let different = false;
22566 for (let i = 0; i < exps.length; i++) {
22567 bindingUpdated(lView, bindingIndex++, exps[i]) && (different = true);
22568 }
22569 return different ? updateBinding(lView, bindingIndex, pureFn.apply(thisArg, exps)) :
22570 getPureFunctionReturnValue(lView, bindingIndex);
22571}
22572
22573/**
22574 * @license
22575 * Copyright Google LLC All Rights Reserved.
22576 *
22577 * Use of this source code is governed by an MIT-style license that can be
22578 * found in the LICENSE file at https://angular.io/license
22579 */
22580/**
22581 * Create a pipe.
22582 *
22583 * @param index Pipe index where the pipe will be stored.
22584 * @param pipeName The name of the pipe
22585 * @returns T the instance of the pipe.
22586 *
22587 * @codeGenApi
22588 */
22589function ɵɵpipe(index, pipeName) {
22590 const tView = getTView();
22591 let pipeDef;
22592 const adjustedIndex = index + HEADER_OFFSET;
22593 if (tView.firstCreatePass) {
22594 pipeDef = getPipeDef(pipeName, tView.pipeRegistry);
22595 tView.data[adjustedIndex] = pipeDef;
22596 if (pipeDef.onDestroy) {
22597 (tView.destroyHooks || (tView.destroyHooks = [])).push(adjustedIndex, pipeDef.onDestroy);
22598 }
22599 }
22600 else {
22601 pipeDef = tView.data[adjustedIndex];
22602 }
22603 const pipeFactory = pipeDef.factory || (pipeDef.factory = getFactoryDef(pipeDef.type, true));
22604 const previousInjectImplementation = setInjectImplementation(ɵɵdirectiveInject);
22605 try {
22606 // DI for pipes is supposed to behave like directives when placed on a component
22607 // host node, which means that we have to disable access to `viewProviders`.
22608 const previousIncludeViewProviders = setIncludeViewProviders(false);
22609 const pipeInstance = pipeFactory();
22610 setIncludeViewProviders(previousIncludeViewProviders);
22611 store(tView, getLView(), adjustedIndex, pipeInstance);
22612 return pipeInstance;
22613 }
22614 finally {
22615 // we have to restore the injector implementation in finally, just in case the creation of the
22616 // pipe throws an error.
22617 setInjectImplementation(previousInjectImplementation);
22618 }
22619}
22620/**
22621 * Searches the pipe registry for a pipe with the given name. If one is found,
22622 * returns the pipe. Otherwise, an error is thrown because the pipe cannot be resolved.
22623 *
22624 * @param name Name of pipe to resolve
22625 * @param registry Full list of available pipes
22626 * @returns Matching PipeDef
22627 */
22628function getPipeDef(name, registry) {
22629 if (registry) {
22630 for (let i = registry.length - 1; i >= 0; i--) {
22631 const pipeDef = registry[i];
22632 if (name === pipeDef.name) {
22633 return pipeDef;
22634 }
22635 }
22636 }
22637 throw new RuntimeError("302" /* PIPE_NOT_FOUND */, `The pipe '${name}' could not be found!`);
22638}
22639/**
22640 * Invokes a pipe with 1 arguments.
22641 *
22642 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22643 * the pipe only when an input to the pipe changes.
22644 *
22645 * @param index Pipe index where the pipe was stored on creation.
22646 * @param slotOffset the offset in the reserved slot space
22647 * @param v1 1st argument to {@link PipeTransform#transform}.
22648 *
22649 * @codeGenApi
22650 */
22651function ɵɵpipeBind1(index, slotOffset, v1) {
22652 const adjustedIndex = index + HEADER_OFFSET;
22653 const lView = getLView();
22654 const pipeInstance = load(lView, adjustedIndex);
22655 return isPure(lView, adjustedIndex) ?
22656 pureFunction1Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, pipeInstance) :
22657 pipeInstance.transform(v1);
22658}
22659/**
22660 * Invokes a pipe with 2 arguments.
22661 *
22662 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22663 * the pipe only when an input to the pipe changes.
22664 *
22665 * @param index Pipe index where the pipe was stored on creation.
22666 * @param slotOffset the offset in the reserved slot space
22667 * @param v1 1st argument to {@link PipeTransform#transform}.
22668 * @param v2 2nd argument to {@link PipeTransform#transform}.
22669 *
22670 * @codeGenApi
22671 */
22672function ɵɵpipeBind2(index, slotOffset, v1, v2) {
22673 const adjustedIndex = index + HEADER_OFFSET;
22674 const lView = getLView();
22675 const pipeInstance = load(lView, adjustedIndex);
22676 return isPure(lView, adjustedIndex) ?
22677 pureFunction2Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, pipeInstance) :
22678 pipeInstance.transform(v1, v2);
22679}
22680/**
22681 * Invokes a pipe with 3 arguments.
22682 *
22683 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22684 * the pipe only when an input to the pipe changes.
22685 *
22686 * @param index Pipe index where the pipe was stored on creation.
22687 * @param slotOffset the offset in the reserved slot space
22688 * @param v1 1st argument to {@link PipeTransform#transform}.
22689 * @param v2 2nd argument to {@link PipeTransform#transform}.
22690 * @param v3 4rd argument to {@link PipeTransform#transform}.
22691 *
22692 * @codeGenApi
22693 */
22694function ɵɵpipeBind3(index, slotOffset, v1, v2, v3) {
22695 const adjustedIndex = index + HEADER_OFFSET;
22696 const lView = getLView();
22697 const pipeInstance = load(lView, adjustedIndex);
22698 return isPure(lView, adjustedIndex) ?
22699 pureFunction3Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, pipeInstance) :
22700 pipeInstance.transform(v1, v2, v3);
22701}
22702/**
22703 * Invokes a pipe with 4 arguments.
22704 *
22705 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22706 * the pipe only when an input to the pipe changes.
22707 *
22708 * @param index Pipe index where the pipe was stored on creation.
22709 * @param slotOffset the offset in the reserved slot space
22710 * @param v1 1st argument to {@link PipeTransform#transform}.
22711 * @param v2 2nd argument to {@link PipeTransform#transform}.
22712 * @param v3 3rd argument to {@link PipeTransform#transform}.
22713 * @param v4 4th argument to {@link PipeTransform#transform}.
22714 *
22715 * @codeGenApi
22716 */
22717function ɵɵpipeBind4(index, slotOffset, v1, v2, v3, v4) {
22718 const adjustedIndex = index + HEADER_OFFSET;
22719 const lView = getLView();
22720 const pipeInstance = load(lView, adjustedIndex);
22721 return isPure(lView, adjustedIndex) ? pureFunction4Internal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, v1, v2, v3, v4, pipeInstance) :
22722 pipeInstance.transform(v1, v2, v3, v4);
22723}
22724/**
22725 * Invokes a pipe with variable number of arguments.
22726 *
22727 * This instruction acts as a guard to {@link PipeTransform#transform} invoking
22728 * the pipe only when an input to the pipe changes.
22729 *
22730 * @param index Pipe index where the pipe was stored on creation.
22731 * @param slotOffset the offset in the reserved slot space
22732 * @param values Array of arguments to pass to {@link PipeTransform#transform} method.
22733 *
22734 * @codeGenApi
22735 */
22736function ɵɵpipeBindV(index, slotOffset, values) {
22737 const adjustedIndex = index + HEADER_OFFSET;
22738 const lView = getLView();
22739 const pipeInstance = load(lView, adjustedIndex);
22740 return isPure(lView, adjustedIndex) ?
22741 pureFunctionVInternal(lView, getBindingRoot(), slotOffset, pipeInstance.transform, values, pipeInstance) :
22742 pipeInstance.transform.apply(pipeInstance, values);
22743}
22744function isPure(lView, index) {
22745 return lView[TVIEW].data[index].pure;
22746}
22747
22748/**
22749 * @license
22750 * Copyright Google LLC All Rights Reserved.
22751 *
22752 * Use of this source code is governed by an MIT-style license that can be
22753 * found in the LICENSE file at https://angular.io/license
22754 */
22755class EventEmitter_ extends Subject {
22756 constructor(isAsync = false) {
22757 super();
22758 this.__isAsync = isAsync;
22759 }
22760 emit(value) {
22761 super.next(value);
22762 }
22763 subscribe(observerOrNext, error, complete) {
22764 var _a, _b, _c;
22765 let nextFn = observerOrNext;
22766 let errorFn = error || (() => null);
22767 let completeFn = complete;
22768 if (observerOrNext && typeof observerOrNext === 'object') {
22769 const observer = observerOrNext;
22770 nextFn = (_a = observer.next) === null || _a === void 0 ? void 0 : _a.bind(observer);
22771 errorFn = (_b = observer.error) === null || _b === void 0 ? void 0 : _b.bind(observer);
22772 completeFn = (_c = observer.complete) === null || _c === void 0 ? void 0 : _c.bind(observer);
22773 }
22774 if (this.__isAsync) {
22775 errorFn = _wrapInTimeout(errorFn);
22776 if (nextFn) {
22777 nextFn = _wrapInTimeout(nextFn);
22778 }
22779 if (completeFn) {
22780 completeFn = _wrapInTimeout(completeFn);
22781 }
22782 }
22783 const sink = super.subscribe({ next: nextFn, error: errorFn, complete: completeFn });
22784 if (observerOrNext instanceof Subscription) {
22785 observerOrNext.add(sink);
22786 }
22787 return sink;
22788 }
22789}
22790function _wrapInTimeout(fn) {
22791 return (value) => {
22792 setTimeout(fn, undefined, value);
22793 };
22794}
22795/**
22796 * @publicApi
22797 */
22798const EventEmitter = EventEmitter_;
22799
22800/**
22801 * @license
22802 * Copyright Google LLC All Rights Reserved.
22803 *
22804 * Use of this source code is governed by an MIT-style license that can be
22805 * found in the LICENSE file at https://angular.io/license
22806 */
22807function symbolIterator() {
22808 return this._results[getSymbolIterator()]();
22809}
22810/**
22811 * An unmodifiable list of items that Angular keeps up to date when the state
22812 * of the application changes.
22813 *
22814 * The type of object that {@link ViewChildren}, {@link ContentChildren}, and {@link QueryList}
22815 * provide.
22816 *
22817 * Implements an iterable interface, therefore it can be used in both ES6
22818 * javascript `for (var i of items)` loops as well as in Angular templates with
22819 * `*ngFor="let i of myList"`.
22820 *
22821 * Changes can be observed by subscribing to the changes `Observable`.
22822 *
22823 * NOTE: In the future this class will implement an `Observable` interface.
22824 *
22825 * @usageNotes
22826 * ### Example
22827 * ```typescript
22828 * @Component({...})
22829 * class Container {
22830 * @ViewChildren(Item) items:QueryList<Item>;
22831 * }
22832 * ```
22833 *
22834 * @publicApi
22835 */
22836class QueryList {
22837 /**
22838 * @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change
22839 * has occurred. Or if it should fire when query is recomputed. (recomputing could resolve in
22840 * the same result)
22841 */
22842 constructor(_emitDistinctChangesOnly = false) {
22843 this._emitDistinctChangesOnly = _emitDistinctChangesOnly;
22844 this.dirty = true;
22845 this._results = [];
22846 this._changesDetected = false;
22847 this._changes = null;
22848 this.length = 0;
22849 this.first = undefined;
22850 this.last = undefined;
22851 // This function should be declared on the prototype, but doing so there will cause the class
22852 // declaration to have side-effects and become not tree-shakable. For this reason we do it in
22853 // the constructor.
22854 // [getSymbolIterator()](): Iterator<T> { ... }
22855 const symbol = getSymbolIterator();
22856 const proto = QueryList.prototype;
22857 if (!proto[symbol])
22858 proto[symbol] = symbolIterator;
22859 }
22860 /**
22861 * Returns `Observable` of `QueryList` notifying the subscriber of changes.
22862 */
22863 get changes() {
22864 return this._changes || (this._changes = new EventEmitter());
22865 }
22866 /**
22867 * Returns the QueryList entry at `index`.
22868 */
22869 get(index) {
22870 return this._results[index];
22871 }
22872 /**
22873 * See
22874 * [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
22875 */
22876 map(fn) {
22877 return this._results.map(fn);
22878 }
22879 /**
22880 * See
22881 * [Array.filter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)
22882 */
22883 filter(fn) {
22884 return this._results.filter(fn);
22885 }
22886 /**
22887 * See
22888 * [Array.find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find)
22889 */
22890 find(fn) {
22891 return this._results.find(fn);
22892 }
22893 /**
22894 * See
22895 * [Array.reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
22896 */
22897 reduce(fn, init) {
22898 return this._results.reduce(fn, init);
22899 }
22900 /**
22901 * See
22902 * [Array.forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)
22903 */
22904 forEach(fn) {
22905 this._results.forEach(fn);
22906 }
22907 /**
22908 * See
22909 * [Array.some](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
22910 */
22911 some(fn) {
22912 return this._results.some(fn);
22913 }
22914 /**
22915 * Returns a copy of the internal results list as an Array.
22916 */
22917 toArray() {
22918 return this._results.slice();
22919 }
22920 toString() {
22921 return this._results.toString();
22922 }
22923 /**
22924 * Updates the stored data of the query list, and resets the `dirty` flag to `false`, so that
22925 * on change detection, it will not notify of changes to the queries, unless a new change
22926 * occurs.
22927 *
22928 * @param resultsTree The query results to store
22929 * @param identityAccessor Optional function for extracting stable object identity from a value
22930 * in the array. This function is executed for each element of the query result list while
22931 * comparing current query list with the new one (provided as a first argument of the `reset`
22932 * function) to detect if the lists are different. If the function is not provided, elements
22933 * are compared as is (without any pre-processing).
22934 */
22935 reset(resultsTree, identityAccessor) {
22936 // Cast to `QueryListInternal` so that we can mutate fields which are readonly for the usage of
22937 // QueryList (but not for QueryList itself.)
22938 const self = this;
22939 self.dirty = false;
22940 const newResultFlat = flatten(resultsTree);
22941 if (this._changesDetected = !arrayEquals(self._results, newResultFlat, identityAccessor)) {
22942 self._results = newResultFlat;
22943 self.length = newResultFlat.length;
22944 self.last = newResultFlat[this.length - 1];
22945 self.first = newResultFlat[0];
22946 }
22947 }
22948 /**
22949 * Triggers a change event by emitting on the `changes` {@link EventEmitter}.
22950 */
22951 notifyOnChanges() {
22952 if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly))
22953 this._changes.emit(this);
22954 }
22955 /** internal */
22956 setDirty() {
22957 this.dirty = true;
22958 }
22959 /** internal */
22960 destroy() {
22961 this.changes.complete();
22962 this.changes.unsubscribe();
22963 }
22964}
22965Symbol.iterator;
22966
22967/**
22968 * @license
22969 * Copyright Google LLC All Rights Reserved.
22970 *
22971 * Use of this source code is governed by an MIT-style license that can be
22972 * found in the LICENSE file at https://angular.io/license
22973 */
22974const SWITCH_TEMPLATE_REF_FACTORY__POST_R3__ = injectTemplateRef;
22975const SWITCH_TEMPLATE_REF_FACTORY__PRE_R3__ = noop;
22976const SWITCH_TEMPLATE_REF_FACTORY = SWITCH_TEMPLATE_REF_FACTORY__POST_R3__;
22977/**
22978 * Represents an embedded template that can be used to instantiate embedded views.
22979 * To instantiate embedded views based on a template, use the `ViewContainerRef`
22980 * method `createEmbeddedView()`.
22981 *
22982 * Access a `TemplateRef` instance by placing a directive on an `<ng-template>`
22983 * element (or directive prefixed with `*`). The `TemplateRef` for the embedded view
22984 * is injected into the constructor of the directive,
22985 * using the `TemplateRef` token.
22986 *
22987 * You can also use a `Query` to find a `TemplateRef` associated with
22988 * a component or a directive.
22989 *
22990 * @see `ViewContainerRef`
22991 * @see [Navigate the Component Tree with DI](guide/dependency-injection-navtree)
22992 *
22993 * @publicApi
22994 */
22995class TemplateRef {
22996}
22997/**
22998 * @internal
22999 * @nocollapse
23000 */
23001TemplateRef.__NG_ELEMENT_ID__ = SWITCH_TEMPLATE_REF_FACTORY;
23002const ViewEngineTemplateRef = TemplateRef;
23003const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
23004 constructor(_declarationLView, _declarationTContainer, elementRef) {
23005 super();
23006 this._declarationLView = _declarationLView;
23007 this._declarationTContainer = _declarationTContainer;
23008 this.elementRef = elementRef;
23009 }
23010 createEmbeddedView(context) {
23011 const embeddedTView = this._declarationTContainer.tViews;
23012 const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* CheckAlways */, null, embeddedTView.declTNode, null, null, null, null);
23013 const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
23014 ngDevMode && assertLContainer(declarationLContainer);
23015 embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
23016 const declarationViewLQueries = this._declarationLView[QUERIES];
23017 if (declarationViewLQueries !== null) {
23018 embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
23019 }
23020 renderView(embeddedTView, embeddedLView, context);
23021 return new ViewRef$1(embeddedLView);
23022 }
23023};
23024/**
23025 * Creates a TemplateRef given a node.
23026 *
23027 * @returns The TemplateRef instance to use
23028 */
23029function injectTemplateRef() {
23030 return createTemplateRef(getCurrentTNode(), getLView());
23031}
23032/**
23033 * Creates a TemplateRef and stores it on the injector.
23034 *
23035 * @param hostTNode The node on which a TemplateRef is requested
23036 * @param hostLView The `LView` to which the node belongs
23037 * @returns The TemplateRef instance or null if we can't create a TemplateRef on a given node type
23038 */
23039function createTemplateRef(hostTNode, hostLView) {
23040 if (hostTNode.type & 4 /* Container */) {
23041 ngDevMode && assertDefined(hostTNode.tViews, 'TView must be allocated');
23042 return new R3TemplateRef(hostLView, hostTNode, createElementRef(hostTNode, hostLView));
23043 }
23044 return null;
23045}
23046
23047const SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__ = injectViewContainerRef;
23048const SWITCH_VIEW_CONTAINER_REF_FACTORY__PRE_R3__ = noop;
23049const SWITCH_VIEW_CONTAINER_REF_FACTORY = SWITCH_VIEW_CONTAINER_REF_FACTORY__POST_R3__;
23050/**
23051 * Represents a container where one or more views can be attached to a component.
23052 *
23053 * Can contain *host views* (created by instantiating a
23054 * component with the `createComponent()` method), and *embedded views*
23055 * (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method).
23056 *
23057 * A view container instance can contain other view containers,
23058 * creating a [view hierarchy](guide/glossary#view-tree).
23059 *
23060 * @see `ComponentRef`
23061 * @see `EmbeddedViewRef`
23062 *
23063 * @publicApi
23064 */
23065class ViewContainerRef {
23066}
23067/**
23068 * @internal
23069 * @nocollapse
23070 */
23071ViewContainerRef.__NG_ELEMENT_ID__ = SWITCH_VIEW_CONTAINER_REF_FACTORY;
23072/**
23073 * Creates a ViewContainerRef and stores it on the injector. Or, if the ViewContainerRef
23074 * already exists, retrieves the existing ViewContainerRef.
23075 *
23076 * @returns The ViewContainerRef instance to use
23077 */
23078function injectViewContainerRef() {
23079 const previousTNode = getCurrentTNode();
23080 return createContainerRef(previousTNode, getLView());
23081}
23082const VE_ViewContainerRef = ViewContainerRef;
23083const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
23084 constructor(_lContainer, _hostTNode, _hostLView) {
23085 super();
23086 this._lContainer = _lContainer;
23087 this._hostTNode = _hostTNode;
23088 this._hostLView = _hostLView;
23089 }
23090 get element() {
23091 return createElementRef(this._hostTNode, this._hostLView);
23092 }
23093 get injector() {
23094 return new NodeInjector(this._hostTNode, this._hostLView);
23095 }
23096 /** @deprecated No replacement */
23097 get parentInjector() {
23098 const parentLocation = getParentInjectorLocation(this._hostTNode, this._hostLView);
23099 if (hasParentInjector(parentLocation)) {
23100 const parentView = getParentInjectorView(parentLocation, this._hostLView);
23101 const injectorIndex = getParentInjectorIndex(parentLocation);
23102 ngDevMode && assertNodeInjector(parentView, injectorIndex);
23103 const parentTNode = parentView[TVIEW].data[injectorIndex + 8 /* TNODE */];
23104 return new NodeInjector(parentTNode, parentView);
23105 }
23106 else {
23107 return new NodeInjector(null, this._hostLView);
23108 }
23109 }
23110 clear() {
23111 while (this.length > 0) {
23112 this.remove(this.length - 1);
23113 }
23114 }
23115 get(index) {
23116 const viewRefs = getViewRefs(this._lContainer);
23117 return viewRefs !== null && viewRefs[index] || null;
23118 }
23119 get length() {
23120 return this._lContainer.length - CONTAINER_HEADER_OFFSET;
23121 }
23122 createEmbeddedView(templateRef, context, index) {
23123 const viewRef = templateRef.createEmbeddedView(context || {});
23124 this.insert(viewRef, index);
23125 return viewRef;
23126 }
23127 createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, ngModuleRef) {
23128 const isComponentFactory = componentFactoryOrType && !isType(componentFactoryOrType);
23129 let index;
23130 // This function supports 2 signatures and we need to handle options correctly for both:
23131 // 1. When first argument is a Component type. This signature also requires extra
23132 // options to be provided as as object (more ergonomic option).
23133 // 2. First argument is a Component factory. In this case extra options are represented as
23134 // positional arguments. This signature is less ergonomic and will be deprecated.
23135 if (isComponentFactory) {
23136 if (ngDevMode) {
23137 assertEqual(typeof indexOrOptions !== 'object', true, 'It looks like Component factory was provided as the first argument ' +
23138 'and an options object as the second argument. This combination of arguments ' +
23139 'is incompatible. You can either change the first argument to provide Component ' +
23140 'type or change the second argument to be a number (representing an index at ' +
23141 'which to insert the new component\'s host view into this container)');
23142 }
23143 index = indexOrOptions;
23144 }
23145 else {
23146 if (ngDevMode) {
23147 assertDefined(getComponentDef(componentFactoryOrType), `Provided Component class doesn't contain Component definition. ` +
23148 `Please check whether provided class has @Component decorator.`);
23149 assertEqual(typeof indexOrOptions !== 'number', true, 'It looks like Component type was provided as the first argument ' +
23150 'and a number (representing an index at which to insert the new component\'s ' +
23151 'host view into this container as the second argument. This combination of arguments ' +
23152 'is incompatible. Please use an object as the second argument instead.');
23153 }
23154 const options = (indexOrOptions || {});
23155 index = options.index;
23156 injector = options.injector;
23157 projectableNodes = options.projectableNodes;
23158 ngModuleRef = options.ngModuleRef;
23159 }
23160 const componentFactory = isComponentFactory ?
23161 componentFactoryOrType :
23162 new ComponentFactory(getComponentDef(componentFactoryOrType));
23163 const contextInjector = injector || this.parentInjector;
23164 if (!ngModuleRef && componentFactory.ngModule == null && contextInjector) {
23165 // DO NOT REFACTOR. The code here used to have a `value || undefined` expression
23166 // which seems to cause internal google apps to fail. This is documented in the
23167 // following internal bug issue: go/b/142967802
23168 const result = contextInjector.get(NgModuleRef$1, null);
23169 if (result) {
23170 ngModuleRef = result;
23171 }
23172 }
23173 const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
23174 this.insert(componentRef.hostView, index);
23175 return componentRef;
23176 }
23177 insert(viewRef, index) {
23178 const lView = viewRef._lView;
23179 const tView = lView[TVIEW];
23180 if (ngDevMode && viewRef.destroyed) {
23181 throw new Error('Cannot insert a destroyed View in a ViewContainer!');
23182 }
23183 if (viewAttachedToContainer(lView)) {
23184 // If view is already attached, detach it first so we clean up references appropriately.
23185 const prevIdx = this.indexOf(viewRef);
23186 // A view might be attached either to this or a different container. The `prevIdx` for
23187 // those cases will be:
23188 // equal to -1 for views attached to this ViewContainerRef
23189 // >= 0 for views attached to a different ViewContainerRef
23190 if (prevIdx !== -1) {
23191 this.detach(prevIdx);
23192 }
23193 else {
23194 const prevLContainer = lView[PARENT];
23195 ngDevMode &&
23196 assertEqual(isLContainer(prevLContainer), true, 'An attached view should have its PARENT point to a container.');
23197 // We need to re-create a R3ViewContainerRef instance since those are not stored on
23198 // LView (nor anywhere else).
23199 const prevVCRef = new R3ViewContainerRef(prevLContainer, prevLContainer[T_HOST], prevLContainer[PARENT]);
23200 prevVCRef.detach(prevVCRef.indexOf(viewRef));
23201 }
23202 }
23203 // Logical operation of adding `LView` to `LContainer`
23204 const adjustedIdx = this._adjustIndex(index);
23205 const lContainer = this._lContainer;
23206 insertView(tView, lView, lContainer, adjustedIdx);
23207 // Physical operation of adding the DOM nodes.
23208 const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);
23209 const renderer = lView[RENDERER];
23210 const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);
23211 if (parentRNode !== null) {
23212 addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
23213 }
23214 viewRef.attachToViewContainerRef();
23215 addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);
23216 return viewRef;
23217 }
23218 move(viewRef, newIndex) {
23219 if (ngDevMode && viewRef.destroyed) {
23220 throw new Error('Cannot move a destroyed View in a ViewContainer!');
23221 }
23222 return this.insert(viewRef, newIndex);
23223 }
23224 indexOf(viewRef) {
23225 const viewRefsArr = getViewRefs(this._lContainer);
23226 return viewRefsArr !== null ? viewRefsArr.indexOf(viewRef) : -1;
23227 }
23228 remove(index) {
23229 const adjustedIdx = this._adjustIndex(index, -1);
23230 const detachedView = detachView(this._lContainer, adjustedIdx);
23231 if (detachedView) {
23232 // Before destroying the view, remove it from the container's array of `ViewRef`s.
23233 // This ensures the view container length is updated before calling
23234 // `destroyLView`, which could recursively call view container methods that
23235 // rely on an accurate container length.
23236 // (e.g. a method on this view container being called by a child directive's OnDestroy
23237 // lifecycle hook)
23238 removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx);
23239 destroyLView(detachedView[TVIEW], detachedView);
23240 }
23241 }
23242 detach(index) {
23243 const adjustedIdx = this._adjustIndex(index, -1);
23244 const view = detachView(this._lContainer, adjustedIdx);
23245 const wasDetached = view && removeFromArray(getOrCreateViewRefs(this._lContainer), adjustedIdx) != null;
23246 return wasDetached ? new ViewRef$1(view) : null;
23247 }
23248 _adjustIndex(index, shift = 0) {
23249 if (index == null) {
23250 return this.length + shift;
23251 }
23252 if (ngDevMode) {
23253 assertGreaterThan(index, -1, `ViewRef index must be positive, got ${index}`);
23254 // +1 because it's legal to insert at the end.
23255 assertLessThan(index, this.length + 1 + shift, 'index');
23256 }
23257 return index;
23258 }
23259};
23260function getViewRefs(lContainer) {
23261 return lContainer[VIEW_REFS];
23262}
23263function getOrCreateViewRefs(lContainer) {
23264 return (lContainer[VIEW_REFS] || (lContainer[VIEW_REFS] = []));
23265}
23266/**
23267 * Creates a ViewContainerRef and stores it on the injector.
23268 *
23269 * @param ViewContainerRefToken The ViewContainerRef type
23270 * @param ElementRefToken The ElementRef type
23271 * @param hostTNode The node that is requesting a ViewContainerRef
23272 * @param hostLView The view to which the node belongs
23273 * @returns The ViewContainerRef instance to use
23274 */
23275function createContainerRef(hostTNode, hostLView) {
23276 ngDevMode && assertTNodeType(hostTNode, 12 /* AnyContainer */ | 3 /* AnyRNode */);
23277 let lContainer;
23278 const slotValue = hostLView[hostTNode.index];
23279 if (isLContainer(slotValue)) {
23280 // If the host is a container, we don't need to create a new LContainer
23281 lContainer = slotValue;
23282 }
23283 else {
23284 let commentNode;
23285 // If the host is an element container, the native host element is guaranteed to be a
23286 // comment and we can reuse that comment as anchor element for the new LContainer.
23287 // The comment node in question is already part of the DOM structure so we don't need to append
23288 // it again.
23289 if (hostTNode.type & 8 /* ElementContainer */) {
23290 commentNode = unwrapRNode(slotValue);
23291 }
23292 else {
23293 // If the host is a regular element, we have to insert a comment node manually which will
23294 // be used as an anchor when inserting elements. In this specific case we use low-level DOM
23295 // manipulation to insert it.
23296 const renderer = hostLView[RENDERER];
23297 ngDevMode && ngDevMode.rendererCreateComment++;
23298 commentNode = renderer.createComment(ngDevMode ? 'container' : '');
23299 const hostNative = getNativeByTNode(hostTNode, hostLView);
23300 const parentOfHostNative = nativeParentNode(renderer, hostNative);
23301 nativeInsertBefore(renderer, parentOfHostNative, commentNode, nativeNextSibling(renderer, hostNative), false);
23302 }
23303 hostLView[hostTNode.index] = lContainer =
23304 createLContainer(slotValue, hostLView, commentNode, hostTNode);
23305 addToViewTree(hostLView, lContainer);
23306 }
23307 return new R3ViewContainerRef(lContainer, hostTNode, hostLView);
23308}
23309
23310/**
23311 * @license
23312 * Copyright Google LLC All Rights Reserved.
23313 *
23314 * Use of this source code is governed by an MIT-style license that can be
23315 * found in the LICENSE file at https://angular.io/license
23316 */
23317// Note: This hack is necessary so we don't erroneously get a circular dependency
23318// failure based on types.
23319const unusedValueExportToPlacateAjd$1 = 1;
23320
23321/**
23322 * @license
23323 * Copyright Google LLC All Rights Reserved.
23324 *
23325 * Use of this source code is governed by an MIT-style license that can be
23326 * found in the LICENSE file at https://angular.io/license
23327 */
23328// Note: This hack is necessary so we don't erroneously get a circular dependency
23329// failure based on types.
23330const unusedValueExportToPlacateAjd = 1;
23331
23332/**
23333 * @license
23334 * Copyright Google LLC All Rights Reserved.
23335 *
23336 * Use of this source code is governed by an MIT-style license that can be
23337 * found in the LICENSE file at https://angular.io/license
23338 */
23339const unusedValueToPlacateAjd = unusedValueExportToPlacateAjd$1 + unusedValueExportToPlacateAjd$5 + unusedValueExportToPlacateAjd$4 + unusedValueExportToPlacateAjd;
23340class LQuery_ {
23341 constructor(queryList) {
23342 this.queryList = queryList;
23343 this.matches = null;
23344 }
23345 clone() {
23346 return new LQuery_(this.queryList);
23347 }
23348 setDirty() {
23349 this.queryList.setDirty();
23350 }
23351}
23352class LQueries_ {
23353 constructor(queries = []) {
23354 this.queries = queries;
23355 }
23356 createEmbeddedView(tView) {
23357 const tQueries = tView.queries;
23358 if (tQueries !== null) {
23359 const noOfInheritedQueries = tView.contentQueries !== null ? tView.contentQueries[0] : tQueries.length;
23360 const viewLQueries = [];
23361 // An embedded view has queries propagated from a declaration view at the beginning of the
23362 // TQueries collection and up until a first content query declared in the embedded view. Only
23363 // propagated LQueries are created at this point (LQuery corresponding to declared content
23364 // queries will be instantiated from the content query instructions for each directive).
23365 for (let i = 0; i < noOfInheritedQueries; i++) {
23366 const tQuery = tQueries.getByIndex(i);
23367 const parentLQuery = this.queries[tQuery.indexInDeclarationView];
23368 viewLQueries.push(parentLQuery.clone());
23369 }
23370 return new LQueries_(viewLQueries);
23371 }
23372 return null;
23373 }
23374 insertView(tView) {
23375 this.dirtyQueriesWithMatches(tView);
23376 }
23377 detachView(tView) {
23378 this.dirtyQueriesWithMatches(tView);
23379 }
23380 dirtyQueriesWithMatches(tView) {
23381 for (let i = 0; i < this.queries.length; i++) {
23382 if (getTQuery(tView, i).matches !== null) {
23383 this.queries[i].setDirty();
23384 }
23385 }
23386 }
23387}
23388class TQueryMetadata_ {
23389 constructor(predicate, flags, read = null) {
23390 this.predicate = predicate;
23391 this.flags = flags;
23392 this.read = read;
23393 }
23394}
23395class TQueries_ {
23396 constructor(queries = []) {
23397 this.queries = queries;
23398 }
23399 elementStart(tView, tNode) {
23400 ngDevMode &&
23401 assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');
23402 for (let i = 0; i < this.queries.length; i++) {
23403 this.queries[i].elementStart(tView, tNode);
23404 }
23405 }
23406 elementEnd(tNode) {
23407 for (let i = 0; i < this.queries.length; i++) {
23408 this.queries[i].elementEnd(tNode);
23409 }
23410 }
23411 embeddedTView(tNode) {
23412 let queriesForTemplateRef = null;
23413 for (let i = 0; i < this.length; i++) {
23414 const childQueryIndex = queriesForTemplateRef !== null ? queriesForTemplateRef.length : 0;
23415 const tqueryClone = this.getByIndex(i).embeddedTView(tNode, childQueryIndex);
23416 if (tqueryClone) {
23417 tqueryClone.indexInDeclarationView = i;
23418 if (queriesForTemplateRef !== null) {
23419 queriesForTemplateRef.push(tqueryClone);
23420 }
23421 else {
23422 queriesForTemplateRef = [tqueryClone];
23423 }
23424 }
23425 }
23426 return queriesForTemplateRef !== null ? new TQueries_(queriesForTemplateRef) : null;
23427 }
23428 template(tView, tNode) {
23429 ngDevMode &&
23430 assertFirstCreatePass(tView, 'Queries should collect results on the first template pass only');
23431 for (let i = 0; i < this.queries.length; i++) {
23432 this.queries[i].template(tView, tNode);
23433 }
23434 }
23435 getByIndex(index) {
23436 ngDevMode && assertIndexInRange(this.queries, index);
23437 return this.queries[index];
23438 }
23439 get length() {
23440 return this.queries.length;
23441 }
23442 track(tquery) {
23443 this.queries.push(tquery);
23444 }
23445}
23446class TQuery_ {
23447 constructor(metadata, nodeIndex = -1) {
23448 this.metadata = metadata;
23449 this.matches = null;
23450 this.indexInDeclarationView = -1;
23451 this.crossesNgTemplate = false;
23452 /**
23453 * A flag indicating if a given query still applies to nodes it is crossing. We use this flag
23454 * (alongside with _declarationNodeIndex) to know when to stop applying content queries to
23455 * elements in a template.
23456 */
23457 this._appliesToNextNode = true;
23458 this._declarationNodeIndex = nodeIndex;
23459 }
23460 elementStart(tView, tNode) {
23461 if (this.isApplyingToNode(tNode)) {
23462 this.matchTNode(tView, tNode);
23463 }
23464 }
23465 elementEnd(tNode) {
23466 if (this._declarationNodeIndex === tNode.index) {
23467 this._appliesToNextNode = false;
23468 }
23469 }
23470 template(tView, tNode) {
23471 this.elementStart(tView, tNode);
23472 }
23473 embeddedTView(tNode, childQueryIndex) {
23474 if (this.isApplyingToNode(tNode)) {
23475 this.crossesNgTemplate = true;
23476 // A marker indicating a `<ng-template>` element (a placeholder for query results from
23477 // embedded views created based on this `<ng-template>`).
23478 this.addMatch(-tNode.index, childQueryIndex);
23479 return new TQuery_(this.metadata);
23480 }
23481 return null;
23482 }
23483 isApplyingToNode(tNode) {
23484 if (this._appliesToNextNode &&
23485 (this.metadata.flags & 1 /* descendants */) !== 1 /* descendants */) {
23486 const declarationNodeIdx = this._declarationNodeIndex;
23487 let parent = tNode.parent;
23488 // Determine if a given TNode is a "direct" child of a node on which a content query was
23489 // declared (only direct children of query's host node can match with the descendants: false
23490 // option). There are 3 main use-case / conditions to consider here:
23491 // - <needs-target><i #target></i></needs-target>: here <i #target> parent node is a query
23492 // host node;
23493 // - <needs-target><ng-template [ngIf]="true"><i #target></i></ng-template></needs-target>:
23494 // here <i #target> parent node is null;
23495 // - <needs-target><ng-container><i #target></i></ng-container></needs-target>: here we need
23496 // to go past `<ng-container>` to determine <i #target> parent node (but we shouldn't traverse
23497 // up past the query's host node!).
23498 while (parent !== null && (parent.type & 8 /* ElementContainer */) &&
23499 parent.index !== declarationNodeIdx) {
23500 parent = parent.parent;
23501 }
23502 return declarationNodeIdx === (parent !== null ? parent.index : -1);
23503 }
23504 return this._appliesToNextNode;
23505 }
23506 matchTNode(tView, tNode) {
23507 const predicate = this.metadata.predicate;
23508 if (Array.isArray(predicate)) {
23509 for (let i = 0; i < predicate.length; i++) {
23510 const name = predicate[i];
23511 this.matchTNodeWithReadOption(tView, tNode, getIdxOfMatchingSelector(tNode, name));
23512 // Also try matching the name to a provider since strings can be used as DI tokens too.
23513 this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, name, false, false));
23514 }
23515 }
23516 else {
23517 if (predicate === TemplateRef) {
23518 if (tNode.type & 4 /* Container */) {
23519 this.matchTNodeWithReadOption(tView, tNode, -1);
23520 }
23521 }
23522 else {
23523 this.matchTNodeWithReadOption(tView, tNode, locateDirectiveOrProvider(tNode, tView, predicate, false, false));
23524 }
23525 }
23526 }
23527 matchTNodeWithReadOption(tView, tNode, nodeMatchIdx) {
23528 if (nodeMatchIdx !== null) {
23529 const read = this.metadata.read;
23530 if (read !== null) {
23531 if (read === ElementRef || read === ViewContainerRef ||
23532 read === TemplateRef && (tNode.type & 4 /* Container */)) {
23533 this.addMatch(tNode.index, -2);
23534 }
23535 else {
23536 const directiveOrProviderIdx = locateDirectiveOrProvider(tNode, tView, read, false, false);
23537 if (directiveOrProviderIdx !== null) {
23538 this.addMatch(tNode.index, directiveOrProviderIdx);
23539 }
23540 }
23541 }
23542 else {
23543 this.addMatch(tNode.index, nodeMatchIdx);
23544 }
23545 }
23546 }
23547 addMatch(tNodeIdx, matchIdx) {
23548 if (this.matches === null) {
23549 this.matches = [tNodeIdx, matchIdx];
23550 }
23551 else {
23552 this.matches.push(tNodeIdx, matchIdx);
23553 }
23554 }
23555}
23556/**
23557 * Iterates over local names for a given node and returns directive index
23558 * (or -1 if a local name points to an element).
23559 *
23560 * @param tNode static data of a node to check
23561 * @param selector selector to match
23562 * @returns directive index, -1 or null if a selector didn't match any of the local names
23563 */
23564function getIdxOfMatchingSelector(tNode, selector) {
23565 const localNames = tNode.localNames;
23566 if (localNames !== null) {
23567 for (let i = 0; i < localNames.length; i += 2) {
23568 if (localNames[i] === selector) {
23569 return localNames[i + 1];
23570 }
23571 }
23572 }
23573 return null;
23574}
23575function createResultByTNodeType(tNode, currentView) {
23576 if (tNode.type & (3 /* AnyRNode */ | 8 /* ElementContainer */)) {
23577 return createElementRef(tNode, currentView);
23578 }
23579 else if (tNode.type & 4 /* Container */) {
23580 return createTemplateRef(tNode, currentView);
23581 }
23582 return null;
23583}
23584function createResultForNode(lView, tNode, matchingIdx, read) {
23585 if (matchingIdx === -1) {
23586 // if read token and / or strategy is not specified, detect it using appropriate tNode type
23587 return createResultByTNodeType(tNode, lView);
23588 }
23589 else if (matchingIdx === -2) {
23590 // read a special token from a node injector
23591 return createSpecialToken(lView, tNode, read);
23592 }
23593 else {
23594 // read a token
23595 return getNodeInjectable(lView, lView[TVIEW], matchingIdx, tNode);
23596 }
23597}
23598function createSpecialToken(lView, tNode, read) {
23599 if (read === ElementRef) {
23600 return createElementRef(tNode, lView);
23601 }
23602 else if (read === TemplateRef) {
23603 return createTemplateRef(tNode, lView);
23604 }
23605 else if (read === ViewContainerRef) {
23606 ngDevMode && assertTNodeType(tNode, 3 /* AnyRNode */ | 12 /* AnyContainer */);
23607 return createContainerRef(tNode, lView);
23608 }
23609 else {
23610 ngDevMode &&
23611 throwError(`Special token to read should be one of ElementRef, TemplateRef or ViewContainerRef but got ${stringify(read)}.`);
23612 }
23613}
23614/**
23615 * A helper function that creates query results for a given view. This function is meant to do the
23616 * processing once and only once for a given view instance (a set of results for a given view
23617 * doesn't change).
23618 */
23619function materializeViewResults(tView, lView, tQuery, queryIndex) {
23620 const lQuery = lView[QUERIES].queries[queryIndex];
23621 if (lQuery.matches === null) {
23622 const tViewData = tView.data;
23623 const tQueryMatches = tQuery.matches;
23624 const result = [];
23625 for (let i = 0; i < tQueryMatches.length; i += 2) {
23626 const matchedNodeIdx = tQueryMatches[i];
23627 if (matchedNodeIdx < 0) {
23628 // we at the <ng-template> marker which might have results in views created based on this
23629 // <ng-template> - those results will be in separate views though, so here we just leave
23630 // null as a placeholder
23631 result.push(null);
23632 }
23633 else {
23634 ngDevMode && assertIndexInRange(tViewData, matchedNodeIdx);
23635 const tNode = tViewData[matchedNodeIdx];
23636 result.push(createResultForNode(lView, tNode, tQueryMatches[i + 1], tQuery.metadata.read));
23637 }
23638 }
23639 lQuery.matches = result;
23640 }
23641 return lQuery.matches;
23642}
23643/**
23644 * A helper function that collects (already materialized) query results from a tree of views,
23645 * starting with a provided LView.
23646 */
23647function collectQueryResults(tView, lView, queryIndex, result) {
23648 const tQuery = tView.queries.getByIndex(queryIndex);
23649 const tQueryMatches = tQuery.matches;
23650 if (tQueryMatches !== null) {
23651 const lViewResults = materializeViewResults(tView, lView, tQuery, queryIndex);
23652 for (let i = 0; i < tQueryMatches.length; i += 2) {
23653 const tNodeIdx = tQueryMatches[i];
23654 if (tNodeIdx > 0) {
23655 result.push(lViewResults[i / 2]);
23656 }
23657 else {
23658 const childQueryIndex = tQueryMatches[i + 1];
23659 const declarationLContainer = lView[-tNodeIdx];
23660 ngDevMode && assertLContainer(declarationLContainer);
23661 // collect matches for views inserted in this container
23662 for (let i = CONTAINER_HEADER_OFFSET; i < declarationLContainer.length; i++) {
23663 const embeddedLView = declarationLContainer[i];
23664 if (embeddedLView[DECLARATION_LCONTAINER] === embeddedLView[PARENT]) {
23665 collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
23666 }
23667 }
23668 // collect matches for views created from this declaration container and inserted into
23669 // different containers
23670 if (declarationLContainer[MOVED_VIEWS] !== null) {
23671 const embeddedLViews = declarationLContainer[MOVED_VIEWS];
23672 for (let i = 0; i < embeddedLViews.length; i++) {
23673 const embeddedLView = embeddedLViews[i];
23674 collectQueryResults(embeddedLView[TVIEW], embeddedLView, childQueryIndex, result);
23675 }
23676 }
23677 }
23678 }
23679 }
23680 return result;
23681}
23682/**
23683 * Refreshes a query by combining matches from all active views and removing matches from deleted
23684 * views.
23685 *
23686 * @returns `true` if a query got dirty during change detection or if this is a static query
23687 * resolving in creation mode, `false` otherwise.
23688 *
23689 * @codeGenApi
23690 */
23691function ɵɵqueryRefresh(queryList) {
23692 const lView = getLView();
23693 const tView = getTView();
23694 const queryIndex = getCurrentQueryIndex();
23695 setCurrentQueryIndex(queryIndex + 1);
23696 const tQuery = getTQuery(tView, queryIndex);
23697 if (queryList.dirty &&
23698 (isCreationMode(lView) ===
23699 ((tQuery.metadata.flags & 2 /* isStatic */) === 2 /* isStatic */))) {
23700 if (tQuery.matches === null) {
23701 queryList.reset([]);
23702 }
23703 else {
23704 const result = tQuery.crossesNgTemplate ?
23705 collectQueryResults(tView, lView, queryIndex, []) :
23706 materializeViewResults(tView, lView, tQuery, queryIndex);
23707 queryList.reset(result, unwrapElementRef);
23708 queryList.notifyOnChanges();
23709 }
23710 return true;
23711 }
23712 return false;
23713}
23714/**
23715 * Creates new QueryList, stores the reference in LView and returns QueryList.
23716 *
23717 * @param predicate The type for which the query will search
23718 * @param flags Flags associated with the query
23719 * @param read What to save in the query
23720 *
23721 * @codeGenApi
23722 */
23723function ɵɵviewQuery(predicate, flags, read) {
23724 ngDevMode && assertNumber(flags, 'Expecting flags');
23725 const tView = getTView();
23726 if (tView.firstCreatePass) {
23727 createTQuery(tView, new TQueryMetadata_(predicate, flags, read), -1);
23728 if ((flags & 2 /* isStatic */) === 2 /* isStatic */) {
23729 tView.staticViewQueries = true;
23730 }
23731 }
23732 createLQuery(tView, getLView(), flags);
23733}
23734/**
23735 * Registers a QueryList, associated with a content query, for later refresh (part of a view
23736 * refresh).
23737 *
23738 * @param directiveIndex Current directive index
23739 * @param predicate The type for which the query will search
23740 * @param flags Flags associated with the query
23741 * @param read What to save in the query
23742 * @returns QueryList<T>
23743 *
23744 * @codeGenApi
23745 */
23746function ɵɵcontentQuery(directiveIndex, predicate, flags, read) {
23747 ngDevMode && assertNumber(flags, 'Expecting flags');
23748 const tView = getTView();
23749 if (tView.firstCreatePass) {
23750 const tNode = getCurrentTNode();
23751 createTQuery(tView, new TQueryMetadata_(predicate, flags, read), tNode.index);
23752 saveContentQueryAndDirectiveIndex(tView, directiveIndex);
23753 if ((flags & 2 /* isStatic */) === 2 /* isStatic */) {
23754 tView.staticContentQueries = true;
23755 }
23756 }
23757 createLQuery(tView, getLView(), flags);
23758}
23759/**
23760 * Loads a QueryList corresponding to the current view or content query.
23761 *
23762 * @codeGenApi
23763 */
23764function ɵɵloadQuery() {
23765 return loadQueryInternal(getLView(), getCurrentQueryIndex());
23766}
23767function loadQueryInternal(lView, queryIndex) {
23768 ngDevMode &&
23769 assertDefined(lView[QUERIES], 'LQueries should be defined when trying to load a query');
23770 ngDevMode && assertIndexInRange(lView[QUERIES].queries, queryIndex);
23771 return lView[QUERIES].queries[queryIndex].queryList;
23772}
23773function createLQuery(tView, lView, flags) {
23774 const queryList = new QueryList((flags & 4 /* emitDistinctChangesOnly */) === 4 /* emitDistinctChangesOnly */);
23775 storeCleanupWithContext(tView, lView, queryList, queryList.destroy);
23776 if (lView[QUERIES] === null)
23777 lView[QUERIES] = new LQueries_();
23778 lView[QUERIES].queries.push(new LQuery_(queryList));
23779}
23780function createTQuery(tView, metadata, nodeIndex) {
23781 if (tView.queries === null)
23782 tView.queries = new TQueries_();
23783 tView.queries.track(new TQuery_(metadata, nodeIndex));
23784}
23785function saveContentQueryAndDirectiveIndex(tView, directiveIndex) {
23786 const tViewContentQueries = tView.contentQueries || (tView.contentQueries = []);
23787 const lastSavedDirectiveIndex = tViewContentQueries.length ? tViewContentQueries[tViewContentQueries.length - 1] : -1;
23788 if (directiveIndex !== lastSavedDirectiveIndex) {
23789 tViewContentQueries.push(tView.queries.length - 1, directiveIndex);
23790 }
23791}
23792function getTQuery(tView, index) {
23793 ngDevMode && assertDefined(tView.queries, 'TQueries must be defined to retrieve a TQuery');
23794 return tView.queries.getByIndex(index);
23795}
23796
23797/**
23798 * @license
23799 * Copyright Google LLC All Rights Reserved.
23800 *
23801 * Use of this source code is governed by an MIT-style license that can be
23802 * found in the LICENSE file at https://angular.io/license
23803 */
23804/**
23805 * Retrieves `TemplateRef` instance from `Injector` when a local reference is placed on the
23806 * `<ng-template>` element.
23807 *
23808 * @codeGenApi
23809 */
23810function ɵɵtemplateRefExtractor(tNode, lView) {
23811 return createTemplateRef(tNode, lView);
23812}
23813
23814/**
23815 * @license
23816 * Copyright Google LLC All Rights Reserved.
23817 *
23818 * Use of this source code is governed by an MIT-style license that can be
23819 * found in the LICENSE file at https://angular.io/license
23820 */
23821
23822/**
23823 * @license
23824 * Copyright Google LLC All Rights Reserved.
23825 *
23826 * Use of this source code is governed by an MIT-style license that can be
23827 * found in the LICENSE file at https://angular.io/license
23828 */
23829/**
23830 * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
23831 *
23832 * This should be kept up to date with the public exports of @angular/core.
23833 */
23834const angularCoreEnv = (() => ({
23835 'ɵɵattribute': ɵɵattribute,
23836 'ɵɵattributeInterpolate1': ɵɵattributeInterpolate1,
23837 'ɵɵattributeInterpolate2': ɵɵattributeInterpolate2,
23838 'ɵɵattributeInterpolate3': ɵɵattributeInterpolate3,
23839 'ɵɵattributeInterpolate4': ɵɵattributeInterpolate4,
23840 'ɵɵattributeInterpolate5': ɵɵattributeInterpolate5,
23841 'ɵɵattributeInterpolate6': ɵɵattributeInterpolate6,
23842 'ɵɵattributeInterpolate7': ɵɵattributeInterpolate7,
23843 'ɵɵattributeInterpolate8': ɵɵattributeInterpolate8,
23844 'ɵɵattributeInterpolateV': ɵɵattributeInterpolateV,
23845 'ɵɵdefineComponent': ɵɵdefineComponent,
23846 'ɵɵdefineDirective': ɵɵdefineDirective,
23847 'ɵɵdefineInjectable': ɵɵdefineInjectable,
23848 'ɵɵdefineInjector': ɵɵdefineInjector,
23849 'ɵɵdefineNgModule': ɵɵdefineNgModule,
23850 'ɵɵdefinePipe': ɵɵdefinePipe,
23851 'ɵɵdirectiveInject': ɵɵdirectiveInject,
23852 'ɵɵgetInheritedFactory': ɵɵgetInheritedFactory,
23853 'ɵɵinject': ɵɵinject,
23854 'ɵɵinjectAttribute': ɵɵinjectAttribute,
23855 'ɵɵinvalidFactory': ɵɵinvalidFactory,
23856 'ɵɵinvalidFactoryDep': ɵɵinvalidFactoryDep,
23857 'ɵɵtemplateRefExtractor': ɵɵtemplateRefExtractor,
23858 'ɵɵNgOnChangesFeature': ɵɵNgOnChangesFeature,
23859 'ɵɵProvidersFeature': ɵɵProvidersFeature,
23860 'ɵɵCopyDefinitionFeature': ɵɵCopyDefinitionFeature,
23861 'ɵɵInheritDefinitionFeature': ɵɵInheritDefinitionFeature,
23862 'ɵɵnextContext': ɵɵnextContext,
23863 'ɵɵnamespaceHTML': ɵɵnamespaceHTML,
23864 'ɵɵnamespaceMathML': ɵɵnamespaceMathML,
23865 'ɵɵnamespaceSVG': ɵɵnamespaceSVG,
23866 'ɵɵenableBindings': ɵɵenableBindings,
23867 'ɵɵdisableBindings': ɵɵdisableBindings,
23868 'ɵɵelementStart': ɵɵelementStart,
23869 'ɵɵelementEnd': ɵɵelementEnd,
23870 'ɵɵelement': ɵɵelement,
23871 'ɵɵelementContainerStart': ɵɵelementContainerStart,
23872 'ɵɵelementContainerEnd': ɵɵelementContainerEnd,
23873 'ɵɵelementContainer': ɵɵelementContainer,
23874 'ɵɵpureFunction0': ɵɵpureFunction0,
23875 'ɵɵpureFunction1': ɵɵpureFunction1,
23876 'ɵɵpureFunction2': ɵɵpureFunction2,
23877 'ɵɵpureFunction3': ɵɵpureFunction3,
23878 'ɵɵpureFunction4': ɵɵpureFunction4,
23879 'ɵɵpureFunction5': ɵɵpureFunction5,
23880 'ɵɵpureFunction6': ɵɵpureFunction6,
23881 'ɵɵpureFunction7': ɵɵpureFunction7,
23882 'ɵɵpureFunction8': ɵɵpureFunction8,
23883 'ɵɵpureFunctionV': ɵɵpureFunctionV,
23884 'ɵɵgetCurrentView': ɵɵgetCurrentView,
23885 'ɵɵrestoreView': ɵɵrestoreView,
23886 'ɵɵlistener': ɵɵlistener,
23887 'ɵɵprojection': ɵɵprojection,
23888 'ɵɵsyntheticHostProperty': ɵɵsyntheticHostProperty,
23889 'ɵɵsyntheticHostListener': ɵɵsyntheticHostListener,
23890 'ɵɵpipeBind1': ɵɵpipeBind1,
23891 'ɵɵpipeBind2': ɵɵpipeBind2,
23892 'ɵɵpipeBind3': ɵɵpipeBind3,
23893 'ɵɵpipeBind4': ɵɵpipeBind4,
23894 'ɵɵpipeBindV': ɵɵpipeBindV,
23895 'ɵɵprojectionDef': ɵɵprojectionDef,
23896 'ɵɵhostProperty': ɵɵhostProperty,
23897 'ɵɵproperty': ɵɵproperty,
23898 'ɵɵpropertyInterpolate': ɵɵpropertyInterpolate,
23899 'ɵɵpropertyInterpolate1': ɵɵpropertyInterpolate1,
23900 'ɵɵpropertyInterpolate2': ɵɵpropertyInterpolate2,
23901 'ɵɵpropertyInterpolate3': ɵɵpropertyInterpolate3,
23902 'ɵɵpropertyInterpolate4': ɵɵpropertyInterpolate4,
23903 'ɵɵpropertyInterpolate5': ɵɵpropertyInterpolate5,
23904 'ɵɵpropertyInterpolate6': ɵɵpropertyInterpolate6,
23905 'ɵɵpropertyInterpolate7': ɵɵpropertyInterpolate7,
23906 'ɵɵpropertyInterpolate8': ɵɵpropertyInterpolate8,
23907 'ɵɵpropertyInterpolateV': ɵɵpropertyInterpolateV,
23908 'ɵɵpipe': ɵɵpipe,
23909 'ɵɵqueryRefresh': ɵɵqueryRefresh,
23910 'ɵɵviewQuery': ɵɵviewQuery,
23911 'ɵɵloadQuery': ɵɵloadQuery,
23912 'ɵɵcontentQuery': ɵɵcontentQuery,
23913 'ɵɵreference': ɵɵreference,
23914 'ɵɵclassMap': ɵɵclassMap,
23915 'ɵɵclassMapInterpolate1': ɵɵclassMapInterpolate1,
23916 'ɵɵclassMapInterpolate2': ɵɵclassMapInterpolate2,
23917 'ɵɵclassMapInterpolate3': ɵɵclassMapInterpolate3,
23918 'ɵɵclassMapInterpolate4': ɵɵclassMapInterpolate4,
23919 'ɵɵclassMapInterpolate5': ɵɵclassMapInterpolate5,
23920 'ɵɵclassMapInterpolate6': ɵɵclassMapInterpolate6,
23921 'ɵɵclassMapInterpolate7': ɵɵclassMapInterpolate7,
23922 'ɵɵclassMapInterpolate8': ɵɵclassMapInterpolate8,
23923 'ɵɵclassMapInterpolateV': ɵɵclassMapInterpolateV,
23924 'ɵɵstyleMap': ɵɵstyleMap,
23925 'ɵɵstyleMapInterpolate1': ɵɵstyleMapInterpolate1,
23926 'ɵɵstyleMapInterpolate2': ɵɵstyleMapInterpolate2,
23927 'ɵɵstyleMapInterpolate3': ɵɵstyleMapInterpolate3,
23928 'ɵɵstyleMapInterpolate4': ɵɵstyleMapInterpolate4,
23929 'ɵɵstyleMapInterpolate5': ɵɵstyleMapInterpolate5,
23930 'ɵɵstyleMapInterpolate6': ɵɵstyleMapInterpolate6,
23931 'ɵɵstyleMapInterpolate7': ɵɵstyleMapInterpolate7,
23932 'ɵɵstyleMapInterpolate8': ɵɵstyleMapInterpolate8,
23933 'ɵɵstyleMapInterpolateV': ɵɵstyleMapInterpolateV,
23934 'ɵɵstyleProp': ɵɵstyleProp,
23935 'ɵɵstylePropInterpolate1': ɵɵstylePropInterpolate1,
23936 'ɵɵstylePropInterpolate2': ɵɵstylePropInterpolate2,
23937 'ɵɵstylePropInterpolate3': ɵɵstylePropInterpolate3,
23938 'ɵɵstylePropInterpolate4': ɵɵstylePropInterpolate4,
23939 'ɵɵstylePropInterpolate5': ɵɵstylePropInterpolate5,
23940 'ɵɵstylePropInterpolate6': ɵɵstylePropInterpolate6,
23941 'ɵɵstylePropInterpolate7': ɵɵstylePropInterpolate7,
23942 'ɵɵstylePropInterpolate8': ɵɵstylePropInterpolate8,
23943 'ɵɵstylePropInterpolateV': ɵɵstylePropInterpolateV,
23944 'ɵɵclassProp': ɵɵclassProp,
23945 'ɵɵadvance': ɵɵadvance,
23946 'ɵɵtemplate': ɵɵtemplate,
23947 'ɵɵtext': ɵɵtext,
23948 'ɵɵtextInterpolate': ɵɵtextInterpolate,
23949 'ɵɵtextInterpolate1': ɵɵtextInterpolate1,
23950 'ɵɵtextInterpolate2': ɵɵtextInterpolate2,
23951 'ɵɵtextInterpolate3': ɵɵtextInterpolate3,
23952 'ɵɵtextInterpolate4': ɵɵtextInterpolate4,
23953 'ɵɵtextInterpolate5': ɵɵtextInterpolate5,
23954 'ɵɵtextInterpolate6': ɵɵtextInterpolate6,
23955 'ɵɵtextInterpolate7': ɵɵtextInterpolate7,
23956 'ɵɵtextInterpolate8': ɵɵtextInterpolate8,
23957 'ɵɵtextInterpolateV': ɵɵtextInterpolateV,
23958 'ɵɵi18n': ɵɵi18n,
23959 'ɵɵi18nAttributes': ɵɵi18nAttributes,
23960 'ɵɵi18nExp': ɵɵi18nExp,
23961 'ɵɵi18nStart': ɵɵi18nStart,
23962 'ɵɵi18nEnd': ɵɵi18nEnd,
23963 'ɵɵi18nApply': ɵɵi18nApply,
23964 'ɵɵi18nPostprocess': ɵɵi18nPostprocess,
23965 'ɵɵresolveWindow': ɵɵresolveWindow,
23966 'ɵɵresolveDocument': ɵɵresolveDocument,
23967 'ɵɵresolveBody': ɵɵresolveBody,
23968 'ɵɵsetComponentScope': ɵɵsetComponentScope,
23969 'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope,
23970 'ɵɵsanitizeHtml': ɵɵsanitizeHtml,
23971 'ɵɵsanitizeStyle': ɵɵsanitizeStyle,
23972 'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl,
23973 'ɵɵsanitizeScript': ɵɵsanitizeScript,
23974 'ɵɵsanitizeUrl': ɵɵsanitizeUrl,
23975 'ɵɵsanitizeUrlOrResourceUrl': ɵɵsanitizeUrlOrResourceUrl,
23976 'ɵɵtrustConstantHtml': ɵɵtrustConstantHtml,
23977 'ɵɵtrustConstantResourceUrl': ɵɵtrustConstantResourceUrl,
23978 'forwardRef': forwardRef,
23979 'resolveForwardRef': resolveForwardRef,
23980}))();
23981
23982let jitOptions = null;
23983function setJitOptions(options) {
23984 if (jitOptions !== null) {
23985 if (options.defaultEncapsulation !== jitOptions.defaultEncapsulation) {
23986 ngDevMode &&
23987 console.error('Provided value for `defaultEncapsulation` can not be changed once it has been set.');
23988 return;
23989 }
23990 if (options.preserveWhitespaces !== jitOptions.preserveWhitespaces) {
23991 ngDevMode &&
23992 console.error('Provided value for `preserveWhitespaces` can not be changed once it has been set.');
23993 return;
23994 }
23995 }
23996 jitOptions = options;
23997}
23998function getJitOptions() {
23999 return jitOptions;
24000}
24001function resetJitOptions() {
24002 jitOptions = null;
24003}
24004
24005/**
24006 * @license
24007 * Copyright Google LLC All Rights Reserved.
24008 *
24009 * Use of this source code is governed by an MIT-style license that can be
24010 * found in the LICENSE file at https://angular.io/license
24011 */
24012const moduleQueue = [];
24013/**
24014 * Enqueues moduleDef to be checked later to see if scope can be set on its
24015 * component declarations.
24016 */
24017function enqueueModuleForDelayedScoping(moduleType, ngModule) {
24018 moduleQueue.push({ moduleType, ngModule });
24019}
24020let flushingModuleQueue = false;
24021/**
24022 * Loops over queued module definitions, if a given module definition has all of its
24023 * declarations resolved, it dequeues that module definition and sets the scope on
24024 * its declarations.
24025 */
24026function flushModuleScopingQueueAsMuchAsPossible() {
24027 if (!flushingModuleQueue) {
24028 flushingModuleQueue = true;
24029 try {
24030 for (let i = moduleQueue.length - 1; i >= 0; i--) {
24031 const { moduleType, ngModule } = moduleQueue[i];
24032 if (ngModule.declarations && ngModule.declarations.every(isResolvedDeclaration)) {
24033 // dequeue
24034 moduleQueue.splice(i, 1);
24035 setScopeOnDeclaredComponents(moduleType, ngModule);
24036 }
24037 }
24038 }
24039 finally {
24040 flushingModuleQueue = false;
24041 }
24042 }
24043}
24044/**
24045 * Returns truthy if a declaration has resolved. If the declaration happens to be
24046 * an array of declarations, it will recurse to check each declaration in that array
24047 * (which may also be arrays).
24048 */
24049function isResolvedDeclaration(declaration) {
24050 if (Array.isArray(declaration)) {
24051 return declaration.every(isResolvedDeclaration);
24052 }
24053 return !!resolveForwardRef(declaration);
24054}
24055/**
24056 * Compiles a module in JIT mode.
24057 *
24058 * This function automatically gets called when a class has a `@NgModule` decorator.
24059 */
24060function compileNgModule(moduleType, ngModule = {}) {
24061 compileNgModuleDefs(moduleType, ngModule);
24062 // Because we don't know if all declarations have resolved yet at the moment the
24063 // NgModule decorator is executing, we're enqueueing the setting of module scope
24064 // on its declarations to be run at a later time when all declarations for the module,
24065 // including forward refs, have resolved.
24066 enqueueModuleForDelayedScoping(moduleType, ngModule);
24067}
24068/**
24069 * Compiles and adds the `ɵmod`, `ɵfac` and `ɵinj` properties to the module class.
24070 *
24071 * It's possible to compile a module via this API which will allow duplicate declarations in its
24072 * root.
24073 */
24074function compileNgModuleDefs(moduleType, ngModule, allowDuplicateDeclarationsInRoot = false) {
24075 ngDevMode && assertDefined(moduleType, 'Required value moduleType');
24076 ngDevMode && assertDefined(ngModule, 'Required value ngModule');
24077 const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
24078 let ngModuleDef = null;
24079 Object.defineProperty(moduleType, NG_MOD_DEF, {
24080 configurable: true,
24081 get: () => {
24082 if (ngModuleDef === null) {
24083 if (ngDevMode && ngModule.imports && ngModule.imports.indexOf(moduleType) > -1) {
24084 // We need to assert this immediately, because allowing it to continue will cause it to
24085 // go into an infinite loop before we've reached the point where we throw all the errors.
24086 throw new Error(`'${stringifyForError(moduleType)}' module can't import itself`);
24087 }
24088 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'NgModule', type: moduleType });
24089 ngModuleDef = compiler.compileNgModule(angularCoreEnv, `ng:///${moduleType.name}/ɵmod.js`, {
24090 type: moduleType,
24091 bootstrap: flatten(ngModule.bootstrap || EMPTY_ARRAY).map(resolveForwardRef),
24092 declarations: declarations.map(resolveForwardRef),
24093 imports: flatten(ngModule.imports || EMPTY_ARRAY)
24094 .map(resolveForwardRef)
24095 .map(expandModuleWithProviders),
24096 exports: flatten(ngModule.exports || EMPTY_ARRAY)
24097 .map(resolveForwardRef)
24098 .map(expandModuleWithProviders),
24099 schemas: ngModule.schemas ? flatten(ngModule.schemas) : null,
24100 id: ngModule.id || null,
24101 });
24102 // Set `schemas` on ngModuleDef to an empty array in JIT mode to indicate that runtime
24103 // should verify that there are no unknown elements in a template. In AOT mode, that check
24104 // happens at compile time and `schemas` information is not present on Component and Module
24105 // defs after compilation (so the check doesn't happen the second time at runtime).
24106 if (!ngModuleDef.schemas) {
24107 ngModuleDef.schemas = [];
24108 }
24109 }
24110 return ngModuleDef;
24111 }
24112 });
24113 let ngFactoryDef = null;
24114 Object.defineProperty(moduleType, NG_FACTORY_DEF, {
24115 get: () => {
24116 if (ngFactoryDef === null) {
24117 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'NgModule', type: moduleType });
24118 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${moduleType.name}/ɵfac.js`, {
24119 name: moduleType.name,
24120 type: moduleType,
24121 deps: reflectDependencies(moduleType),
24122 target: compiler.FactoryTarget.NgModule,
24123 typeArgumentCount: 0,
24124 });
24125 }
24126 return ngFactoryDef;
24127 },
24128 // Make the property configurable in dev mode to allow overriding in tests
24129 configurable: !!ngDevMode,
24130 });
24131 let ngInjectorDef = null;
24132 Object.defineProperty(moduleType, NG_INJ_DEF, {
24133 get: () => {
24134 if (ngInjectorDef === null) {
24135 ngDevMode &&
24136 verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot);
24137 const meta = {
24138 name: moduleType.name,
24139 type: moduleType,
24140 providers: ngModule.providers || EMPTY_ARRAY,
24141 imports: [
24142 (ngModule.imports || EMPTY_ARRAY).map(resolveForwardRef),
24143 (ngModule.exports || EMPTY_ARRAY).map(resolveForwardRef),
24144 ],
24145 };
24146 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'NgModule', type: moduleType });
24147 ngInjectorDef =
24148 compiler.compileInjector(angularCoreEnv, `ng:///${moduleType.name}/ɵinj.js`, meta);
24149 }
24150 return ngInjectorDef;
24151 },
24152 // Make the property configurable in dev mode to allow overriding in tests
24153 configurable: !!ngDevMode,
24154 });
24155}
24156function verifySemanticsOfNgModuleDef(moduleType, allowDuplicateDeclarationsInRoot, importingModule) {
24157 if (verifiedNgModule.get(moduleType))
24158 return;
24159 verifiedNgModule.set(moduleType, true);
24160 moduleType = resolveForwardRef(moduleType);
24161 let ngModuleDef;
24162 if (importingModule) {
24163 ngModuleDef = getNgModuleDef(moduleType);
24164 if (!ngModuleDef) {
24165 throw new Error(`Unexpected value '${moduleType.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
24166 }
24167 }
24168 else {
24169 ngModuleDef = getNgModuleDef(moduleType, true);
24170 }
24171 const errors = [];
24172 const declarations = maybeUnwrapFn(ngModuleDef.declarations);
24173 const imports = maybeUnwrapFn(ngModuleDef.imports);
24174 flatten(imports).map(unwrapModuleWithProvidersImports).forEach(mod => {
24175 verifySemanticsOfNgModuleImport(mod, moduleType);
24176 verifySemanticsOfNgModuleDef(mod, false, moduleType);
24177 });
24178 const exports = maybeUnwrapFn(ngModuleDef.exports);
24179 declarations.forEach(verifyDeclarationsHaveDefinitions);
24180 declarations.forEach(verifyDirectivesHaveSelector);
24181 const combinedDeclarations = [
24182 ...declarations.map(resolveForwardRef),
24183 ...flatten(imports.map(computeCombinedExports)).map(resolveForwardRef),
24184 ];
24185 exports.forEach(verifyExportsAreDeclaredOrReExported);
24186 declarations.forEach(decl => verifyDeclarationIsUnique(decl, allowDuplicateDeclarationsInRoot));
24187 declarations.forEach(verifyComponentEntryComponentsIsPartOfNgModule);
24188 const ngModule = getAnnotation(moduleType, 'NgModule');
24189 if (ngModule) {
24190 ngModule.imports &&
24191 flatten(ngModule.imports).map(unwrapModuleWithProvidersImports).forEach(mod => {
24192 verifySemanticsOfNgModuleImport(mod, moduleType);
24193 verifySemanticsOfNgModuleDef(mod, false, moduleType);
24194 });
24195 ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyCorrectBootstrapType);
24196 ngModule.bootstrap && deepForEach(ngModule.bootstrap, verifyComponentIsPartOfNgModule);
24197 ngModule.entryComponents &&
24198 deepForEach(ngModule.entryComponents, verifyComponentIsPartOfNgModule);
24199 }
24200 // Throw Error if any errors were detected.
24201 if (errors.length) {
24202 throw new Error(errors.join('\n'));
24203 }
24204 ////////////////////////////////////////////////////////////////////////////////////////////////
24205 function verifyDeclarationsHaveDefinitions(type) {
24206 type = resolveForwardRef(type);
24207 const def = getComponentDef(type) || getDirectiveDef(type) || getPipeDef$1(type);
24208 if (!def) {
24209 errors.push(`Unexpected value '${stringifyForError(type)}' declared by the module '${stringifyForError(moduleType)}'. Please add a @Pipe/@Directive/@Component annotation.`);
24210 }
24211 }
24212 function verifyDirectivesHaveSelector(type) {
24213 type = resolveForwardRef(type);
24214 const def = getDirectiveDef(type);
24215 if (!getComponentDef(type) && def && def.selectors.length == 0) {
24216 errors.push(`Directive ${stringifyForError(type)} has no selector, please add it!`);
24217 }
24218 }
24219 function verifyExportsAreDeclaredOrReExported(type) {
24220 type = resolveForwardRef(type);
24221 const kind = getComponentDef(type) && 'component' || getDirectiveDef(type) && 'directive' ||
24222 getPipeDef$1(type) && 'pipe';
24223 if (kind) {
24224 // only checked if we are declared as Component, Directive, or Pipe
24225 // Modules don't need to be declared or imported.
24226 if (combinedDeclarations.lastIndexOf(type) === -1) {
24227 // We are exporting something which we don't explicitly declare or import.
24228 errors.push(`Can't export ${kind} ${stringifyForError(type)} from ${stringifyForError(moduleType)} as it was neither declared nor imported!`);
24229 }
24230 }
24231 }
24232 function verifyDeclarationIsUnique(type, suppressErrors) {
24233 type = resolveForwardRef(type);
24234 const existingModule = ownerNgModule.get(type);
24235 if (existingModule && existingModule !== moduleType) {
24236 if (!suppressErrors) {
24237 const modules = [existingModule, moduleType].map(stringifyForError).sort();
24238 errors.push(`Type ${stringifyForError(type)} is part of the declarations of 2 modules: ${modules[0]} and ${modules[1]}! ` +
24239 `Please consider moving ${stringifyForError(type)} to a higher module that imports ${modules[0]} and ${modules[1]}. ` +
24240 `You can also create a new NgModule that exports and includes ${stringifyForError(type)} then import that NgModule in ${modules[0]} and ${modules[1]}.`);
24241 }
24242 }
24243 else {
24244 // Mark type as having owner.
24245 ownerNgModule.set(type, moduleType);
24246 }
24247 }
24248 function verifyComponentIsPartOfNgModule(type) {
24249 type = resolveForwardRef(type);
24250 const existingModule = ownerNgModule.get(type);
24251 if (!existingModule) {
24252 errors.push(`Component ${stringifyForError(type)} is not part of any NgModule or the module has not been imported into your module.`);
24253 }
24254 }
24255 function verifyCorrectBootstrapType(type) {
24256 type = resolveForwardRef(type);
24257 if (!getComponentDef(type)) {
24258 errors.push(`${stringifyForError(type)} cannot be used as an entry component.`);
24259 }
24260 }
24261 function verifyComponentEntryComponentsIsPartOfNgModule(type) {
24262 type = resolveForwardRef(type);
24263 if (getComponentDef(type)) {
24264 // We know we are component
24265 const component = getAnnotation(type, 'Component');
24266 if (component && component.entryComponents) {
24267 deepForEach(component.entryComponents, verifyComponentIsPartOfNgModule);
24268 }
24269 }
24270 }
24271 function verifySemanticsOfNgModuleImport(type, importingModule) {
24272 type = resolveForwardRef(type);
24273 if (getComponentDef(type) || getDirectiveDef(type)) {
24274 throw new Error(`Unexpected directive '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
24275 }
24276 if (getPipeDef$1(type)) {
24277 throw new Error(`Unexpected pipe '${type.name}' imported by the module '${importingModule.name}'. Please add an @NgModule annotation.`);
24278 }
24279 }
24280}
24281function unwrapModuleWithProvidersImports(typeOrWithProviders) {
24282 typeOrWithProviders = resolveForwardRef(typeOrWithProviders);
24283 return typeOrWithProviders.ngModule || typeOrWithProviders;
24284}
24285function getAnnotation(type, name) {
24286 let annotation = null;
24287 collect(type.__annotations__);
24288 collect(type.decorators);
24289 return annotation;
24290 function collect(annotations) {
24291 if (annotations) {
24292 annotations.forEach(readAnnotation);
24293 }
24294 }
24295 function readAnnotation(decorator) {
24296 if (!annotation) {
24297 const proto = Object.getPrototypeOf(decorator);
24298 if (proto.ngMetadataName == name) {
24299 annotation = decorator;
24300 }
24301 else if (decorator.type) {
24302 const proto = Object.getPrototypeOf(decorator.type);
24303 if (proto.ngMetadataName == name) {
24304 annotation = decorator.args[0];
24305 }
24306 }
24307 }
24308 }
24309}
24310/**
24311 * Keep track of compiled components. This is needed because in tests we often want to compile the
24312 * same component with more than one NgModule. This would cause an error unless we reset which
24313 * NgModule the component belongs to. We keep the list of compiled components here so that the
24314 * TestBed can reset it later.
24315 */
24316let ownerNgModule = new WeakMap();
24317let verifiedNgModule = new WeakMap();
24318function resetCompiledComponents() {
24319 ownerNgModule = new WeakMap();
24320 verifiedNgModule = new WeakMap();
24321 moduleQueue.length = 0;
24322}
24323/**
24324 * Computes the combined declarations of explicit declarations, as well as declarations inherited by
24325 * traversing the exports of imported modules.
24326 * @param type
24327 */
24328function computeCombinedExports(type) {
24329 type = resolveForwardRef(type);
24330 const ngModuleDef = getNgModuleDef(type, true);
24331 return [...flatten(maybeUnwrapFn(ngModuleDef.exports).map((type) => {
24332 const ngModuleDef = getNgModuleDef(type);
24333 if (ngModuleDef) {
24334 verifySemanticsOfNgModuleDef(type, false);
24335 return computeCombinedExports(type);
24336 }
24337 else {
24338 return type;
24339 }
24340 }))];
24341}
24342/**
24343 * Some declared components may be compiled asynchronously, and thus may not have their
24344 * ɵcmp set yet. If this is the case, then a reference to the module is written into
24345 * the `ngSelectorScope` property of the declared type.
24346 */
24347function setScopeOnDeclaredComponents(moduleType, ngModule) {
24348 const declarations = flatten(ngModule.declarations || EMPTY_ARRAY);
24349 const transitiveScopes = transitiveScopesFor(moduleType);
24350 declarations.forEach(declaration => {
24351 if (declaration.hasOwnProperty(NG_COMP_DEF)) {
24352 // A `ɵcmp` field exists - go ahead and patch the component directly.
24353 const component = declaration;
24354 const componentDef = getComponentDef(component);
24355 patchComponentDefWithScope(componentDef, transitiveScopes);
24356 }
24357 else if (!declaration.hasOwnProperty(NG_DIR_DEF) && !declaration.hasOwnProperty(NG_PIPE_DEF)) {
24358 // Set `ngSelectorScope` for future reference when the component compilation finishes.
24359 declaration.ngSelectorScope = moduleType;
24360 }
24361 });
24362}
24363/**
24364 * Patch the definition of a component with directives and pipes from the compilation scope of
24365 * a given module.
24366 */
24367function patchComponentDefWithScope(componentDef, transitiveScopes) {
24368 componentDef.directiveDefs = () => Array.from(transitiveScopes.compilation.directives)
24369 .map(dir => dir.hasOwnProperty(NG_COMP_DEF) ? getComponentDef(dir) : getDirectiveDef(dir))
24370 .filter(def => !!def);
24371 componentDef.pipeDefs = () => Array.from(transitiveScopes.compilation.pipes).map(pipe => getPipeDef$1(pipe));
24372 componentDef.schemas = transitiveScopes.schemas;
24373 // Since we avoid Components/Directives/Pipes recompiling in case there are no overrides, we
24374 // may face a problem where previously compiled defs available to a given Component/Directive
24375 // are cached in TView and may become stale (in case any of these defs gets recompiled). In
24376 // order to avoid this problem, we force fresh TView to be created.
24377 componentDef.tView = null;
24378}
24379/**
24380 * Compute the pair of transitive scopes (compilation scope and exported scope) for a given module.
24381 *
24382 * This operation is memoized and the result is cached on the module's definition. This function can
24383 * be called on modules with components that have not fully compiled yet, but the result should not
24384 * be used until they have.
24385 *
24386 * @param moduleType module that transitive scope should be calculated for.
24387 */
24388function transitiveScopesFor(moduleType) {
24389 if (!isNgModule(moduleType)) {
24390 throw new Error(`${moduleType.name} does not have a module def (ɵmod property)`);
24391 }
24392 const def = getNgModuleDef(moduleType);
24393 if (def.transitiveCompileScopes !== null) {
24394 return def.transitiveCompileScopes;
24395 }
24396 const scopes = {
24397 schemas: def.schemas || null,
24398 compilation: {
24399 directives: new Set(),
24400 pipes: new Set(),
24401 },
24402 exported: {
24403 directives: new Set(),
24404 pipes: new Set(),
24405 },
24406 };
24407 maybeUnwrapFn(def.imports).forEach((imported) => {
24408 const importedType = imported;
24409 if (!isNgModule(importedType)) {
24410 throw new Error(`Importing ${importedType.name} which does not have a ɵmod property`);
24411 }
24412 // When this module imports another, the imported module's exported directives and pipes are
24413 // added to the compilation scope of this module.
24414 const importedScope = transitiveScopesFor(importedType);
24415 importedScope.exported.directives.forEach(entry => scopes.compilation.directives.add(entry));
24416 importedScope.exported.pipes.forEach(entry => scopes.compilation.pipes.add(entry));
24417 });
24418 maybeUnwrapFn(def.declarations).forEach(declared => {
24419 const declaredWithDefs = declared;
24420 if (getPipeDef$1(declaredWithDefs)) {
24421 scopes.compilation.pipes.add(declared);
24422 }
24423 else {
24424 // Either declared has a ɵcmp or ɵdir, or it's a component which hasn't
24425 // had its template compiled yet. In either case, it gets added to the compilation's
24426 // directives.
24427 scopes.compilation.directives.add(declared);
24428 }
24429 });
24430 maybeUnwrapFn(def.exports).forEach((exported) => {
24431 const exportedType = exported;
24432 // Either the type is a module, a pipe, or a component/directive (which may not have a
24433 // ɵcmp as it might be compiled asynchronously).
24434 if (isNgModule(exportedType)) {
24435 // When this module exports another, the exported module's exported directives and pipes are
24436 // added to both the compilation and exported scopes of this module.
24437 const exportedScope = transitiveScopesFor(exportedType);
24438 exportedScope.exported.directives.forEach(entry => {
24439 scopes.compilation.directives.add(entry);
24440 scopes.exported.directives.add(entry);
24441 });
24442 exportedScope.exported.pipes.forEach(entry => {
24443 scopes.compilation.pipes.add(entry);
24444 scopes.exported.pipes.add(entry);
24445 });
24446 }
24447 else if (getPipeDef$1(exportedType)) {
24448 scopes.exported.pipes.add(exportedType);
24449 }
24450 else {
24451 scopes.exported.directives.add(exportedType);
24452 }
24453 });
24454 def.transitiveCompileScopes = scopes;
24455 return scopes;
24456}
24457function expandModuleWithProviders(value) {
24458 if (isModuleWithProviders(value)) {
24459 return value.ngModule;
24460 }
24461 return value;
24462}
24463function isModuleWithProviders(value) {
24464 return value.ngModule !== undefined;
24465}
24466function isNgModule(value) {
24467 return !!getNgModuleDef(value);
24468}
24469
24470/**
24471 * @license
24472 * Copyright Google LLC All Rights Reserved.
24473 *
24474 * Use of this source code is governed by an MIT-style license that can be
24475 * found in the LICENSE file at https://angular.io/license
24476 */
24477/**
24478 * Keep track of the compilation depth to avoid reentrancy issues during JIT compilation. This
24479 * matters in the following scenario:
24480 *
24481 * Consider a component 'A' that extends component 'B', both declared in module 'M'. During
24482 * the compilation of 'A' the definition of 'B' is requested to capture the inheritance chain,
24483 * potentially triggering compilation of 'B'. If this nested compilation were to trigger
24484 * `flushModuleScopingQueueAsMuchAsPossible` it may happen that module 'M' is still pending in the
24485 * queue, resulting in 'A' and 'B' to be patched with the NgModule scope. As the compilation of
24486 * 'A' is still in progress, this would introduce a circular dependency on its compilation. To avoid
24487 * this issue, the module scope queue is only flushed for compilations at the depth 0, to ensure
24488 * all compilations have finished.
24489 */
24490let compilationDepth = 0;
24491/**
24492 * Compile an Angular component according to its decorator metadata, and patch the resulting
24493 * component def (ɵcmp) onto the component type.
24494 *
24495 * Compilation may be asynchronous (due to the need to resolve URLs for the component template or
24496 * other resources, for example). In the event that compilation is not immediate, `compileComponent`
24497 * will enqueue resource resolution into a global queue and will fail to return the `ɵcmp`
24498 * until the global queue has been resolved with a call to `resolveComponentResources`.
24499 */
24500function compileComponent(type, metadata) {
24501 // Initialize ngDevMode. This must be the first statement in compileComponent.
24502 // See the `initNgDevMode` docstring for more information.
24503 (typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode();
24504 let ngComponentDef = null;
24505 // Metadata may have resources which need to be resolved.
24506 maybeQueueResolutionOfComponentResources(type, metadata);
24507 // Note that we're using the same function as `Directive`, because that's only subset of metadata
24508 // that we need to create the ngFactoryDef. We're avoiding using the component metadata
24509 // because we'd have to resolve the asynchronous templates.
24510 addDirectiveFactoryDef(type, metadata);
24511 Object.defineProperty(type, NG_COMP_DEF, {
24512 get: () => {
24513 if (ngComponentDef === null) {
24514 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'component', type: type });
24515 if (componentNeedsResolution(metadata)) {
24516 const error = [`Component '${type.name}' is not resolved:`];
24517 if (metadata.templateUrl) {
24518 error.push(` - templateUrl: ${metadata.templateUrl}`);
24519 }
24520 if (metadata.styleUrls && metadata.styleUrls.length) {
24521 error.push(` - styleUrls: ${JSON.stringify(metadata.styleUrls)}`);
24522 }
24523 error.push(`Did you run and wait for 'resolveComponentResources()'?`);
24524 throw new Error(error.join('\n'));
24525 }
24526 // This const was called `jitOptions` previously but had to be renamed to `options` because
24527 // of a bug with Terser that caused optimized JIT builds to throw a `ReferenceError`.
24528 // This bug was investigated in https://github.com/angular/angular-cli/issues/17264.
24529 // We should not rename it back until https://github.com/terser/terser/issues/615 is fixed.
24530 const options = getJitOptions();
24531 let preserveWhitespaces = metadata.preserveWhitespaces;
24532 if (preserveWhitespaces === undefined) {
24533 if (options !== null && options.preserveWhitespaces !== undefined) {
24534 preserveWhitespaces = options.preserveWhitespaces;
24535 }
24536 else {
24537 preserveWhitespaces = false;
24538 }
24539 }
24540 let encapsulation = metadata.encapsulation;
24541 if (encapsulation === undefined) {
24542 if (options !== null && options.defaultEncapsulation !== undefined) {
24543 encapsulation = options.defaultEncapsulation;
24544 }
24545 else {
24546 encapsulation = ViewEncapsulation$1.Emulated;
24547 }
24548 }
24549 const templateUrl = metadata.templateUrl || `ng:///${type.name}/template.html`;
24550 const meta = Object.assign(Object.assign({}, directiveMetadata(type, metadata)), { typeSourceSpan: compiler.createParseSourceSpan('Component', type.name, templateUrl), template: metadata.template || '', preserveWhitespaces, styles: metadata.styles || EMPTY_ARRAY, animations: metadata.animations, directives: [], changeDetection: metadata.changeDetection, pipes: new Map(), encapsulation, interpolation: metadata.interpolation, viewProviders: metadata.viewProviders || null });
24551 compilationDepth++;
24552 try {
24553 if (meta.usesInheritance) {
24554 addDirectiveDefToUndecoratedParents(type);
24555 }
24556 ngComponentDef = compiler.compileComponent(angularCoreEnv, templateUrl, meta);
24557 }
24558 finally {
24559 // Ensure that the compilation depth is decremented even when the compilation failed.
24560 compilationDepth--;
24561 }
24562 if (compilationDepth === 0) {
24563 // When NgModule decorator executed, we enqueued the module definition such that
24564 // it would only dequeue and add itself as module scope to all of its declarations,
24565 // but only if if all of its declarations had resolved. This call runs the check
24566 // to see if any modules that are in the queue can be dequeued and add scope to
24567 // their declarations.
24568 flushModuleScopingQueueAsMuchAsPossible();
24569 }
24570 // If component compilation is async, then the @NgModule annotation which declares the
24571 // component may execute and set an ngSelectorScope property on the component type. This
24572 // allows the component to patch itself with directiveDefs from the module after it
24573 // finishes compiling.
24574 if (hasSelectorScope(type)) {
24575 const scopes = transitiveScopesFor(type.ngSelectorScope);
24576 patchComponentDefWithScope(ngComponentDef, scopes);
24577 }
24578 }
24579 return ngComponentDef;
24580 },
24581 // Make the property configurable in dev mode to allow overriding in tests
24582 configurable: !!ngDevMode,
24583 });
24584}
24585function hasSelectorScope(component) {
24586 return component.ngSelectorScope !== undefined;
24587}
24588/**
24589 * Compile an Angular directive according to its decorator metadata, and patch the resulting
24590 * directive def onto the component type.
24591 *
24592 * In the event that compilation is not immediate, `compileDirective` will return a `Promise` which
24593 * will resolve when compilation completes and the directive becomes usable.
24594 */
24595function compileDirective(type, directive) {
24596 let ngDirectiveDef = null;
24597 addDirectiveFactoryDef(type, directive || {});
24598 Object.defineProperty(type, NG_DIR_DEF, {
24599 get: () => {
24600 if (ngDirectiveDef === null) {
24601 // `directive` can be null in the case of abstract directives as a base class
24602 // that use `@Directive()` with no selector. In that case, pass empty object to the
24603 // `directiveMetadata` function instead of null.
24604 const meta = getDirectiveMetadata(type, directive || {});
24605 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'directive', type });
24606 ngDirectiveDef =
24607 compiler.compileDirective(angularCoreEnv, meta.sourceMapUrl, meta.metadata);
24608 }
24609 return ngDirectiveDef;
24610 },
24611 // Make the property configurable in dev mode to allow overriding in tests
24612 configurable: !!ngDevMode,
24613 });
24614}
24615function getDirectiveMetadata(type, metadata) {
24616 const name = type && type.name;
24617 const sourceMapUrl = `ng:///${name}/ɵdir.js`;
24618 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'directive', type });
24619 const facade = directiveMetadata(type, metadata);
24620 facade.typeSourceSpan = compiler.createParseSourceSpan('Directive', name, sourceMapUrl);
24621 if (facade.usesInheritance) {
24622 addDirectiveDefToUndecoratedParents(type);
24623 }
24624 return { metadata: facade, sourceMapUrl };
24625}
24626function addDirectiveFactoryDef(type, metadata) {
24627 let ngFactoryDef = null;
24628 Object.defineProperty(type, NG_FACTORY_DEF, {
24629 get: () => {
24630 if (ngFactoryDef === null) {
24631 const meta = getDirectiveMetadata(type, metadata);
24632 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'directive', type });
24633 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${type.name}/ɵfac.js`, {
24634 name: meta.metadata.name,
24635 type: meta.metadata.type,
24636 typeArgumentCount: 0,
24637 deps: reflectDependencies(type),
24638 target: compiler.FactoryTarget.Directive
24639 });
24640 }
24641 return ngFactoryDef;
24642 },
24643 // Make the property configurable in dev mode to allow overriding in tests
24644 configurable: !!ngDevMode,
24645 });
24646}
24647function extendsDirectlyFromObject(type) {
24648 return Object.getPrototypeOf(type.prototype) === Object.prototype;
24649}
24650/**
24651 * Extract the `R3DirectiveMetadata` for a particular directive (either a `Directive` or a
24652 * `Component`).
24653 */
24654function directiveMetadata(type, metadata) {
24655 // Reflect inputs and outputs.
24656 const reflect = getReflect();
24657 const propMetadata = reflect.ownPropMetadata(type);
24658 return {
24659 name: type.name,
24660 type: type,
24661 selector: metadata.selector !== undefined ? metadata.selector : null,
24662 host: metadata.host || EMPTY_OBJ,
24663 propMetadata: propMetadata,
24664 inputs: metadata.inputs || EMPTY_ARRAY,
24665 outputs: metadata.outputs || EMPTY_ARRAY,
24666 queries: extractQueriesMetadata(type, propMetadata, isContentQuery),
24667 lifecycle: { usesOnChanges: reflect.hasLifecycleHook(type, 'ngOnChanges') },
24668 typeSourceSpan: null,
24669 usesInheritance: !extendsDirectlyFromObject(type),
24670 exportAs: extractExportAs(metadata.exportAs),
24671 providers: metadata.providers || null,
24672 viewQueries: extractQueriesMetadata(type, propMetadata, isViewQuery)
24673 };
24674}
24675/**
24676 * Adds a directive definition to all parent classes of a type that don't have an Angular decorator.
24677 */
24678function addDirectiveDefToUndecoratedParents(type) {
24679 const objPrototype = Object.prototype;
24680 let parent = Object.getPrototypeOf(type.prototype).constructor;
24681 // Go up the prototype until we hit `Object`.
24682 while (parent && parent !== objPrototype) {
24683 // Since inheritance works if the class was annotated already, we only need to add
24684 // the def if there are no annotations and the def hasn't been created already.
24685 if (!getDirectiveDef(parent) && !getComponentDef(parent) &&
24686 shouldAddAbstractDirective(parent)) {
24687 compileDirective(parent, null);
24688 }
24689 parent = Object.getPrototypeOf(parent);
24690 }
24691}
24692function convertToR3QueryPredicate(selector) {
24693 return typeof selector === 'string' ? splitByComma(selector) : resolveForwardRef(selector);
24694}
24695function convertToR3QueryMetadata(propertyName, ann) {
24696 return {
24697 propertyName: propertyName,
24698 predicate: convertToR3QueryPredicate(ann.selector),
24699 descendants: ann.descendants,
24700 first: ann.first,
24701 read: ann.read ? ann.read : null,
24702 static: !!ann.static,
24703 emitDistinctChangesOnly: !!ann.emitDistinctChangesOnly,
24704 };
24705}
24706function extractQueriesMetadata(type, propMetadata, isQueryAnn) {
24707 const queriesMeta = [];
24708 for (const field in propMetadata) {
24709 if (propMetadata.hasOwnProperty(field)) {
24710 const annotations = propMetadata[field];
24711 annotations.forEach(ann => {
24712 if (isQueryAnn(ann)) {
24713 if (!ann.selector) {
24714 throw new Error(`Can't construct a query for the property "${field}" of ` +
24715 `"${stringifyForError(type)}" since the query selector wasn't defined.`);
24716 }
24717 if (annotations.some(isInputAnnotation)) {
24718 throw new Error(`Cannot combine @Input decorators with query decorators`);
24719 }
24720 queriesMeta.push(convertToR3QueryMetadata(field, ann));
24721 }
24722 });
24723 }
24724 }
24725 return queriesMeta;
24726}
24727function extractExportAs(exportAs) {
24728 return exportAs === undefined ? null : splitByComma(exportAs);
24729}
24730function isContentQuery(value) {
24731 const name = value.ngMetadataName;
24732 return name === 'ContentChild' || name === 'ContentChildren';
24733}
24734function isViewQuery(value) {
24735 const name = value.ngMetadataName;
24736 return name === 'ViewChild' || name === 'ViewChildren';
24737}
24738function isInputAnnotation(value) {
24739 return value.ngMetadataName === 'Input';
24740}
24741function splitByComma(value) {
24742 return value.split(',').map(piece => piece.trim());
24743}
24744const LIFECYCLE_HOOKS = [
24745 'ngOnChanges', 'ngOnInit', 'ngOnDestroy', 'ngDoCheck', 'ngAfterViewInit', 'ngAfterViewChecked',
24746 'ngAfterContentInit', 'ngAfterContentChecked'
24747];
24748function shouldAddAbstractDirective(type) {
24749 const reflect = getReflect();
24750 if (LIFECYCLE_HOOKS.some(hookName => reflect.hasLifecycleHook(type, hookName))) {
24751 return true;
24752 }
24753 const propMetadata = reflect.propMetadata(type);
24754 for (const field in propMetadata) {
24755 const annotations = propMetadata[field];
24756 for (let i = 0; i < annotations.length; i++) {
24757 const current = annotations[i];
24758 const metadataName = current.ngMetadataName;
24759 if (isInputAnnotation(current) || isContentQuery(current) || isViewQuery(current) ||
24760 metadataName === 'Output' || metadataName === 'HostBinding' ||
24761 metadataName === 'HostListener') {
24762 return true;
24763 }
24764 }
24765 }
24766 return false;
24767}
24768
24769/**
24770 * @license
24771 * Copyright Google LLC All Rights Reserved.
24772 *
24773 * Use of this source code is governed by an MIT-style license that can be
24774 * found in the LICENSE file at https://angular.io/license
24775 */
24776function compilePipe(type, meta) {
24777 let ngPipeDef = null;
24778 let ngFactoryDef = null;
24779 Object.defineProperty(type, NG_FACTORY_DEF, {
24780 get: () => {
24781 if (ngFactoryDef === null) {
24782 const metadata = getPipeMetadata(type, meta);
24783 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'pipe', type: metadata.type });
24784 ngFactoryDef = compiler.compileFactory(angularCoreEnv, `ng:///${metadata.name}/ɵfac.js`, {
24785 name: metadata.name,
24786 type: metadata.type,
24787 typeArgumentCount: 0,
24788 deps: reflectDependencies(type),
24789 target: compiler.FactoryTarget.Pipe
24790 });
24791 }
24792 return ngFactoryDef;
24793 },
24794 // Make the property configurable in dev mode to allow overriding in tests
24795 configurable: !!ngDevMode,
24796 });
24797 Object.defineProperty(type, NG_PIPE_DEF, {
24798 get: () => {
24799 if (ngPipeDef === null) {
24800 const metadata = getPipeMetadata(type, meta);
24801 const compiler = getCompilerFacade({ usage: 0 /* Decorator */, kind: 'pipe', type: metadata.type });
24802 ngPipeDef =
24803 compiler.compilePipe(angularCoreEnv, `ng:///${metadata.name}/ɵpipe.js`, metadata);
24804 }
24805 return ngPipeDef;
24806 },
24807 // Make the property configurable in dev mode to allow overriding in tests
24808 configurable: !!ngDevMode,
24809 });
24810}
24811function getPipeMetadata(type, meta) {
24812 return {
24813 type: type,
24814 name: type.name,
24815 pipeName: meta.name,
24816 pure: meta.pure !== undefined ? meta.pure : true
24817 };
24818}
24819
24820/**
24821 * @license
24822 * Copyright Google LLC All Rights Reserved.
24823 *
24824 * Use of this source code is governed by an MIT-style license that can be
24825 * found in the LICENSE file at https://angular.io/license
24826 */
24827/**
24828 * Type of the Directive metadata.
24829 *
24830 * @publicApi
24831 */
24832const Directive = makeDecorator('Directive', (dir = {}) => dir, undefined, undefined, (type, meta) => SWITCH_COMPILE_DIRECTIVE(type, meta));
24833/**
24834 * Component decorator and metadata.
24835 *
24836 * @Annotation
24837 * @publicApi
24838 */
24839const Component = makeDecorator('Component', (c = {}) => (Object.assign({ changeDetection: ChangeDetectionStrategy.Default }, c)), Directive, undefined, (type, meta) => SWITCH_COMPILE_COMPONENT(type, meta));
24840/**
24841 * @Annotation
24842 * @publicApi
24843 */
24844const Pipe = makeDecorator('Pipe', (p) => (Object.assign({ pure: true }, p)), undefined, undefined, (type, meta) => SWITCH_COMPILE_PIPE(type, meta));
24845/**
24846 * @Annotation
24847 * @publicApi
24848 */
24849const Input = makePropDecorator('Input', (bindingPropertyName) => ({ bindingPropertyName }));
24850/**
24851 * @Annotation
24852 * @publicApi
24853 */
24854const Output = makePropDecorator('Output', (bindingPropertyName) => ({ bindingPropertyName }));
24855/**
24856 * @Annotation
24857 * @publicApi
24858 */
24859const HostBinding = makePropDecorator('HostBinding', (hostPropertyName) => ({ hostPropertyName }));
24860/**
24861 * Decorator that binds a DOM event to a host listener and supplies configuration metadata.
24862 * Angular invokes the supplied handler method when the host element emits the specified event,
24863 * and updates the bound element with the result.
24864 *
24865 * If the handler method returns false, applies `preventDefault` on the bound element.
24866 *
24867 * @usageNotes
24868 *
24869 * The following example declares a directive
24870 * that attaches a click listener to a button and counts clicks.
24871 *
24872 * ```ts
24873 * @Directive({selector: 'button[counting]'})
24874 * class CountClicks {
24875 * numberOfClicks = 0;
24876 *
24877 * @HostListener('click', ['$event.target'])
24878 * onClick(btn) {
24879 * console.log('button', btn, 'number of clicks:', this.numberOfClicks++);
24880 * }
24881 * }
24882 *
24883 * @Component({
24884 * selector: 'app',
24885 * template: '<button counting>Increment</button>',
24886 * })
24887 * class App {}
24888 *
24889 * ```
24890 *
24891 * The following example registers another DOM event handler that listens for key-press events.
24892 * ``` ts
24893 * import { HostListener, Component } from "@angular/core";
24894 *
24895 * @Component({
24896 * selector: 'app',
24897 * template: `<h1>Hello, you have pressed keys {{counter}} number of times!</h1> Press any key to
24898 * increment the counter.
24899 * <button (click)="resetCounter()">Reset Counter</button>`
24900 * })
24901 * class AppComponent {
24902 * counter = 0;
24903 * @HostListener('window:keydown', ['$event'])
24904 * handleKeyDown(event: KeyboardEvent) {
24905 * this.counter++;
24906 * }
24907 * resetCounter() {
24908 * this.counter = 0;
24909 * }
24910 * }
24911 * ```
24912 *
24913 * @Annotation
24914 * @publicApi
24915 */
24916const HostListener = makePropDecorator('HostListener', (eventName, args) => ({ eventName, args }));
24917const SWITCH_COMPILE_COMPONENT__POST_R3__ = compileComponent;
24918const SWITCH_COMPILE_DIRECTIVE__POST_R3__ = compileDirective;
24919const SWITCH_COMPILE_PIPE__POST_R3__ = compilePipe;
24920const SWITCH_COMPILE_COMPONENT__PRE_R3__ = noop;
24921const SWITCH_COMPILE_DIRECTIVE__PRE_R3__ = noop;
24922const SWITCH_COMPILE_PIPE__PRE_R3__ = noop;
24923const SWITCH_COMPILE_COMPONENT = SWITCH_COMPILE_COMPONENT__POST_R3__;
24924const SWITCH_COMPILE_DIRECTIVE = SWITCH_COMPILE_DIRECTIVE__POST_R3__;
24925const SWITCH_COMPILE_PIPE = SWITCH_COMPILE_PIPE__POST_R3__;
24926
24927/**
24928 * @license
24929 * Copyright Google LLC All Rights Reserved.
24930 *
24931 * Use of this source code is governed by an MIT-style license that can be
24932 * found in the LICENSE file at https://angular.io/license
24933 */
24934/**
24935 * @Annotation
24936 * @publicApi
24937 */
24938const NgModule = makeDecorator('NgModule', (ngModule) => ngModule, undefined, undefined,
24939/**
24940 * Decorator that marks the following class as an NgModule, and supplies
24941 * configuration metadata for it.
24942 *
24943 * * The `declarations` and `entryComponents` options configure the compiler
24944 * with information about what belongs to the NgModule.
24945 * * The `providers` options configures the NgModule's injector to provide
24946 * dependencies the NgModule members.
24947 * * The `imports` and `exports` options bring in members from other modules, and make
24948 * this module's members available to others.
24949 */
24950(type, meta) => SWITCH_COMPILE_NGMODULE(type, meta));
24951function preR3NgModuleCompile(moduleType, metadata) {
24952 let imports = (metadata && metadata.imports) || [];
24953 if (metadata && metadata.exports) {
24954 imports = [...imports, metadata.exports];
24955 }
24956 const moduleInjectorType = moduleType;
24957 moduleInjectorType.ɵfac = convertInjectableProviderToFactory(moduleType, { useClass: moduleType });
24958 moduleInjectorType.ɵinj =
24959 ɵɵdefineInjector({ providers: metadata && metadata.providers, imports: imports });
24960}
24961const SWITCH_COMPILE_NGMODULE__POST_R3__ = compileNgModule;
24962const SWITCH_COMPILE_NGMODULE__PRE_R3__ = preR3NgModuleCompile;
24963const SWITCH_COMPILE_NGMODULE = SWITCH_COMPILE_NGMODULE__POST_R3__;
24964
24965/**
24966 * @license
24967 * Copyright Google LLC All Rights Reserved.
24968 *
24969 * Use of this source code is governed by an MIT-style license that can be
24970 * found in the LICENSE file at https://angular.io/license
24971 */
24972
24973/**
24974 * @license
24975 * Copyright Google LLC All Rights Reserved.
24976 *
24977 * Use of this source code is governed by an MIT-style license that can be
24978 * found in the LICENSE file at https://angular.io/license
24979 */
24980/**
24981 * The existence of this constant (in this particular file) informs the Angular compiler that the
24982 * current program is actually @angular/core, which needs to be compiled specially.
24983 */
24984const ITS_JUST_ANGULAR = true;
24985
24986/**
24987 * A [DI token](guide/glossary#di-token "DI token definition") that you can use to provide
24988 * one or more initialization functions.
24989 *
24990 * The provided functions are injected at application startup and executed during
24991 * app initialization. If any of these functions returns a Promise or an Observable, initialization
24992 * does not complete until the Promise is resolved or the Observable is completed.
24993 *
24994 * You can, for example, create a factory function that loads language data
24995 * or an external configuration, and provide that function to the `APP_INITIALIZER` token.
24996 * The function is executed during the application bootstrap process,
24997 * and the needed data is available on startup.
24998 *
24999 * @see `ApplicationInitStatus`
25000 *
25001 * @usageNotes
25002 *
25003 * The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
25004 * and a function returning a promise.
25005 *
25006 * ```
25007 * function initializeApp(): Promise<any> {
25008 * return new Promise((resolve, reject) => {
25009 * // Do some asynchronous stuff
25010 * resolve();
25011 * });
25012 * }
25013 *
25014 * @NgModule({
25015 * imports: [BrowserModule],
25016 * declarations: [AppComponent],
25017 * bootstrap: [AppComponent],
25018 * providers: [{
25019 * provide: APP_INITIALIZER,
25020 * useFactory: () => initializeApp,
25021 * multi: true
25022 * }]
25023 * })
25024 * export class AppModule {}
25025 * ```
25026 *
25027 * It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
25028 * returning an observable, see an example below. Note: the `HttpClient` in this example is used for
25029 * demo purposes to illustrate how the factory function can work with other providers available
25030 * through DI.
25031 *
25032 * ```
25033 * function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
25034 * return () => httpClient.get("https://someUrl.com/api/user")
25035 * .pipe(
25036 * tap(user => { ... })
25037 * );
25038 * }
25039 *
25040 * @NgModule({
25041 * imports: [BrowserModule, HttpClientModule],
25042 * declarations: [AppComponent],
25043 * bootstrap: [AppComponent],
25044 * providers: [{
25045 * provide: APP_INITIALIZER,
25046 * useFactory: initializeAppFactory,
25047 * deps: [HttpClient],
25048 * multi: true
25049 * }]
25050 * })
25051 * export class AppModule {}
25052 * ```
25053 *
25054 * @publicApi
25055 */
25056const APP_INITIALIZER = new InjectionToken('Application Initializer');
25057/**
25058 * A class that reflects the state of running {@link APP_INITIALIZER} functions.
25059 *
25060 * @publicApi
25061 */
25062class ApplicationInitStatus {
25063 constructor(appInits) {
25064 this.appInits = appInits;
25065 this.resolve = noop;
25066 this.reject = noop;
25067 this.initialized = false;
25068 this.done = false;
25069 this.donePromise = new Promise((res, rej) => {
25070 this.resolve = res;
25071 this.reject = rej;
25072 });
25073 }
25074 /** @internal */
25075 runInitializers() {
25076 if (this.initialized) {
25077 return;
25078 }
25079 const asyncInitPromises = [];
25080 const complete = () => {
25081 this.done = true;
25082 this.resolve();
25083 };
25084 if (this.appInits) {
25085 for (let i = 0; i < this.appInits.length; i++) {
25086 const initResult = this.appInits[i]();
25087 if (isPromise(initResult)) {
25088 asyncInitPromises.push(initResult);
25089 }
25090 else if (isObservable(initResult)) {
25091 const observableAsPromise = new Promise((resolve, reject) => {
25092 initResult.subscribe({ complete: resolve, error: reject });
25093 });
25094 asyncInitPromises.push(observableAsPromise);
25095 }
25096 }
25097 }
25098 Promise.all(asyncInitPromises)
25099 .then(() => {
25100 complete();
25101 })
25102 .catch(e => {
25103 this.reject(e);
25104 });
25105 if (asyncInitPromises.length === 0) {
25106 complete();
25107 }
25108 this.initialized = true;
25109 }
25110}
25111ApplicationInitStatus.ɵfac = function ApplicationInitStatus_Factory(t) { return new (t || ApplicationInitStatus)(ɵɵinject(APP_INITIALIZER, 8)); };
25112ApplicationInitStatus.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationInitStatus, factory: ApplicationInitStatus.ɵfac });
25113(function () {
25114 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationInitStatus, [{
25115 type: Injectable
25116 }], function () {
25117 return [{ type: undefined, decorators: [{
25118 type: Inject,
25119 args: [APP_INITIALIZER]
25120 }, {
25121 type: Optional
25122 }] }];
25123 }, null);
25124})();
25125
25126/**
25127 * @license
25128 * Copyright Google LLC All Rights Reserved.
25129 *
25130 * Use of this source code is governed by an MIT-style license that can be
25131 * found in the LICENSE file at https://angular.io/license
25132 */
25133/**
25134 * A [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used
25135 * primarily for prefixing application attributes and CSS styles when
25136 * {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
25137 *
25138 * BY default, the value is randomly generated and assigned to the application by Angular.
25139 * To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure
25140 * the root {@link Injector} that uses this token.
25141 *
25142 * @publicApi
25143 */
25144const APP_ID = new InjectionToken('AppId');
25145function _appIdRandomProviderFactory() {
25146 return `${_randomChar()}${_randomChar()}${_randomChar()}`;
25147}
25148/**
25149 * Providers that generate a random `APP_ID_TOKEN`.
25150 * @publicApi
25151 */
25152const APP_ID_RANDOM_PROVIDER = {
25153 provide: APP_ID,
25154 useFactory: _appIdRandomProviderFactory,
25155 deps: [],
25156};
25157function _randomChar() {
25158 return String.fromCharCode(97 + Math.floor(Math.random() * 25));
25159}
25160/**
25161 * A function that is executed when a platform is initialized.
25162 * @publicApi
25163 */
25164const PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer');
25165/**
25166 * A token that indicates an opaque platform ID.
25167 * @publicApi
25168 */
25169const PLATFORM_ID = new InjectionToken('Platform ID');
25170/**
25171 * A [DI token](guide/glossary#di-token "DI token definition") that provides a set of callbacks to
25172 * be called for every component that is bootstrapped.
25173 *
25174 * Each callback must take a `ComponentRef` instance and return nothing.
25175 *
25176 * `(componentRef: ComponentRef) => void`
25177 *
25178 * @publicApi
25179 */
25180const APP_BOOTSTRAP_LISTENER = new InjectionToken('appBootstrapListener');
25181/**
25182 * A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of
25183 * the application
25184 * @publicApi
25185 */
25186const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
25187
25188/**
25189 * @license
25190 * Copyright Google LLC All Rights Reserved.
25191 *
25192 * Use of this source code is governed by an MIT-style license that can be
25193 * found in the LICENSE file at https://angular.io/license
25194 */
25195class Console {
25196 log(message) {
25197 // tslint:disable-next-line:no-console
25198 console.log(message);
25199 }
25200 // Note: for reporting errors use `DOM.logError()` as it is platform specific
25201 warn(message) {
25202 // tslint:disable-next-line:no-console
25203 console.warn(message);
25204 }
25205}
25206Console.ɵfac = function Console_Factory(t) { return new (t || Console)(); };
25207Console.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Console, factory: Console.ɵfac });
25208(function () {
25209 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Console, [{
25210 type: Injectable
25211 }], null, null);
25212})();
25213
25214/**
25215 * @license
25216 * Copyright Google LLC All Rights Reserved.
25217 *
25218 * Use of this source code is governed by an MIT-style license that can be
25219 * found in the LICENSE file at https://angular.io/license
25220 */
25221/**
25222 * Provide this token to set the locale of your application.
25223 * It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe,
25224 * DecimalPipe and PercentPipe) and by ICU expressions.
25225 *
25226 * See the [i18n guide](guide/i18n-common-locale-id) for more information.
25227 *
25228 * @usageNotes
25229 * ### Example
25230 *
25231 * ```typescript
25232 * import { LOCALE_ID } from '@angular/core';
25233 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25234 * import { AppModule } from './app/app.module';
25235 *
25236 * platformBrowserDynamic().bootstrapModule(AppModule, {
25237 * providers: [{provide: LOCALE_ID, useValue: 'en-US' }]
25238 * });
25239 * ```
25240 *
25241 * @publicApi
25242 */
25243const LOCALE_ID = new InjectionToken('LocaleId');
25244/**
25245 * Provide this token to set the default currency code your application uses for
25246 * CurrencyPipe when there is no currency code passed into it. This is only used by
25247 * CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured.
25248 *
25249 * See the [i18n guide](guide/i18n-common-locale-id) for more information.
25250 *
25251 * <div class="alert is-helpful">
25252 *
25253 * **Deprecation notice:**
25254 *
25255 * The default currency code is currently always `USD` but this is deprecated from v9.
25256 *
25257 * **In v10 the default currency code will be taken from the current locale.**
25258 *
25259 * If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in
25260 * your application `NgModule`:
25261 *
25262 * ```ts
25263 * {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}
25264 * ```
25265 *
25266 * </div>
25267 *
25268 * @usageNotes
25269 * ### Example
25270 *
25271 * ```typescript
25272 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25273 * import { AppModule } from './app/app.module';
25274 *
25275 * platformBrowserDynamic().bootstrapModule(AppModule, {
25276 * providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }]
25277 * });
25278 * ```
25279 *
25280 * @publicApi
25281 */
25282const DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode');
25283/**
25284 * Use this token at bootstrap to provide the content of your translation file (`xtb`,
25285 * `xlf` or `xlf2`) when you want to translate your application in another language.
25286 *
25287 * See the [i18n guide](guide/i18n-common-merge) for more information.
25288 *
25289 * @usageNotes
25290 * ### Example
25291 *
25292 * ```typescript
25293 * import { TRANSLATIONS } from '@angular/core';
25294 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25295 * import { AppModule } from './app/app.module';
25296 *
25297 * // content of your translation file
25298 * const translations = '....';
25299 *
25300 * platformBrowserDynamic().bootstrapModule(AppModule, {
25301 * providers: [{provide: TRANSLATIONS, useValue: translations }]
25302 * });
25303 * ```
25304 *
25305 * @publicApi
25306 */
25307const TRANSLATIONS = new InjectionToken('Translations');
25308/**
25309 * Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`,
25310 * `xlf` or `xlf2`.
25311 *
25312 * See the [i18n guide](guide/i18n-common-merge) for more information.
25313 *
25314 * @usageNotes
25315 * ### Example
25316 *
25317 * ```typescript
25318 * import { TRANSLATIONS_FORMAT } from '@angular/core';
25319 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25320 * import { AppModule } from './app/app.module';
25321 *
25322 * platformBrowserDynamic().bootstrapModule(AppModule, {
25323 * providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }]
25324 * });
25325 * ```
25326 *
25327 * @publicApi
25328 */
25329const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat');
25330/**
25331 * Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy
25332 * that the compiler should use in case of missing translations:
25333 * - Error: throw if you have missing translations.
25334 * - Warning (default): show a warning in the console and/or shell.
25335 * - Ignore: do nothing.
25336 *
25337 * See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information.
25338 *
25339 * @usageNotes
25340 * ### Example
25341 * ```typescript
25342 * import { MissingTranslationStrategy } from '@angular/core';
25343 * import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
25344 * import { AppModule } from './app/app.module';
25345 *
25346 * platformBrowserDynamic().bootstrapModule(AppModule, {
25347 * missingTranslation: MissingTranslationStrategy.Error
25348 * });
25349 * ```
25350 *
25351 * @publicApi
25352 */
25353var MissingTranslationStrategy;
25354(function (MissingTranslationStrategy) {
25355 MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
25356 MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
25357 MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
25358})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
25359
25360/**
25361 * @license
25362 * Copyright Google LLC All Rights Reserved.
25363 *
25364 * Use of this source code is governed by an MIT-style license that can be
25365 * found in the LICENSE file at https://angular.io/license
25366 */
25367const SWITCH_IVY_ENABLED__POST_R3__ = true;
25368const SWITCH_IVY_ENABLED__PRE_R3__ = false;
25369const ivyEnabled = SWITCH_IVY_ENABLED__POST_R3__;
25370
25371/**
25372 * @license
25373 * Copyright Google LLC All Rights Reserved.
25374 *
25375 * Use of this source code is governed by an MIT-style license that can be
25376 * found in the LICENSE file at https://angular.io/license
25377 */
25378/**
25379 * Combination of NgModuleFactory and ComponentFactories.
25380 *
25381 * @publicApi
25382 *
25383 * @deprecated
25384 * Ivy JIT mode doesn't require accessing this symbol.
25385 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
25386 * additional context.
25387 */
25388class ModuleWithComponentFactories {
25389 constructor(ngModuleFactory, componentFactories) {
25390 this.ngModuleFactory = ngModuleFactory;
25391 this.componentFactories = componentFactories;
25392 }
25393}
25394function _throwError() {
25395 throw new Error(`Runtime compiler is not loaded`);
25396}
25397const Compiler_compileModuleSync__PRE_R3__ = _throwError;
25398const Compiler_compileModuleSync__POST_R3__ = function (moduleType) {
25399 return new NgModuleFactory(moduleType);
25400};
25401const Compiler_compileModuleSync = Compiler_compileModuleSync__POST_R3__;
25402const Compiler_compileModuleAsync__PRE_R3__ = _throwError;
25403const Compiler_compileModuleAsync__POST_R3__ = function (moduleType) {
25404 return Promise.resolve(Compiler_compileModuleSync__POST_R3__(moduleType));
25405};
25406const Compiler_compileModuleAsync = Compiler_compileModuleAsync__POST_R3__;
25407const Compiler_compileModuleAndAllComponentsSync__PRE_R3__ = _throwError;
25408const Compiler_compileModuleAndAllComponentsSync__POST_R3__ = function (moduleType) {
25409 const ngModuleFactory = Compiler_compileModuleSync__POST_R3__(moduleType);
25410 const moduleDef = getNgModuleDef(moduleType);
25411 const componentFactories = maybeUnwrapFn(moduleDef.declarations)
25412 .reduce((factories, declaration) => {
25413 const componentDef = getComponentDef(declaration);
25414 componentDef && factories.push(new ComponentFactory(componentDef));
25415 return factories;
25416 }, []);
25417 return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
25418};
25419const Compiler_compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync__POST_R3__;
25420const Compiler_compileModuleAndAllComponentsAsync__PRE_R3__ = _throwError;
25421const Compiler_compileModuleAndAllComponentsAsync__POST_R3__ = function (moduleType) {
25422 return Promise.resolve(Compiler_compileModuleAndAllComponentsSync__POST_R3__(moduleType));
25423};
25424const Compiler_compileModuleAndAllComponentsAsync = Compiler_compileModuleAndAllComponentsAsync__POST_R3__;
25425/**
25426 * Low-level service for running the angular compiler during runtime
25427 * to create {@link ComponentFactory}s, which
25428 * can later be used to create and render a Component instance.
25429 *
25430 * Each `@NgModule` provides an own `Compiler` to its injector,
25431 * that will use the directives/pipes of the ng module for compilation
25432 * of components.
25433 *
25434 * @publicApi
25435 *
25436 * @deprecated
25437 * Ivy JIT mode doesn't require accessing this symbol.
25438 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
25439 * additional context.
25440 */
25441class Compiler {
25442 constructor() {
25443 /**
25444 * Compiles the given NgModule and all of its components. All templates of the components listed
25445 * in `entryComponents` have to be inlined.
25446 */
25447 this.compileModuleSync = Compiler_compileModuleSync;
25448 /**
25449 * Compiles the given NgModule and all of its components
25450 */
25451 this.compileModuleAsync = Compiler_compileModuleAsync;
25452 /**
25453 * Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
25454 */
25455 this.compileModuleAndAllComponentsSync = Compiler_compileModuleAndAllComponentsSync;
25456 /**
25457 * Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
25458 */
25459 this.compileModuleAndAllComponentsAsync = Compiler_compileModuleAndAllComponentsAsync;
25460 }
25461 /**
25462 * Clears all caches.
25463 */
25464 clearCache() { }
25465 /**
25466 * Clears the cache for the given component/ngModule.
25467 */
25468 clearCacheFor(type) { }
25469 /**
25470 * Returns the id for a given NgModule, if one is defined and known to the compiler.
25471 */
25472 getModuleId(moduleType) {
25473 return undefined;
25474 }
25475}
25476Compiler.ɵfac = function Compiler_Factory(t) { return new (t || Compiler)(); };
25477Compiler.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Compiler, factory: Compiler.ɵfac });
25478(function () {
25479 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Compiler, [{
25480 type: Injectable
25481 }], null, null);
25482})();
25483/**
25484 * Token to provide CompilerOptions in the platform injector.
25485 *
25486 * @publicApi
25487 */
25488const COMPILER_OPTIONS = new InjectionToken('compilerOptions');
25489/**
25490 * A factory for creating a Compiler
25491 *
25492 * @publicApi
25493 *
25494 * @deprecated
25495 * Ivy JIT mode doesn't require accessing this symbol.
25496 * See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
25497 * additional context.
25498 */
25499class CompilerFactory {
25500}
25501
25502/**
25503 * @license
25504 * Copyright Google LLC All Rights Reserved.
25505 *
25506 * Use of this source code is governed by an MIT-style license that can be
25507 * found in the LICENSE file at https://angular.io/license
25508 */
25509const promise = (() => Promise.resolve(0))();
25510function scheduleMicroTask(fn) {
25511 if (typeof Zone === 'undefined') {
25512 // use promise to schedule microTask instead of use Zone
25513 promise.then(() => {
25514 fn && fn.apply(null, null);
25515 });
25516 }
25517 else {
25518 Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
25519 }
25520}
25521
25522/**
25523 * @license
25524 * Copyright Google LLC All Rights Reserved.
25525 *
25526 * Use of this source code is governed by an MIT-style license that can be
25527 * found in the LICENSE file at https://angular.io/license
25528 */
25529function getNativeRequestAnimationFrame() {
25530 let nativeRequestAnimationFrame = _global['requestAnimationFrame'];
25531 let nativeCancelAnimationFrame = _global['cancelAnimationFrame'];
25532 if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
25533 // use unpatched version of requestAnimationFrame(native delegate) if possible
25534 // to avoid another Change detection
25535 const unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')];
25536 if (unpatchedRequestAnimationFrame) {
25537 nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
25538 }
25539 const unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')];
25540 if (unpatchedCancelAnimationFrame) {
25541 nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
25542 }
25543 }
25544 return { nativeRequestAnimationFrame, nativeCancelAnimationFrame };
25545}
25546
25547/**
25548 * @license
25549 * Copyright Google LLC All Rights Reserved.
25550 *
25551 * Use of this source code is governed by an MIT-style license that can be
25552 * found in the LICENSE file at https://angular.io/license
25553 */
25554/**
25555 * An injectable service for executing work inside or outside of the Angular zone.
25556 *
25557 * The most common use of this service is to optimize performance when starting a work consisting of
25558 * one or more asynchronous tasks that don't require UI updates or error handling to be handled by
25559 * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks
25560 * can reenter the Angular zone via {@link #run}.
25561 *
25562 * <!-- TODO: add/fix links to:
25563 * - docs explaining zones and the use of zones in Angular and change-detection
25564 * - link to runOutsideAngular/run (throughout this file!)
25565 * -->
25566 *
25567 * @usageNotes
25568 * ### Example
25569 *
25570 * ```
25571 * import {Component, NgZone} from '@angular/core';
25572 * import {NgIf} from '@angular/common';
25573 *
25574 * @Component({
25575 * selector: 'ng-zone-demo',
25576 * template: `
25577 * <h2>Demo: NgZone</h2>
25578 *
25579 * <p>Progress: {{progress}}%</p>
25580 * <p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p>
25581 *
25582 * <button (click)="processWithinAngularZone()">Process within Angular zone</button>
25583 * <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
25584 * `,
25585 * })
25586 * export class NgZoneDemo {
25587 * progress: number = 0;
25588 * label: string;
25589 *
25590 * constructor(private _ngZone: NgZone) {}
25591 *
25592 * // Loop inside the Angular zone
25593 * // so the UI DOES refresh after each setTimeout cycle
25594 * processWithinAngularZone() {
25595 * this.label = 'inside';
25596 * this.progress = 0;
25597 * this._increaseProgress(() => console.log('Inside Done!'));
25598 * }
25599 *
25600 * // Loop outside of the Angular zone
25601 * // so the UI DOES NOT refresh after each setTimeout cycle
25602 * processOutsideOfAngularZone() {
25603 * this.label = 'outside';
25604 * this.progress = 0;
25605 * this._ngZone.runOutsideAngular(() => {
25606 * this._increaseProgress(() => {
25607 * // reenter the Angular zone and display done
25608 * this._ngZone.run(() => { console.log('Outside Done!'); });
25609 * });
25610 * });
25611 * }
25612 *
25613 * _increaseProgress(doneCallback: () => void) {
25614 * this.progress += 1;
25615 * console.log(`Current progress: ${this.progress}%`);
25616 *
25617 * if (this.progress < 100) {
25618 * window.setTimeout(() => this._increaseProgress(doneCallback), 10);
25619 * } else {
25620 * doneCallback();
25621 * }
25622 * }
25623 * }
25624 * ```
25625 *
25626 * @publicApi
25627 */
25628class NgZone {
25629 constructor({ enableLongStackTrace = false, shouldCoalesceEventChangeDetection = false, shouldCoalesceRunChangeDetection = false }) {
25630 this.hasPendingMacrotasks = false;
25631 this.hasPendingMicrotasks = false;
25632 /**
25633 * Whether there are no outstanding microtasks or macrotasks.
25634 */
25635 this.isStable = true;
25636 /**
25637 * Notifies when code enters Angular Zone. This gets fired first on VM Turn.
25638 */
25639 this.onUnstable = new EventEmitter(false);
25640 /**
25641 * Notifies when there is no more microtasks enqueued in the current VM Turn.
25642 * This is a hint for Angular to do change detection, which may enqueue more microtasks.
25643 * For this reason this event can fire multiple times per VM Turn.
25644 */
25645 this.onMicrotaskEmpty = new EventEmitter(false);
25646 /**
25647 * Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
25648 * implies we are about to relinquish VM turn.
25649 * This event gets called just once.
25650 */
25651 this.onStable = new EventEmitter(false);
25652 /**
25653 * Notifies that an error has been delivered.
25654 */
25655 this.onError = new EventEmitter(false);
25656 if (typeof Zone == 'undefined') {
25657 throw new Error(`In this configuration Angular requires Zone.js`);
25658 }
25659 Zone.assertZonePatched();
25660 const self = this;
25661 self._nesting = 0;
25662 self._outer = self._inner = Zone.current;
25663 if (Zone['TaskTrackingZoneSpec']) {
25664 self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']);
25665 }
25666 if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
25667 self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
25668 }
25669 // if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be
25670 // coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.
25671 self.shouldCoalesceEventChangeDetection =
25672 !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
25673 self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
25674 self.lastRequestAnimationFrameId = -1;
25675 self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
25676 forkInnerZoneWithAngularBehavior(self);
25677 }
25678 static isInAngularZone() {
25679 return Zone.current.get('isAngularZone') === true;
25680 }
25681 static assertInAngularZone() {
25682 if (!NgZone.isInAngularZone()) {
25683 throw new Error('Expected to be in Angular Zone, but it is not!');
25684 }
25685 }
25686 static assertNotInAngularZone() {
25687 if (NgZone.isInAngularZone()) {
25688 throw new Error('Expected to not be in Angular Zone, but it is!');
25689 }
25690 }
25691 /**
25692 * Executes the `fn` function synchronously within the Angular zone and returns value returned by
25693 * the function.
25694 *
25695 * Running functions via `run` allows you to reenter Angular zone from a task that was executed
25696 * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
25697 *
25698 * Any future tasks or microtasks scheduled from within this function will continue executing from
25699 * within the Angular zone.
25700 *
25701 * If a synchronous error happens it will be rethrown and not reported via `onError`.
25702 */
25703 run(fn, applyThis, applyArgs) {
25704 return this._inner.run(fn, applyThis, applyArgs);
25705 }
25706 /**
25707 * Executes the `fn` function synchronously within the Angular zone as a task and returns value
25708 * returned by the function.
25709 *
25710 * Running functions via `run` allows you to reenter Angular zone from a task that was executed
25711 * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
25712 *
25713 * Any future tasks or microtasks scheduled from within this function will continue executing from
25714 * within the Angular zone.
25715 *
25716 * If a synchronous error happens it will be rethrown and not reported via `onError`.
25717 */
25718 runTask(fn, applyThis, applyArgs, name) {
25719 const zone = this._inner;
25720 const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);
25721 try {
25722 return zone.runTask(task, applyThis, applyArgs);
25723 }
25724 finally {
25725 zone.cancelTask(task);
25726 }
25727 }
25728 /**
25729 * Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
25730 * rethrown.
25731 */
25732 runGuarded(fn, applyThis, applyArgs) {
25733 return this._inner.runGuarded(fn, applyThis, applyArgs);
25734 }
25735 /**
25736 * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
25737 * the function.
25738 *
25739 * Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do
25740 * work that
25741 * doesn't trigger Angular change-detection or is subject to Angular's error handling.
25742 *
25743 * Any future tasks or microtasks scheduled from within this function will continue executing from
25744 * outside of the Angular zone.
25745 *
25746 * Use {@link #run} to reenter the Angular zone and do work that updates the application model.
25747 */
25748 runOutsideAngular(fn) {
25749 return this._outer.run(fn);
25750 }
25751}
25752const EMPTY_PAYLOAD = {};
25753function checkStable(zone) {
25754 // TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent
25755 // re-entry. The case is:
25756 //
25757 // @Component({...})
25758 // export class AppComponent {
25759 // constructor(private ngZone: NgZone) {
25760 // this.ngZone.onStable.subscribe(() => {
25761 // this.ngZone.run(() => console.log('stable'););
25762 // });
25763 // }
25764 //
25765 // The onStable subscriber run another function inside ngZone
25766 // which causes `checkStable()` re-entry.
25767 // But this fix causes some issues in g3, so this fix will be
25768 // launched in another PR.
25769 if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
25770 try {
25771 zone._nesting++;
25772 zone.onMicrotaskEmpty.emit(null);
25773 }
25774 finally {
25775 zone._nesting--;
25776 if (!zone.hasPendingMicrotasks) {
25777 try {
25778 zone.runOutsideAngular(() => zone.onStable.emit(null));
25779 }
25780 finally {
25781 zone.isStable = true;
25782 }
25783 }
25784 }
25785 }
25786}
25787function delayChangeDetectionForEvents(zone) {
25788 /**
25789 * We also need to check _nesting here
25790 * Consider the following case with shouldCoalesceRunChangeDetection = true
25791 *
25792 * ngZone.run(() => {});
25793 * ngZone.run(() => {});
25794 *
25795 * We want the two `ngZone.run()` only trigger one change detection
25796 * when shouldCoalesceRunChangeDetection is true.
25797 * And because in this case, change detection run in async way(requestAnimationFrame),
25798 * so we also need to check the _nesting here to prevent multiple
25799 * change detections.
25800 */
25801 if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
25802 return;
25803 }
25804 zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => {
25805 // This is a work around for https://github.com/angular/angular/issues/36839.
25806 // The core issue is that when event coalescing is enabled it is possible for microtasks
25807 // to get flushed too early (As is the case with `Promise.then`) between the
25808 // coalescing eventTasks.
25809 //
25810 // To workaround this we schedule a "fake" eventTask before we process the
25811 // coalescing eventTasks. The benefit of this is that the "fake" container eventTask
25812 // will prevent the microtasks queue from getting drained in between the coalescing
25813 // eventTask execution.
25814 if (!zone.fakeTopEventTask) {
25815 zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
25816 zone.lastRequestAnimationFrameId = -1;
25817 updateMicroTaskStatus(zone);
25818 zone.isCheckStableRunning = true;
25819 checkStable(zone);
25820 zone.isCheckStableRunning = false;
25821 }, undefined, () => { }, () => { });
25822 }
25823 zone.fakeTopEventTask.invoke();
25824 });
25825 updateMicroTaskStatus(zone);
25826}
25827function forkInnerZoneWithAngularBehavior(zone) {
25828 const delayChangeDetectionForEventsDelegate = () => {
25829 delayChangeDetectionForEvents(zone);
25830 };
25831 zone._inner = zone._inner.fork({
25832 name: 'angular',
25833 properties: { 'isAngularZone': true },
25834 onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
25835 try {
25836 onEnter(zone);
25837 return delegate.invokeTask(target, task, applyThis, applyArgs);
25838 }
25839 finally {
25840 if ((zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask') ||
25841 zone.shouldCoalesceRunChangeDetection) {
25842 delayChangeDetectionForEventsDelegate();
25843 }
25844 onLeave(zone);
25845 }
25846 },
25847 onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => {
25848 try {
25849 onEnter(zone);
25850 return delegate.invoke(target, callback, applyThis, applyArgs, source);
25851 }
25852 finally {
25853 if (zone.shouldCoalesceRunChangeDetection) {
25854 delayChangeDetectionForEventsDelegate();
25855 }
25856 onLeave(zone);
25857 }
25858 },
25859 onHasTask: (delegate, current, target, hasTaskState) => {
25860 delegate.hasTask(target, hasTaskState);
25861 if (current === target) {
25862 // We are only interested in hasTask events which originate from our zone
25863 // (A child hasTask event is not interesting to us)
25864 if (hasTaskState.change == 'microTask') {
25865 zone._hasPendingMicrotasks = hasTaskState.microTask;
25866 updateMicroTaskStatus(zone);
25867 checkStable(zone);
25868 }
25869 else if (hasTaskState.change == 'macroTask') {
25870 zone.hasPendingMacrotasks = hasTaskState.macroTask;
25871 }
25872 }
25873 },
25874 onHandleError: (delegate, current, target, error) => {
25875 delegate.handleError(target, error);
25876 zone.runOutsideAngular(() => zone.onError.emit(error));
25877 return false;
25878 }
25879 });
25880}
25881function updateMicroTaskStatus(zone) {
25882 if (zone._hasPendingMicrotasks ||
25883 ((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&
25884 zone.lastRequestAnimationFrameId !== -1)) {
25885 zone.hasPendingMicrotasks = true;
25886 }
25887 else {
25888 zone.hasPendingMicrotasks = false;
25889 }
25890}
25891function onEnter(zone) {
25892 zone._nesting++;
25893 if (zone.isStable) {
25894 zone.isStable = false;
25895 zone.onUnstable.emit(null);
25896 }
25897}
25898function onLeave(zone) {
25899 zone._nesting--;
25900 checkStable(zone);
25901}
25902/**
25903 * Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls
25904 * to framework to perform rendering.
25905 */
25906class NoopNgZone {
25907 constructor() {
25908 this.hasPendingMicrotasks = false;
25909 this.hasPendingMacrotasks = false;
25910 this.isStable = true;
25911 this.onUnstable = new EventEmitter();
25912 this.onMicrotaskEmpty = new EventEmitter();
25913 this.onStable = new EventEmitter();
25914 this.onError = new EventEmitter();
25915 }
25916 run(fn, applyThis, applyArgs) {
25917 return fn.apply(applyThis, applyArgs);
25918 }
25919 runGuarded(fn, applyThis, applyArgs) {
25920 return fn.apply(applyThis, applyArgs);
25921 }
25922 runOutsideAngular(fn) {
25923 return fn();
25924 }
25925 runTask(fn, applyThis, applyArgs, name) {
25926 return fn.apply(applyThis, applyArgs);
25927 }
25928}
25929
25930/**
25931 * @license
25932 * Copyright Google LLC All Rights Reserved.
25933 *
25934 * Use of this source code is governed by an MIT-style license that can be
25935 * found in the LICENSE file at https://angular.io/license
25936 */
25937/**
25938 * The Testability service provides testing hooks that can be accessed from
25939 * the browser. Each bootstrapped Angular application on the page will have
25940 * an instance of Testability.
25941 * @publicApi
25942 */
25943class Testability {
25944 constructor(_ngZone) {
25945 this._ngZone = _ngZone;
25946 this._pendingCount = 0;
25947 this._isZoneStable = true;
25948 /**
25949 * Whether any work was done since the last 'whenStable' callback. This is
25950 * useful to detect if this could have potentially destabilized another
25951 * component while it is stabilizing.
25952 * @internal
25953 */
25954 this._didWork = false;
25955 this._callbacks = [];
25956 this.taskTrackingZone = null;
25957 this._watchAngularEvents();
25958 _ngZone.run(() => {
25959 this.taskTrackingZone =
25960 typeof Zone == 'undefined' ? null : Zone.current.get('TaskTrackingZone');
25961 });
25962 }
25963 _watchAngularEvents() {
25964 this._ngZone.onUnstable.subscribe({
25965 next: () => {
25966 this._didWork = true;
25967 this._isZoneStable = false;
25968 }
25969 });
25970 this._ngZone.runOutsideAngular(() => {
25971 this._ngZone.onStable.subscribe({
25972 next: () => {
25973 NgZone.assertNotInAngularZone();
25974 scheduleMicroTask(() => {
25975 this._isZoneStable = true;
25976 this._runCallbacksIfReady();
25977 });
25978 }
25979 });
25980 });
25981 }
25982 /**
25983 * Increases the number of pending request
25984 * @deprecated pending requests are now tracked with zones.
25985 */
25986 increasePendingRequestCount() {
25987 this._pendingCount += 1;
25988 this._didWork = true;
25989 return this._pendingCount;
25990 }
25991 /**
25992 * Decreases the number of pending request
25993 * @deprecated pending requests are now tracked with zones
25994 */
25995 decreasePendingRequestCount() {
25996 this._pendingCount -= 1;
25997 if (this._pendingCount < 0) {
25998 throw new Error('pending async requests below zero');
25999 }
26000 this._runCallbacksIfReady();
26001 return this._pendingCount;
26002 }
26003 /**
26004 * Whether an associated application is stable
26005 */
26006 isStable() {
26007 return this._isZoneStable && this._pendingCount === 0 && !this._ngZone.hasPendingMacrotasks;
26008 }
26009 _runCallbacksIfReady() {
26010 if (this.isStable()) {
26011 // Schedules the call backs in a new frame so that it is always async.
26012 scheduleMicroTask(() => {
26013 while (this._callbacks.length !== 0) {
26014 let cb = this._callbacks.pop();
26015 clearTimeout(cb.timeoutId);
26016 cb.doneCb(this._didWork);
26017 }
26018 this._didWork = false;
26019 });
26020 }
26021 else {
26022 // Still not stable, send updates.
26023 let pending = this.getPendingTasks();
26024 this._callbacks = this._callbacks.filter((cb) => {
26025 if (cb.updateCb && cb.updateCb(pending)) {
26026 clearTimeout(cb.timeoutId);
26027 return false;
26028 }
26029 return true;
26030 });
26031 this._didWork = true;
26032 }
26033 }
26034 getPendingTasks() {
26035 if (!this.taskTrackingZone) {
26036 return [];
26037 }
26038 // Copy the tasks data so that we don't leak tasks.
26039 return this.taskTrackingZone.macroTasks.map((t) => {
26040 return {
26041 source: t.source,
26042 // From TaskTrackingZone:
26043 // https://github.com/angular/zone.js/blob/master/lib/zone-spec/task-tracking.ts#L40
26044 creationLocation: t.creationLocation,
26045 data: t.data
26046 };
26047 });
26048 }
26049 addCallback(cb, timeout, updateCb) {
26050 let timeoutId = -1;
26051 if (timeout && timeout > 0) {
26052 timeoutId = setTimeout(() => {
26053 this._callbacks = this._callbacks.filter((cb) => cb.timeoutId !== timeoutId);
26054 cb(this._didWork, this.getPendingTasks());
26055 }, timeout);
26056 }
26057 this._callbacks.push({ doneCb: cb, timeoutId: timeoutId, updateCb: updateCb });
26058 }
26059 /**
26060 * Wait for the application to be stable with a timeout. If the timeout is reached before that
26061 * happens, the callback receives a list of the macro tasks that were pending, otherwise null.
26062 *
26063 * @param doneCb The callback to invoke when Angular is stable or the timeout expires
26064 * whichever comes first.
26065 * @param timeout Optional. The maximum time to wait for Angular to become stable. If not
26066 * specified, whenStable() will wait forever.
26067 * @param updateCb Optional. If specified, this callback will be invoked whenever the set of
26068 * pending macrotasks changes. If this callback returns true doneCb will not be invoked
26069 * and no further updates will be issued.
26070 */
26071 whenStable(doneCb, timeout, updateCb) {
26072 if (updateCb && !this.taskTrackingZone) {
26073 throw new Error('Task tracking zone is required when passing an update callback to ' +
26074 'whenStable(). Is "zone.js/plugins/task-tracking" loaded?');
26075 }
26076 // These arguments are 'Function' above to keep the public API simple.
26077 this.addCallback(doneCb, timeout, updateCb);
26078 this._runCallbacksIfReady();
26079 }
26080 /**
26081 * Get the number of pending requests
26082 * @deprecated pending requests are now tracked with zones
26083 */
26084 getPendingRequestCount() {
26085 return this._pendingCount;
26086 }
26087 /**
26088 * Find providers by name
26089 * @param using The root element to search from
26090 * @param provider The name of binding variable
26091 * @param exactMatch Whether using exactMatch
26092 */
26093 findProviders(using, provider, exactMatch) {
26094 // TODO(juliemr): implement.
26095 return [];
26096 }
26097}
26098Testability.ɵfac = function Testability_Factory(t) { return new (t || Testability)(ɵɵinject(NgZone)); };
26099Testability.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Testability, factory: Testability.ɵfac });
26100(function () {
26101 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Testability, [{
26102 type: Injectable
26103 }], function () { return [{ type: NgZone }]; }, null);
26104})();
26105/**
26106 * A global registry of {@link Testability} instances for specific elements.
26107 * @publicApi
26108 */
26109class TestabilityRegistry {
26110 constructor() {
26111 /** @internal */
26112 this._applications = new Map();
26113 _testabilityGetter.addToWindow(this);
26114 }
26115 /**
26116 * Registers an application with a testability hook so that it can be tracked
26117 * @param token token of application, root element
26118 * @param testability Testability hook
26119 */
26120 registerApplication(token, testability) {
26121 this._applications.set(token, testability);
26122 }
26123 /**
26124 * Unregisters an application.
26125 * @param token token of application, root element
26126 */
26127 unregisterApplication(token) {
26128 this._applications.delete(token);
26129 }
26130 /**
26131 * Unregisters all applications
26132 */
26133 unregisterAllApplications() {
26134 this._applications.clear();
26135 }
26136 /**
26137 * Get a testability hook associated with the application
26138 * @param elem root element
26139 */
26140 getTestability(elem) {
26141 return this._applications.get(elem) || null;
26142 }
26143 /**
26144 * Get all registered testabilities
26145 */
26146 getAllTestabilities() {
26147 return Array.from(this._applications.values());
26148 }
26149 /**
26150 * Get all registered applications(root elements)
26151 */
26152 getAllRootElements() {
26153 return Array.from(this._applications.keys());
26154 }
26155 /**
26156 * Find testability of a node in the Tree
26157 * @param elem node
26158 * @param findInAncestors whether finding testability in ancestors if testability was not found in
26159 * current node
26160 */
26161 findTestabilityInTree(elem, findInAncestors = true) {
26162 return _testabilityGetter.findTestabilityInTree(this, elem, findInAncestors);
26163 }
26164}
26165TestabilityRegistry.ɵfac = function TestabilityRegistry_Factory(t) { return new (t || TestabilityRegistry)(); };
26166TestabilityRegistry.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: TestabilityRegistry, factory: TestabilityRegistry.ɵfac });
26167(function () {
26168 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(TestabilityRegistry, [{
26169 type: Injectable
26170 }], function () { return []; }, null);
26171})();
26172class _NoopGetTestability {
26173 addToWindow(registry) { }
26174 findTestabilityInTree(registry, elem, findInAncestors) {
26175 return null;
26176 }
26177}
26178/**
26179 * Set the {@link GetTestability} implementation used by the Angular testing framework.
26180 * @publicApi
26181 */
26182function setTestabilityGetter(getter) {
26183 _testabilityGetter = getter;
26184}
26185let _testabilityGetter = new _NoopGetTestability();
26186
26187/**
26188 * @license
26189 * Copyright Google LLC All Rights Reserved.
26190 *
26191 * Use of this source code is governed by an MIT-style license that can be
26192 * found in the LICENSE file at https://angular.io/license
26193 */
26194/**
26195 * This file is used to control if the default rendering pipeline should be `ViewEngine` or `Ivy`.
26196 *
26197 * For more information on how to run and debug tests with either Ivy or View Engine (legacy),
26198 * please see [BAZEL.md](./docs/BAZEL.md).
26199 */
26200let _devMode = true;
26201let _runModeLocked = false;
26202/**
26203 * Returns whether Angular is in development mode. After called once,
26204 * the value is locked and won't change any more.
26205 *
26206 * By default, this is true, unless a user calls `enableProdMode` before calling this.
26207 *
26208 * @publicApi
26209 */
26210function isDevMode() {
26211 _runModeLocked = true;
26212 return _devMode;
26213}
26214/**
26215 * Disable Angular's development mode, which turns off assertions and other
26216 * checks within the framework.
26217 *
26218 * One important assertion this disables verifies that a change detection pass
26219 * does not result in additional changes to any bindings (also known as
26220 * unidirectional data flow).
26221 *
26222 * @publicApi
26223 */
26224function enableProdMode() {
26225 if (_runModeLocked) {
26226 throw new Error('Cannot enable prod mode after platform setup.');
26227 }
26228 // The below check is there so when ngDevMode is set via terser
26229 // `global['ngDevMode'] = false;` is also dropped.
26230 if (typeof ngDevMode === undefined || !!ngDevMode) {
26231 _global['ngDevMode'] = false;
26232 }
26233 _devMode = false;
26234}
26235
26236/**
26237 * @license
26238 * Copyright Google LLC All Rights Reserved.
26239 *
26240 * Use of this source code is governed by an MIT-style license that can be
26241 * found in the LICENSE file at https://angular.io/license
26242 */
26243let _platform;
26244let compileNgModuleFactory = compileNgModuleFactory__POST_R3__;
26245function compileNgModuleFactory__PRE_R3__(injector, options, moduleType) {
26246 const compilerFactory = injector.get(CompilerFactory);
26247 const compiler = compilerFactory.createCompiler([options]);
26248 return compiler.compileModuleAsync(moduleType);
26249}
26250function compileNgModuleFactory__POST_R3__(injector, options, moduleType) {
26251 ngDevMode && assertNgModuleType(moduleType);
26252 const moduleFactory = new NgModuleFactory(moduleType);
26253 // All of the logic below is irrelevant for AOT-compiled code.
26254 if (typeof ngJitMode !== 'undefined' && !ngJitMode) {
26255 return Promise.resolve(moduleFactory);
26256 }
26257 const compilerOptions = injector.get(COMPILER_OPTIONS, []).concat(options);
26258 // Configure the compiler to use the provided options. This call may fail when multiple modules
26259 // are bootstrapped with incompatible options, as a component can only be compiled according to
26260 // a single set of options.
26261 setJitOptions({
26262 defaultEncapsulation: _lastDefined(compilerOptions.map(opts => opts.defaultEncapsulation)),
26263 preserveWhitespaces: _lastDefined(compilerOptions.map(opts => opts.preserveWhitespaces)),
26264 });
26265 if (isComponentResourceResolutionQueueEmpty()) {
26266 return Promise.resolve(moduleFactory);
26267 }
26268 const compilerProviders = _mergeArrays(compilerOptions.map(o => o.providers));
26269 // In case there are no compiler providers, we just return the module factory as
26270 // there won't be any resource loader. This can happen with Ivy, because AOT compiled
26271 // modules can be still passed through "bootstrapModule". In that case we shouldn't
26272 // unnecessarily require the JIT compiler.
26273 if (compilerProviders.length === 0) {
26274 return Promise.resolve(moduleFactory);
26275 }
26276 const compiler = getCompilerFacade({
26277 usage: 0 /* Decorator */,
26278 kind: 'NgModule',
26279 type: moduleType,
26280 });
26281 const compilerInjector = Injector.create({ providers: compilerProviders });
26282 const resourceLoader = compilerInjector.get(compiler.ResourceLoader);
26283 // The resource loader can also return a string while the "resolveComponentResources"
26284 // always expects a promise. Therefore we need to wrap the returned value in a promise.
26285 return resolveComponentResources(url => Promise.resolve(resourceLoader.get(url)))
26286 .then(() => moduleFactory);
26287}
26288// the `window.ng` global utilities are only available in non-VE versions of
26289// Angular. The function switch below will make sure that the code is not
26290// included into Angular when PRE mode is active.
26291function publishDefaultGlobalUtils__PRE_R3__() { }
26292function publishDefaultGlobalUtils__POST_R3__() {
26293 ngDevMode && publishDefaultGlobalUtils$1();
26294}
26295let publishDefaultGlobalUtils = publishDefaultGlobalUtils__POST_R3__;
26296let isBoundToModule = isBoundToModule__POST_R3__;
26297function isBoundToModule__PRE_R3__(cf) {
26298 return cf instanceof ComponentFactoryBoundToModule;
26299}
26300function isBoundToModule__POST_R3__(cf) {
26301 return cf.isBoundToModule;
26302}
26303const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken');
26304/**
26305 * A token for third-party components that can register themselves with NgProbe.
26306 *
26307 * @publicApi
26308 */
26309class NgProbeToken {
26310 constructor(name, token) {
26311 this.name = name;
26312 this.token = token;
26313 }
26314}
26315/**
26316 * Creates a platform.
26317 * Platforms must be created on launch using this function.
26318 *
26319 * @publicApi
26320 */
26321function createPlatform(injector) {
26322 if (_platform && !_platform.destroyed &&
26323 !_platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
26324 throw new Error('There can be only one platform. Destroy the previous one to create a new one.');
26325 }
26326 publishDefaultGlobalUtils();
26327 _platform = injector.get(PlatformRef);
26328 const inits = injector.get(PLATFORM_INITIALIZER, null);
26329 if (inits)
26330 inits.forEach((init) => init());
26331 return _platform;
26332}
26333/**
26334 * Creates a factory for a platform. Can be used to provide or override `Providers` specific to
26335 * your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
26336 * @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
26337 * to build up configurations that might be required by different libraries or parts of the
26338 * application.
26339 * @param name Identifies the new platform factory.
26340 * @param providers A set of dependency providers for platforms created with the new factory.
26341 *
26342 * @publicApi
26343 */
26344function createPlatformFactory(parentPlatformFactory, name, providers = []) {
26345 const desc = `Platform: ${name}`;
26346 const marker = new InjectionToken(desc);
26347 return (extraProviders = []) => {
26348 let platform = getPlatform();
26349 if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
26350 if (parentPlatformFactory) {
26351 parentPlatformFactory(providers.concat(extraProviders).concat({ provide: marker, useValue: true }));
26352 }
26353 else {
26354 const injectedProviders = providers.concat(extraProviders).concat({ provide: marker, useValue: true }, {
26355 provide: INJECTOR_SCOPE,
26356 useValue: 'platform'
26357 });
26358 createPlatform(Injector.create({ providers: injectedProviders, name: desc }));
26359 }
26360 }
26361 return assertPlatform(marker);
26362 };
26363}
26364/**
26365 * Checks that there is currently a platform that contains the given token as a provider.
26366 *
26367 * @publicApi
26368 */
26369function assertPlatform(requiredToken) {
26370 const platform = getPlatform();
26371 if (!platform) {
26372 throw new Error('No platform exists!');
26373 }
26374 if (!platform.injector.get(requiredToken, null)) {
26375 throw new Error('A platform with a different configuration has been created. Please destroy it first.');
26376 }
26377 return platform;
26378}
26379/**
26380 * Destroys the current Angular platform and all Angular applications on the page.
26381 * Destroys all modules and listeners registered with the platform.
26382 *
26383 * @publicApi
26384 */
26385function destroyPlatform() {
26386 if (_platform && !_platform.destroyed) {
26387 _platform.destroy();
26388 }
26389}
26390/**
26391 * Returns the current platform.
26392 *
26393 * @publicApi
26394 */
26395function getPlatform() {
26396 return _platform && !_platform.destroyed ? _platform : null;
26397}
26398/**
26399 * The Angular platform is the entry point for Angular on a web page.
26400 * Each page has exactly one platform. Services (such as reflection) which are common
26401 * to every Angular application running on the page are bound in its scope.
26402 * A page's platform is initialized implicitly when a platform is created using a platform
26403 * factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.
26404 *
26405 * @publicApi
26406 */
26407class PlatformRef {
26408 /** @internal */
26409 constructor(_injector) {
26410 this._injector = _injector;
26411 this._modules = [];
26412 this._destroyListeners = [];
26413 this._destroyed = false;
26414 }
26415 /**
26416 * Creates an instance of an `@NgModule` for the given platform for offline compilation.
26417 *
26418 * @usageNotes
26419 *
26420 * The following example creates the NgModule for a browser platform.
26421 *
26422 * ```typescript
26423 * my_module.ts:
26424 *
26425 * @NgModule({
26426 * imports: [BrowserModule]
26427 * })
26428 * class MyModule {}
26429 *
26430 * main.ts:
26431 * import {MyModuleNgFactory} from './my_module.ngfactory';
26432 * import {platformBrowser} from '@angular/platform-browser';
26433 *
26434 * let moduleRef = platformBrowser().bootstrapModuleFactory(MyModuleNgFactory);
26435 * ```
26436 *
26437 * @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function
26438 * argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.
26439 */
26440 bootstrapModuleFactory(moduleFactory, options) {
26441 // Note: We need to create the NgZone _before_ we instantiate the module,
26442 // as instantiating the module creates some providers eagerly.
26443 // So we create a mini parent injector that just contains the new NgZone and
26444 // pass that as parent to the NgModuleFactory.
26445 const ngZoneOption = options ? options.ngZone : undefined;
26446 const ngZoneEventCoalescing = (options && options.ngZoneEventCoalescing) || false;
26447 const ngZoneRunCoalescing = (options && options.ngZoneRunCoalescing) || false;
26448 const ngZone = getNgZone(ngZoneOption, { ngZoneEventCoalescing, ngZoneRunCoalescing });
26449 const providers = [{ provide: NgZone, useValue: ngZone }];
26450 // Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
26451 // created within the Angular zone
26452 // Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
26453 // created outside of the Angular zone.
26454 return ngZone.run(() => {
26455 const ngZoneInjector = Injector.create({ providers: providers, parent: this.injector, name: moduleFactory.moduleType.name });
26456 const moduleRef = moduleFactory.create(ngZoneInjector);
26457 const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
26458 if (!exceptionHandler) {
26459 throw new Error('No ErrorHandler. Is platform module (BrowserModule) included?');
26460 }
26461 ngZone.runOutsideAngular(() => {
26462 const subscription = ngZone.onError.subscribe({
26463 next: (error) => {
26464 exceptionHandler.handleError(error);
26465 }
26466 });
26467 moduleRef.onDestroy(() => {
26468 remove(this._modules, moduleRef);
26469 subscription.unsubscribe();
26470 });
26471 });
26472 return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
26473 const initStatus = moduleRef.injector.get(ApplicationInitStatus);
26474 initStatus.runInitializers();
26475 return initStatus.donePromise.then(() => {
26476 if (ivyEnabled) {
26477 // If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
26478 const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
26479 setLocaleId(localeId || DEFAULT_LOCALE_ID);
26480 }
26481 this._moduleDoBootstrap(moduleRef);
26482 return moduleRef;
26483 });
26484 });
26485 });
26486 }
26487 /**
26488 * Creates an instance of an `@NgModule` for a given platform using the given runtime compiler.
26489 *
26490 * @usageNotes
26491 * ### Simple Example
26492 *
26493 * ```typescript
26494 * @NgModule({
26495 * imports: [BrowserModule]
26496 * })
26497 * class MyModule {}
26498 *
26499 * let moduleRef = platformBrowser().bootstrapModule(MyModule);
26500 * ```
26501 *
26502 */
26503 bootstrapModule(moduleType, compilerOptions = []) {
26504 const options = optionsReducer({}, compilerOptions);
26505 return compileNgModuleFactory(this.injector, options, moduleType)
26506 .then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
26507 }
26508 _moduleDoBootstrap(moduleRef) {
26509 const appRef = moduleRef.injector.get(ApplicationRef);
26510 if (moduleRef._bootstrapComponents.length > 0) {
26511 moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
26512 }
26513 else if (moduleRef.instance.ngDoBootstrap) {
26514 moduleRef.instance.ngDoBootstrap(appRef);
26515 }
26516 else {
26517 throw new Error(`The module ${stringify(moduleRef.instance
26518 .constructor)} was bootstrapped, but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
26519 `Please define one of these.`);
26520 }
26521 this._modules.push(moduleRef);
26522 }
26523 /**
26524 * Registers a listener to be called when the platform is destroyed.
26525 */
26526 onDestroy(callback) {
26527 this._destroyListeners.push(callback);
26528 }
26529 /**
26530 * Retrieves the platform {@link Injector}, which is the parent injector for
26531 * every Angular application on the page and provides singleton providers.
26532 */
26533 get injector() {
26534 return this._injector;
26535 }
26536 /**
26537 * Destroys the current Angular platform and all Angular applications on the page.
26538 * Destroys all modules and listeners registered with the platform.
26539 */
26540 destroy() {
26541 if (this._destroyed) {
26542 throw new Error('The platform has already been destroyed!');
26543 }
26544 this._modules.slice().forEach(module => module.destroy());
26545 this._destroyListeners.forEach(listener => listener());
26546 this._destroyed = true;
26547 }
26548 get destroyed() {
26549 return this._destroyed;
26550 }
26551}
26552PlatformRef.ɵfac = function PlatformRef_Factory(t) { return new (t || PlatformRef)(ɵɵinject(Injector)); };
26553PlatformRef.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: PlatformRef, factory: PlatformRef.ɵfac });
26554(function () {
26555 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformRef, [{
26556 type: Injectable
26557 }], function () { return [{ type: Injector }]; }, null);
26558})();
26559function getNgZone(ngZoneOption, extra) {
26560 let ngZone;
26561 if (ngZoneOption === 'noop') {
26562 ngZone = new NoopNgZone();
26563 }
26564 else {
26565 ngZone = (ngZoneOption === 'zone.js' ? undefined : ngZoneOption) || new NgZone({
26566 enableLongStackTrace: isDevMode(),
26567 shouldCoalesceEventChangeDetection: !!(extra === null || extra === void 0 ? void 0 : extra.ngZoneEventCoalescing),
26568 shouldCoalesceRunChangeDetection: !!(extra === null || extra === void 0 ? void 0 : extra.ngZoneRunCoalescing)
26569 });
26570 }
26571 return ngZone;
26572}
26573function _callAndReportToErrorHandler(errorHandler, ngZone, callback) {
26574 try {
26575 const result = callback();
26576 if (isPromise(result)) {
26577 return result.catch((e) => {
26578 ngZone.runOutsideAngular(() => errorHandler.handleError(e));
26579 // rethrow as the exception handler might not do it
26580 throw e;
26581 });
26582 }
26583 return result;
26584 }
26585 catch (e) {
26586 ngZone.runOutsideAngular(() => errorHandler.handleError(e));
26587 // rethrow as the exception handler might not do it
26588 throw e;
26589 }
26590}
26591function optionsReducer(dst, objs) {
26592 if (Array.isArray(objs)) {
26593 dst = objs.reduce(optionsReducer, dst);
26594 }
26595 else {
26596 dst = Object.assign(Object.assign({}, dst), objs);
26597 }
26598 return dst;
26599}
26600/**
26601 * A reference to an Angular application running on a page.
26602 *
26603 * @usageNotes
26604 *
26605 * {@a is-stable-examples}
26606 * ### isStable examples and caveats
26607 *
26608 * Note two important points about `isStable`, demonstrated in the examples below:
26609 * - the application will never be stable if you start any kind
26610 * of recurrent asynchronous task when the application starts
26611 * (for example for a polling process, started with a `setInterval`, a `setTimeout`
26612 * or using RxJS operators like `interval`);
26613 * - the `isStable` Observable runs outside of the Angular zone.
26614 *
26615 * Let's imagine that you start a recurrent task
26616 * (here incrementing a counter, using RxJS `interval`),
26617 * and at the same time subscribe to `isStable`.
26618 *
26619 * ```
26620 * constructor(appRef: ApplicationRef) {
26621 * appRef.isStable.pipe(
26622 * filter(stable => stable)
26623 * ).subscribe(() => console.log('App is stable now');
26624 * interval(1000).subscribe(counter => console.log(counter));
26625 * }
26626 * ```
26627 * In this example, `isStable` will never emit `true`,
26628 * and the trace "App is stable now" will never get logged.
26629 *
26630 * If you want to execute something when the app is stable,
26631 * you have to wait for the application to be stable
26632 * before starting your polling process.
26633 *
26634 * ```
26635 * constructor(appRef: ApplicationRef) {
26636 * appRef.isStable.pipe(
26637 * first(stable => stable),
26638 * tap(stable => console.log('App is stable now')),
26639 * switchMap(() => interval(1000))
26640 * ).subscribe(counter => console.log(counter));
26641 * }
26642 * ```
26643 * In this example, the trace "App is stable now" will be logged
26644 * and then the counter starts incrementing every second.
26645 *
26646 * Note also that this Observable runs outside of the Angular zone,
26647 * which means that the code in the subscription
26648 * to this Observable will not trigger the change detection.
26649 *
26650 * Let's imagine that instead of logging the counter value,
26651 * you update a field of your component
26652 * and display it in its template.
26653 *
26654 * ```
26655 * constructor(appRef: ApplicationRef) {
26656 * appRef.isStable.pipe(
26657 * first(stable => stable),
26658 * switchMap(() => interval(1000))
26659 * ).subscribe(counter => this.value = counter);
26660 * }
26661 * ```
26662 * As the `isStable` Observable runs outside the zone,
26663 * the `value` field will be updated properly,
26664 * but the template will not be refreshed!
26665 *
26666 * You'll have to manually trigger the change detection to update the template.
26667 *
26668 * ```
26669 * constructor(appRef: ApplicationRef, cd: ChangeDetectorRef) {
26670 * appRef.isStable.pipe(
26671 * first(stable => stable),
26672 * switchMap(() => interval(1000))
26673 * ).subscribe(counter => {
26674 * this.value = counter;
26675 * cd.detectChanges();
26676 * });
26677 * }
26678 * ```
26679 *
26680 * Or make the subscription callback run inside the zone.
26681 *
26682 * ```
26683 * constructor(appRef: ApplicationRef, zone: NgZone) {
26684 * appRef.isStable.pipe(
26685 * first(stable => stable),
26686 * switchMap(() => interval(1000))
26687 * ).subscribe(counter => zone.run(() => this.value = counter));
26688 * }
26689 * ```
26690 *
26691 * @publicApi
26692 */
26693class ApplicationRef {
26694 /** @internal */
26695 constructor(_zone, _injector, _exceptionHandler, _componentFactoryResolver, _initStatus) {
26696 this._zone = _zone;
26697 this._injector = _injector;
26698 this._exceptionHandler = _exceptionHandler;
26699 this._componentFactoryResolver = _componentFactoryResolver;
26700 this._initStatus = _initStatus;
26701 /** @internal */
26702 this._bootstrapListeners = [];
26703 this._views = [];
26704 this._runningTick = false;
26705 this._stable = true;
26706 /**
26707 * Get a list of component types registered to this application.
26708 * This list is populated even before the component is created.
26709 */
26710 this.componentTypes = [];
26711 /**
26712 * Get a list of components registered to this application.
26713 */
26714 this.components = [];
26715 this._onMicrotaskEmptySubscription = this._zone.onMicrotaskEmpty.subscribe({
26716 next: () => {
26717 this._zone.run(() => {
26718 this.tick();
26719 });
26720 }
26721 });
26722 const isCurrentlyStable = new Observable((observer) => {
26723 this._stable = this._zone.isStable && !this._zone.hasPendingMacrotasks &&
26724 !this._zone.hasPendingMicrotasks;
26725 this._zone.runOutsideAngular(() => {
26726 observer.next(this._stable);
26727 observer.complete();
26728 });
26729 });
26730 const isStable = new Observable((observer) => {
26731 // Create the subscription to onStable outside the Angular Zone so that
26732 // the callback is run outside the Angular Zone.
26733 let stableSub;
26734 this._zone.runOutsideAngular(() => {
26735 stableSub = this._zone.onStable.subscribe(() => {
26736 NgZone.assertNotInAngularZone();
26737 // Check whether there are no pending macro/micro tasks in the next tick
26738 // to allow for NgZone to update the state.
26739 scheduleMicroTask(() => {
26740 if (!this._stable && !this._zone.hasPendingMacrotasks &&
26741 !this._zone.hasPendingMicrotasks) {
26742 this._stable = true;
26743 observer.next(true);
26744 }
26745 });
26746 });
26747 });
26748 const unstableSub = this._zone.onUnstable.subscribe(() => {
26749 NgZone.assertInAngularZone();
26750 if (this._stable) {
26751 this._stable = false;
26752 this._zone.runOutsideAngular(() => {
26753 observer.next(false);
26754 });
26755 }
26756 });
26757 return () => {
26758 stableSub.unsubscribe();
26759 unstableSub.unsubscribe();
26760 };
26761 });
26762 this.isStable =
26763 merge$1(isCurrentlyStable, isStable.pipe(share()));
26764 }
26765 /**
26766 * Bootstrap a component onto the element identified by its selector or, optionally, to a
26767 * specified element.
26768 *
26769 * @usageNotes
26770 * ### Bootstrap process
26771 *
26772 * When bootstrapping a component, Angular mounts it onto a target DOM element
26773 * and kicks off automatic change detection. The target DOM element can be
26774 * provided using the `rootSelectorOrNode` argument.
26775 *
26776 * If the target DOM element is not provided, Angular tries to find one on a page
26777 * using the `selector` of the component that is being bootstrapped
26778 * (first matched element is used).
26779 *
26780 * ### Example
26781 *
26782 * Generally, we define the component to bootstrap in the `bootstrap` array of `NgModule`,
26783 * but it requires us to know the component while writing the application code.
26784 *
26785 * Imagine a situation where we have to wait for an API call to decide about the component to
26786 * bootstrap. We can use the `ngDoBootstrap` hook of the `NgModule` and call this method to
26787 * dynamically bootstrap a component.
26788 *
26789 * {@example core/ts/platform/platform.ts region='componentSelector'}
26790 *
26791 * Optionally, a component can be mounted onto a DOM element that does not match the
26792 * selector of the bootstrapped component.
26793 *
26794 * In the following example, we are providing a CSS selector to match the target element.
26795 *
26796 * {@example core/ts/platform/platform.ts region='cssSelector'}
26797 *
26798 * While in this example, we are providing reference to a DOM node.
26799 *
26800 * {@example core/ts/platform/platform.ts region='domNode'}
26801 */
26802 bootstrap(componentOrFactory, rootSelectorOrNode) {
26803 if (!this._initStatus.done) {
26804 throw new Error('Cannot bootstrap as there are still asynchronous initializers running. Bootstrap components in the `ngDoBootstrap` method of the root module.');
26805 }
26806 let componentFactory;
26807 if (componentOrFactory instanceof ComponentFactory$1) {
26808 componentFactory = componentOrFactory;
26809 }
26810 else {
26811 componentFactory =
26812 this._componentFactoryResolver.resolveComponentFactory(componentOrFactory);
26813 }
26814 this.componentTypes.push(componentFactory.componentType);
26815 // Create a factory associated with the current module if it's not bound to some other
26816 const ngModule = isBoundToModule(componentFactory) ? undefined : this._injector.get(NgModuleRef$1);
26817 const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
26818 const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
26819 const nativeElement = compRef.location.nativeElement;
26820 const testability = compRef.injector.get(Testability, null);
26821 const testabilityRegistry = testability && compRef.injector.get(TestabilityRegistry);
26822 if (testability && testabilityRegistry) {
26823 testabilityRegistry.registerApplication(nativeElement, testability);
26824 }
26825 compRef.onDestroy(() => {
26826 this.detachView(compRef.hostView);
26827 remove(this.components, compRef);
26828 if (testabilityRegistry) {
26829 testabilityRegistry.unregisterApplication(nativeElement);
26830 }
26831 });
26832 this._loadComponent(compRef);
26833 // Note that we have still left the `isDevMode()` condition in order to avoid
26834 // creating a breaking change for projects that still use the View Engine.
26835 if ((typeof ngDevMode === 'undefined' || ngDevMode) && isDevMode()) {
26836 const _console = this._injector.get(Console);
26837 _console.log(`Angular is running in development mode. Call enableProdMode() to enable production mode.`);
26838 }
26839 return compRef;
26840 }
26841 /**
26842 * Invoke this method to explicitly process change detection and its side-effects.
26843 *
26844 * In development mode, `tick()` also performs a second change detection cycle to ensure that no
26845 * further changes are detected. If additional changes are picked up during this second cycle,
26846 * bindings in the app have side-effects that cannot be resolved in a single change detection
26847 * pass.
26848 * In this case, Angular throws an error, since an Angular application can only have one change
26849 * detection pass during which all change detection must complete.
26850 */
26851 tick() {
26852 if (this._runningTick) {
26853 throw new Error('ApplicationRef.tick is called recursively');
26854 }
26855 try {
26856 this._runningTick = true;
26857 for (let view of this._views) {
26858 view.detectChanges();
26859 }
26860 // Note that we have still left the `isDevMode()` condition in order to avoid
26861 // creating a breaking change for projects that still use the View Engine.
26862 if ((typeof ngDevMode === 'undefined' || ngDevMode) && isDevMode()) {
26863 for (let view of this._views) {
26864 view.checkNoChanges();
26865 }
26866 }
26867 }
26868 catch (e) {
26869 // Attention: Don't rethrow as it could cancel subscriptions to Observables!
26870 this._zone.runOutsideAngular(() => this._exceptionHandler.handleError(e));
26871 }
26872 finally {
26873 this._runningTick = false;
26874 }
26875 }
26876 /**
26877 * Attaches a view so that it will be dirty checked.
26878 * The view will be automatically detached when it is destroyed.
26879 * This will throw if the view is already attached to a ViewContainer.
26880 */
26881 attachView(viewRef) {
26882 const view = viewRef;
26883 this._views.push(view);
26884 view.attachToAppRef(this);
26885 }
26886 /**
26887 * Detaches a view from dirty checking again.
26888 */
26889 detachView(viewRef) {
26890 const view = viewRef;
26891 remove(this._views, view);
26892 view.detachFromAppRef();
26893 }
26894 _loadComponent(componentRef) {
26895 this.attachView(componentRef.hostView);
26896 this.tick();
26897 this.components.push(componentRef);
26898 // Get the listeners lazily to prevent DI cycles.
26899 const listeners = this._injector.get(APP_BOOTSTRAP_LISTENER, []).concat(this._bootstrapListeners);
26900 listeners.forEach((listener) => listener(componentRef));
26901 }
26902 /** @internal */
26903 ngOnDestroy() {
26904 this._views.slice().forEach((view) => view.destroy());
26905 this._onMicrotaskEmptySubscription.unsubscribe();
26906 }
26907 /**
26908 * Returns the number of attached views.
26909 */
26910 get viewCount() {
26911 return this._views.length;
26912 }
26913}
26914ApplicationRef.ɵfac = function ApplicationRef_Factory(t) { return new (t || ApplicationRef)(ɵɵinject(NgZone), ɵɵinject(Injector), ɵɵinject(ErrorHandler), ɵɵinject(ComponentFactoryResolver$1), ɵɵinject(ApplicationInitStatus)); };
26915ApplicationRef.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationRef, factory: ApplicationRef.ɵfac });
26916(function () {
26917 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationRef, [{
26918 type: Injectable
26919 }], function () { return [{ type: NgZone }, { type: Injector }, { type: ErrorHandler }, { type: ComponentFactoryResolver$1 }, { type: ApplicationInitStatus }]; }, null);
26920})();
26921function remove(list, el) {
26922 const index = list.indexOf(el);
26923 if (index > -1) {
26924 list.splice(index, 1);
26925 }
26926}
26927function _lastDefined(args) {
26928 for (let i = args.length - 1; i >= 0; i--) {
26929 if (args[i] !== undefined) {
26930 return args[i];
26931 }
26932 }
26933 return undefined;
26934}
26935function _mergeArrays(parts) {
26936 const result = [];
26937 parts.forEach((part) => part && result.push(...part));
26938 return result;
26939}
26940
26941/**
26942 * @license
26943 * Copyright Google LLC All Rights Reserved.
26944 *
26945 * Use of this source code is governed by an MIT-style license that can be
26946 * found in the LICENSE file at https://angular.io/license
26947 */
26948
26949/**
26950 * @license
26951 * Copyright Google LLC All Rights Reserved.
26952 *
26953 * Use of this source code is governed by an MIT-style license that can be
26954 * found in the LICENSE file at https://angular.io/license
26955 */
26956
26957function getModuleFactory__PRE_R3__(id) {
26958 const factory = getRegisteredNgModuleType(id);
26959 if (!factory)
26960 throw noModuleError(id);
26961 return factory;
26962}
26963function getModuleFactory__POST_R3__(id) {
26964 const type = getRegisteredNgModuleType(id);
26965 if (!type)
26966 throw noModuleError(id);
26967 return new NgModuleFactory(type);
26968}
26969function getNgModuleById__PRE_R3__(id) {
26970 throw new Error(`ViewEngine doesn't support retrieving NgModule classes by id`);
26971}
26972function getNgModuleById__POST_R3__(id) {
26973 const type = getRegisteredNgModuleType(id);
26974 if (!type)
26975 throw noModuleError(id);
26976 return type;
26977}
26978/**
26979 * Returns the NgModuleFactory with the given id (specified using [@NgModule.id
26980 * field](api/core/NgModule#id)), if it exists and has been loaded. Factories for NgModules that do
26981 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
26982 * @publicApi
26983 * @deprecated Use `getNgModuleById` instead.
26984 */
26985const getModuleFactory = getModuleFactory__POST_R3__;
26986/**
26987 * Returns the NgModule class with the given id (specified using [@NgModule.id
26988 * field](api/core/NgModule#id)), if it exists and has been loaded. Classes for NgModules that do
26989 * not specify an `id` cannot be retrieved. Throws if an NgModule cannot be found.
26990 * @publicApi
26991 */
26992const getNgModuleById = getNgModuleById__POST_R3__;
26993function noModuleError(id) {
26994 return new Error(`No module with ID ${id} loaded`);
26995}
26996
26997const SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__ = injectChangeDetectorRef;
26998const SWITCH_CHANGE_DETECTOR_REF_FACTORY__PRE_R3__ = noop;
26999const SWITCH_CHANGE_DETECTOR_REF_FACTORY = SWITCH_CHANGE_DETECTOR_REF_FACTORY__POST_R3__;
27000/**
27001 * Base class that provides change detection functionality.
27002 * A change-detection tree collects all views that are to be checked for changes.
27003 * Use the methods to add and remove views from the tree, initiate change-detection,
27004 * and explicitly mark views as _dirty_, meaning that they have changed and need to be re-rendered.
27005 *
27006 * @see [Using change detection hooks](guide/lifecycle-hooks#using-change-detection-hooks)
27007 * @see [Defining custom change detection](guide/lifecycle-hooks#defining-custom-change-detection)
27008 *
27009 * @usageNotes
27010 *
27011 * The following examples demonstrate how to modify default change-detection behavior
27012 * to perform explicit detection when needed.
27013 *
27014 * ### Use `markForCheck()` with `CheckOnce` strategy
27015 *
27016 * The following example sets the `OnPush` change-detection strategy for a component
27017 * (`CheckOnce`, rather than the default `CheckAlways`), then forces a second check
27018 * after an interval. See [live demo](https://plnkr.co/edit/GC512b?p=preview).
27019 *
27020 * <code-example path="core/ts/change_detect/change-detection.ts"
27021 * region="mark-for-check"></code-example>
27022 *
27023 * ### Detach change detector to limit how often check occurs
27024 *
27025 * The following example defines a component with a large list of read-only data
27026 * that is expected to change constantly, many times per second.
27027 * To improve performance, we want to check and update the list
27028 * less often than the changes actually occur. To do that, we detach
27029 * the component's change detector and perform an explicit local check every five seconds.
27030 *
27031 * <code-example path="core/ts/change_detect/change-detection.ts" region="detach"></code-example>
27032 *
27033 *
27034 * ### Reattaching a detached component
27035 *
27036 * The following example creates a component displaying live data.
27037 * The component detaches its change detector from the main change detector tree
27038 * when the `live` property is set to false, and reattaches it when the property
27039 * becomes true.
27040 *
27041 * <code-example path="core/ts/change_detect/change-detection.ts" region="reattach"></code-example>
27042 *
27043 * @publicApi
27044 */
27045class ChangeDetectorRef {
27046}
27047/**
27048 * @internal
27049 * @nocollapse
27050 */
27051ChangeDetectorRef.__NG_ELEMENT_ID__ = SWITCH_CHANGE_DETECTOR_REF_FACTORY;
27052/** Returns a ChangeDetectorRef (a.k.a. a ViewRef) */
27053function injectChangeDetectorRef(flags) {
27054 return createViewRef(getCurrentTNode(), getLView(), (flags & 16 /* ForPipe */) === 16 /* ForPipe */);
27055}
27056/**
27057 * Creates a ViewRef and stores it on the injector as ChangeDetectorRef (public alias).
27058 *
27059 * @param tNode The node that is requesting a ChangeDetectorRef
27060 * @param lView The view to which the node belongs
27061 * @param isPipe Whether the view is being injected into a pipe.
27062 * @returns The ChangeDetectorRef to use
27063 */
27064function createViewRef(tNode, lView, isPipe) {
27065 if (isComponentHost(tNode) && !isPipe) {
27066 // The LView represents the location where the component is declared.
27067 // Instead we want the LView for the component View and so we need to look it up.
27068 const componentView = getComponentLViewByIndex(tNode.index, lView); // look down
27069 return new ViewRef$1(componentView, componentView);
27070 }
27071 else if (tNode.type & (3 /* AnyRNode */ | 12 /* AnyContainer */ | 32 /* Icu */)) {
27072 // The LView represents the location where the injection is requested from.
27073 // We need to locate the containing LView (in case where the `lView` is an embedded view)
27074 const hostComponentView = lView[DECLARATION_COMPONENT_VIEW]; // look up
27075 return new ViewRef$1(hostComponentView, lView);
27076 }
27077 return null;
27078}
27079
27080/**
27081 * @license
27082 * Copyright Google LLC All Rights Reserved.
27083 *
27084 * Use of this source code is governed by an MIT-style license that can be
27085 * found in the LICENSE file at https://angular.io/license
27086 */
27087/**
27088 * Represents an Angular [view](guide/glossary#view "Definition").
27089 *
27090 * @see {@link ChangeDetectorRef#usage-notes Change detection usage}
27091 *
27092 * @publicApi
27093 */
27094class ViewRef extends ChangeDetectorRef {
27095}
27096/**
27097 * Represents an Angular [view](guide/glossary#view) in a view container.
27098 * An [embedded view](guide/glossary#view-tree) can be referenced from a component
27099 * other than the hosting component whose template defines it, or it can be defined
27100 * independently by a `TemplateRef`.
27101 *
27102 * Properties of elements in a view can change, but the structure (number and order) of elements in
27103 * a view cannot. Change the structure of elements by inserting, moving, or
27104 * removing nested views in a view container.
27105 *
27106 * @see `ViewContainerRef`
27107 *
27108 * @usageNotes
27109 *
27110 * The following template breaks down into two separate `TemplateRef` instances,
27111 * an outer one and an inner one.
27112 *
27113 * ```
27114 * Count: {{items.length}}
27115 * <ul>
27116 * <li *ngFor="let item of items">{{item}}</li>
27117 * </ul>
27118 * ```
27119 *
27120 * This is the outer `TemplateRef`:
27121 *
27122 * ```
27123 * Count: {{items.length}}
27124 * <ul>
27125 * <ng-template ngFor let-item [ngForOf]="items"></ng-template>
27126 * </ul>
27127 * ```
27128 *
27129 * This is the inner `TemplateRef`:
27130 *
27131 * ```
27132 * <li>{{item}}</li>
27133 * ```
27134 *
27135 * The outer and inner `TemplateRef` instances are assembled into views as follows:
27136 *
27137 * ```
27138 * <!-- ViewRef: outer-0 -->
27139 * Count: 2
27140 * <ul>
27141 * <ng-template view-container-ref></ng-template>
27142 * <!-- ViewRef: inner-1 --><li>first</li><!-- /ViewRef: inner-1 -->
27143 * <!-- ViewRef: inner-2 --><li>second</li><!-- /ViewRef: inner-2 -->
27144 * </ul>
27145 * <!-- /ViewRef: outer-0 -->
27146 * ```
27147 * @publicApi
27148 */
27149class EmbeddedViewRef extends ViewRef {
27150}
27151
27152/**
27153 * @license
27154 * Copyright Google LLC All Rights Reserved.
27155 *
27156 * Use of this source code is governed by an MIT-style license that can be
27157 * found in the LICENSE file at https://angular.io/license
27158 */
27159
27160/**
27161 * @license
27162 * Copyright Google LLC All Rights Reserved.
27163 *
27164 * Use of this source code is governed by an MIT-style license that can be
27165 * found in the LICENSE file at https://angular.io/license
27166 */
27167// This file exists for easily patching NgModuleFactoryLoader in g3
27168var ng_module_factory_loader_impl = {};
27169
27170/**
27171 * @publicApi
27172 */
27173class DebugEventListener {
27174 constructor(name, callback) {
27175 this.name = name;
27176 this.callback = callback;
27177 }
27178}
27179class DebugNode__PRE_R3__ {
27180 constructor(nativeNode, parent, _debugContext) {
27181 this.listeners = [];
27182 this.parent = null;
27183 this._debugContext = _debugContext;
27184 this.nativeNode = nativeNode;
27185 if (parent && parent instanceof DebugElement__PRE_R3__) {
27186 parent.addChild(this);
27187 }
27188 }
27189 get injector() {
27190 return this._debugContext.injector;
27191 }
27192 get componentInstance() {
27193 return this._debugContext.component;
27194 }
27195 get context() {
27196 return this._debugContext.context;
27197 }
27198 get references() {
27199 return this._debugContext.references;
27200 }
27201 get providerTokens() {
27202 return this._debugContext.providerTokens;
27203 }
27204}
27205class DebugElement__PRE_R3__ extends DebugNode__PRE_R3__ {
27206 constructor(nativeNode, parent, _debugContext) {
27207 super(nativeNode, parent, _debugContext);
27208 this.properties = {};
27209 this.attributes = {};
27210 this.classes = {};
27211 this.styles = {};
27212 this.childNodes = [];
27213 this.nativeElement = nativeNode;
27214 }
27215 addChild(child) {
27216 if (child) {
27217 this.childNodes.push(child);
27218 child.parent = this;
27219 }
27220 }
27221 removeChild(child) {
27222 const childIndex = this.childNodes.indexOf(child);
27223 if (childIndex !== -1) {
27224 child.parent = null;
27225 this.childNodes.splice(childIndex, 1);
27226 }
27227 }
27228 insertChildrenAfter(child, newChildren) {
27229 const siblingIndex = this.childNodes.indexOf(child);
27230 if (siblingIndex !== -1) {
27231 this.childNodes.splice(siblingIndex + 1, 0, ...newChildren);
27232 newChildren.forEach(c => {
27233 if (c.parent) {
27234 c.parent.removeChild(c);
27235 }
27236 child.parent = this;
27237 });
27238 }
27239 }
27240 insertBefore(refChild, newChild) {
27241 const refIndex = this.childNodes.indexOf(refChild);
27242 if (refIndex === -1) {
27243 this.addChild(newChild);
27244 }
27245 else {
27246 if (newChild.parent) {
27247 newChild.parent.removeChild(newChild);
27248 }
27249 newChild.parent = this;
27250 this.childNodes.splice(refIndex, 0, newChild);
27251 }
27252 }
27253 query(predicate) {
27254 const results = this.queryAll(predicate);
27255 return results[0] || null;
27256 }
27257 queryAll(predicate) {
27258 const matches = [];
27259 _queryElementChildren(this, predicate, matches);
27260 return matches;
27261 }
27262 queryAllNodes(predicate) {
27263 const matches = [];
27264 _queryNodeChildren(this, predicate, matches);
27265 return matches;
27266 }
27267 get children() {
27268 return this.childNodes //
27269 .filter((node) => node instanceof DebugElement__PRE_R3__);
27270 }
27271 triggerEventHandler(eventName, eventObj) {
27272 this.listeners.forEach((listener) => {
27273 if (listener.name == eventName) {
27274 listener.callback(eventObj);
27275 }
27276 });
27277 }
27278}
27279/**
27280 * @publicApi
27281 */
27282function asNativeElements(debugEls) {
27283 return debugEls.map((el) => el.nativeElement);
27284}
27285function _queryElementChildren(element, predicate, matches) {
27286 element.childNodes.forEach(node => {
27287 if (node instanceof DebugElement__PRE_R3__) {
27288 if (predicate(node)) {
27289 matches.push(node);
27290 }
27291 _queryElementChildren(node, predicate, matches);
27292 }
27293 });
27294}
27295function _queryNodeChildren(parentNode, predicate, matches) {
27296 if (parentNode instanceof DebugElement__PRE_R3__) {
27297 parentNode.childNodes.forEach(node => {
27298 if (predicate(node)) {
27299 matches.push(node);
27300 }
27301 if (node instanceof DebugElement__PRE_R3__) {
27302 _queryNodeChildren(node, predicate, matches);
27303 }
27304 });
27305 }
27306}
27307class DebugNode__POST_R3__ {
27308 constructor(nativeNode) {
27309 this.nativeNode = nativeNode;
27310 }
27311 get parent() {
27312 const parent = this.nativeNode.parentNode;
27313 return parent ? new DebugElement__POST_R3__(parent) : null;
27314 }
27315 get injector() {
27316 return getInjector(this.nativeNode);
27317 }
27318 get componentInstance() {
27319 const nativeElement = this.nativeNode;
27320 return nativeElement &&
27321 (getComponent$1(nativeElement) || getOwningComponent(nativeElement));
27322 }
27323 get context() {
27324 return getComponent$1(this.nativeNode) || getContext(this.nativeNode);
27325 }
27326 get listeners() {
27327 return getListeners(this.nativeNode).filter(listener => listener.type === 'dom');
27328 }
27329 get references() {
27330 return getLocalRefs(this.nativeNode);
27331 }
27332 get providerTokens() {
27333 return getInjectionTokens(this.nativeNode);
27334 }
27335}
27336class DebugElement__POST_R3__ extends DebugNode__POST_R3__ {
27337 constructor(nativeNode) {
27338 ngDevMode && assertDomNode(nativeNode);
27339 super(nativeNode);
27340 }
27341 get nativeElement() {
27342 return this.nativeNode.nodeType == Node.ELEMENT_NODE ? this.nativeNode : null;
27343 }
27344 get name() {
27345 const context = getLContext(this.nativeNode);
27346 if (context !== null) {
27347 const lView = context.lView;
27348 const tData = lView[TVIEW].data;
27349 const tNode = tData[context.nodeIndex];
27350 return tNode.value;
27351 }
27352 else {
27353 return this.nativeNode.nodeName;
27354 }
27355 }
27356 /**
27357 * Gets a map of property names to property values for an element.
27358 *
27359 * This map includes:
27360 * - Regular property bindings (e.g. `[id]="id"`)
27361 * - Host property bindings (e.g. `host: { '[id]': "id" }`)
27362 * - Interpolated property bindings (e.g. `id="{{ value }}")
27363 *
27364 * It does not include:
27365 * - input property bindings (e.g. `[myCustomInput]="value"`)
27366 * - attribute bindings (e.g. `[attr.role]="menu"`)
27367 */
27368 get properties() {
27369 const context = getLContext(this.nativeNode);
27370 if (context === null) {
27371 return {};
27372 }
27373 const lView = context.lView;
27374 const tData = lView[TVIEW].data;
27375 const tNode = tData[context.nodeIndex];
27376 const properties = {};
27377 // Collect properties from the DOM.
27378 copyDomProperties(this.nativeElement, properties);
27379 // Collect properties from the bindings. This is needed for animation renderer which has
27380 // synthetic properties which don't get reflected into the DOM.
27381 collectPropertyBindings(properties, tNode, lView, tData);
27382 return properties;
27383 }
27384 get attributes() {
27385 const attributes = {};
27386 const element = this.nativeElement;
27387 if (!element) {
27388 return attributes;
27389 }
27390 const context = getLContext(element);
27391 if (context === null) {
27392 return {};
27393 }
27394 const lView = context.lView;
27395 const tNodeAttrs = lView[TVIEW].data[context.nodeIndex].attrs;
27396 const lowercaseTNodeAttrs = [];
27397 // For debug nodes we take the element's attribute directly from the DOM since it allows us
27398 // to account for ones that weren't set via bindings (e.g. ViewEngine keeps track of the ones
27399 // that are set through `Renderer2`). The problem is that the browser will lowercase all names,
27400 // however since we have the attributes already on the TNode, we can preserve the case by going
27401 // through them once, adding them to the `attributes` map and putting their lower-cased name
27402 // into an array. Afterwards when we're going through the native DOM attributes, we can check
27403 // whether we haven't run into an attribute already through the TNode.
27404 if (tNodeAttrs) {
27405 let i = 0;
27406 while (i < tNodeAttrs.length) {
27407 const attrName = tNodeAttrs[i];
27408 // Stop as soon as we hit a marker. We only care about the regular attributes. Everything
27409 // else will be handled below when we read the final attributes off the DOM.
27410 if (typeof attrName !== 'string')
27411 break;
27412 const attrValue = tNodeAttrs[i + 1];
27413 attributes[attrName] = attrValue;
27414 lowercaseTNodeAttrs.push(attrName.toLowerCase());
27415 i += 2;
27416 }
27417 }
27418 const eAttrs = element.attributes;
27419 for (let i = 0; i < eAttrs.length; i++) {
27420 const attr = eAttrs[i];
27421 const lowercaseName = attr.name.toLowerCase();
27422 // Make sure that we don't assign the same attribute both in its
27423 // case-sensitive form and the lower-cased one from the browser.
27424 if (lowercaseTNodeAttrs.indexOf(lowercaseName) === -1) {
27425 // Save the lowercase name to align the behavior between browsers.
27426 // IE preserves the case, while all other browser convert it to lower case.
27427 attributes[lowercaseName] = attr.value;
27428 }
27429 }
27430 return attributes;
27431 }
27432 get styles() {
27433 if (this.nativeElement && this.nativeElement.style) {
27434 return this.nativeElement.style;
27435 }
27436 return {};
27437 }
27438 get classes() {
27439 const result = {};
27440 const element = this.nativeElement;
27441 // SVG elements return an `SVGAnimatedString` instead of a plain string for the `className`.
27442 const className = element.className;
27443 const classes = typeof className !== 'string' ? className.baseVal.split(' ') : className.split(' ');
27444 classes.forEach((value) => result[value] = true);
27445 return result;
27446 }
27447 get childNodes() {
27448 const childNodes = this.nativeNode.childNodes;
27449 const children = [];
27450 for (let i = 0; i < childNodes.length; i++) {
27451 const element = childNodes[i];
27452 children.push(getDebugNode__POST_R3__(element));
27453 }
27454 return children;
27455 }
27456 get children() {
27457 const nativeElement = this.nativeElement;
27458 if (!nativeElement)
27459 return [];
27460 const childNodes = nativeElement.children;
27461 const children = [];
27462 for (let i = 0; i < childNodes.length; i++) {
27463 const element = childNodes[i];
27464 children.push(getDebugNode__POST_R3__(element));
27465 }
27466 return children;
27467 }
27468 query(predicate) {
27469 const results = this.queryAll(predicate);
27470 return results[0] || null;
27471 }
27472 queryAll(predicate) {
27473 const matches = [];
27474 _queryAllR3(this, predicate, matches, true);
27475 return matches;
27476 }
27477 queryAllNodes(predicate) {
27478 const matches = [];
27479 _queryAllR3(this, predicate, matches, false);
27480 return matches;
27481 }
27482 triggerEventHandler(eventName, eventObj) {
27483 const node = this.nativeNode;
27484 const invokedListeners = [];
27485 this.listeners.forEach(listener => {
27486 if (listener.name === eventName) {
27487 const callback = listener.callback;
27488 callback.call(node, eventObj);
27489 invokedListeners.push(callback);
27490 }
27491 });
27492 // We need to check whether `eventListeners` exists, because it's something
27493 // that Zone.js only adds to `EventTarget` in browser environments.
27494 if (typeof node.eventListeners === 'function') {
27495 // Note that in Ivy we wrap event listeners with a call to `event.preventDefault` in some
27496 // cases. We use '__ngUnwrap__' as a special token that gives us access to the actual event
27497 // listener.
27498 node.eventListeners(eventName).forEach((listener) => {
27499 // In order to ensure that we can detect the special __ngUnwrap__ token described above, we
27500 // use `toString` on the listener and see if it contains the token. We use this approach to
27501 // ensure that it still worked with compiled code since it cannot remove or rename string
27502 // literals. We also considered using a special function name (i.e. if(listener.name ===
27503 // special)) but that was more cumbersome and we were also concerned the compiled code could
27504 // strip the name, turning the condition in to ("" === "") and always returning true.
27505 if (listener.toString().indexOf('__ngUnwrap__') !== -1) {
27506 const unwrappedListener = listener('__ngUnwrap__');
27507 return invokedListeners.indexOf(unwrappedListener) === -1 &&
27508 unwrappedListener.call(node, eventObj);
27509 }
27510 });
27511 }
27512 }
27513}
27514function copyDomProperties(element, properties) {
27515 if (element) {
27516 // Skip own properties (as those are patched)
27517 let obj = Object.getPrototypeOf(element);
27518 const NodePrototype = Node.prototype;
27519 while (obj !== null && obj !== NodePrototype) {
27520 const descriptors = Object.getOwnPropertyDescriptors(obj);
27521 for (let key in descriptors) {
27522 if (!key.startsWith('__') && !key.startsWith('on')) {
27523 // don't include properties starting with `__` and `on`.
27524 // `__` are patched values which should not be included.
27525 // `on` are listeners which also should not be included.
27526 const value = element[key];
27527 if (isPrimitiveValue(value)) {
27528 properties[key] = value;
27529 }
27530 }
27531 }
27532 obj = Object.getPrototypeOf(obj);
27533 }
27534 }
27535}
27536function isPrimitiveValue(value) {
27537 return typeof value === 'string' || typeof value === 'boolean' || typeof value === 'number' ||
27538 value === null;
27539}
27540function _queryAllR3(parentElement, predicate, matches, elementsOnly) {
27541 const context = getLContext(parentElement.nativeNode);
27542 if (context !== null) {
27543 const parentTNode = context.lView[TVIEW].data[context.nodeIndex];
27544 _queryNodeChildrenR3(parentTNode, context.lView, predicate, matches, elementsOnly, parentElement.nativeNode);
27545 }
27546 else {
27547 // If the context is null, then `parentElement` was either created with Renderer2 or native DOM
27548 // APIs.
27549 _queryNativeNodeDescendants(parentElement.nativeNode, predicate, matches, elementsOnly);
27550 }
27551}
27552/**
27553 * Recursively match the current TNode against the predicate, and goes on with the next ones.
27554 *
27555 * @param tNode the current TNode
27556 * @param lView the LView of this TNode
27557 * @param predicate the predicate to match
27558 * @param matches the list of positive matches
27559 * @param elementsOnly whether only elements should be searched
27560 * @param rootNativeNode the root native node on which predicate should not be matched
27561 */
27562function _queryNodeChildrenR3(tNode, lView, predicate, matches, elementsOnly, rootNativeNode) {
27563 ngDevMode && assertTNodeForLView(tNode, lView);
27564 const nativeNode = getNativeByTNodeOrNull(tNode, lView);
27565 // For each type of TNode, specific logic is executed.
27566 if (tNode.type & (3 /* AnyRNode */ | 8 /* ElementContainer */)) {
27567 // Case 1: the TNode is an element
27568 // The native node has to be checked.
27569 _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
27570 if (isComponentHost(tNode)) {
27571 // If the element is the host of a component, then all nodes in its view have to be processed.
27572 // Note: the component's content (tNode.child) will be processed from the insertion points.
27573 const componentView = getComponentLViewByIndex(tNode.index, lView);
27574 if (componentView && componentView[TVIEW].firstChild) {
27575 _queryNodeChildrenR3(componentView[TVIEW].firstChild, componentView, predicate, matches, elementsOnly, rootNativeNode);
27576 }
27577 }
27578 else {
27579 if (tNode.child) {
27580 // Otherwise, its children have to be processed.
27581 _queryNodeChildrenR3(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode);
27582 }
27583 // We also have to query the DOM directly in order to catch elements inserted through
27584 // Renderer2. Note that this is __not__ optimal, because we're walking similar trees multiple
27585 // times. ViewEngine could do it more efficiently, because all the insertions go through
27586 // Renderer2, however that's not the case in Ivy. This approach is being used because:
27587 // 1. Matching the ViewEngine behavior would mean potentially introducing a depedency
27588 // from `Renderer2` to Ivy which could bring Ivy code into ViewEngine.
27589 // 2. We would have to make `Renderer3` "know" about debug nodes.
27590 // 3. It allows us to capture nodes that were inserted directly via the DOM.
27591 nativeNode && _queryNativeNodeDescendants(nativeNode, predicate, matches, elementsOnly);
27592 }
27593 // In all cases, if a dynamic container exists for this node, each view inside it has to be
27594 // processed.
27595 const nodeOrContainer = lView[tNode.index];
27596 if (isLContainer(nodeOrContainer)) {
27597 _queryNodeChildrenInContainerR3(nodeOrContainer, predicate, matches, elementsOnly, rootNativeNode);
27598 }
27599 }
27600 else if (tNode.type & 4 /* Container */) {
27601 // Case 2: the TNode is a container
27602 // The native node has to be checked.
27603 const lContainer = lView[tNode.index];
27604 _addQueryMatchR3(lContainer[NATIVE], predicate, matches, elementsOnly, rootNativeNode);
27605 // Each view inside the container has to be processed.
27606 _queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode);
27607 }
27608 else if (tNode.type & 16 /* Projection */) {
27609 // Case 3: the TNode is a projection insertion point (i.e. a <ng-content>).
27610 // The nodes projected at this location all need to be processed.
27611 const componentView = lView[DECLARATION_COMPONENT_VIEW];
27612 const componentHost = componentView[T_HOST];
27613 const head = componentHost.projection[tNode.projection];
27614 if (Array.isArray(head)) {
27615 for (let nativeNode of head) {
27616 _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode);
27617 }
27618 }
27619 else if (head) {
27620 const nextLView = componentView[PARENT];
27621 const nextTNode = nextLView[TVIEW].data[head.index];
27622 _queryNodeChildrenR3(nextTNode, nextLView, predicate, matches, elementsOnly, rootNativeNode);
27623 }
27624 }
27625 else if (tNode.child) {
27626 // Case 4: the TNode is a view.
27627 _queryNodeChildrenR3(tNode.child, lView, predicate, matches, elementsOnly, rootNativeNode);
27628 }
27629 // We don't want to go to the next sibling of the root node.
27630 if (rootNativeNode !== nativeNode) {
27631 // To determine the next node to be processed, we need to use the next or the projectionNext
27632 // link, depending on whether the current node has been projected.
27633 const nextTNode = (tNode.flags & 4 /* isProjected */) ? tNode.projectionNext : tNode.next;
27634 if (nextTNode) {
27635 _queryNodeChildrenR3(nextTNode, lView, predicate, matches, elementsOnly, rootNativeNode);
27636 }
27637 }
27638}
27639/**
27640 * Process all TNodes in a given container.
27641 *
27642 * @param lContainer the container to be processed
27643 * @param predicate the predicate to match
27644 * @param matches the list of positive matches
27645 * @param elementsOnly whether only elements should be searched
27646 * @param rootNativeNode the root native node on which predicate should not be matched
27647 */
27648function _queryNodeChildrenInContainerR3(lContainer, predicate, matches, elementsOnly, rootNativeNode) {
27649 for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
27650 const childView = lContainer[i];
27651 const firstChild = childView[TVIEW].firstChild;
27652 if (firstChild) {
27653 _queryNodeChildrenR3(firstChild, childView, predicate, matches, elementsOnly, rootNativeNode);
27654 }
27655 }
27656}
27657/**
27658 * Match the current native node against the predicate.
27659 *
27660 * @param nativeNode the current native node
27661 * @param predicate the predicate to match
27662 * @param matches the list of positive matches
27663 * @param elementsOnly whether only elements should be searched
27664 * @param rootNativeNode the root native node on which predicate should not be matched
27665 */
27666function _addQueryMatchR3(nativeNode, predicate, matches, elementsOnly, rootNativeNode) {
27667 if (rootNativeNode !== nativeNode) {
27668 const debugNode = getDebugNode(nativeNode);
27669 if (!debugNode) {
27670 return;
27671 }
27672 // Type of the "predicate and "matches" array are set based on the value of
27673 // the "elementsOnly" parameter. TypeScript is not able to properly infer these
27674 // types with generics, so we manually cast the parameters accordingly.
27675 if (elementsOnly && debugNode instanceof DebugElement__POST_R3__ && predicate(debugNode) &&
27676 matches.indexOf(debugNode) === -1) {
27677 matches.push(debugNode);
27678 }
27679 else if (!elementsOnly && predicate(debugNode) &&
27680 matches.indexOf(debugNode) === -1) {
27681 matches.push(debugNode);
27682 }
27683 }
27684}
27685/**
27686 * Match all the descendants of a DOM node against a predicate.
27687 *
27688 * @param nativeNode the current native node
27689 * @param predicate the predicate to match
27690 * @param matches the list where matches are stored
27691 * @param elementsOnly whether only elements should be searched
27692 */
27693function _queryNativeNodeDescendants(parentNode, predicate, matches, elementsOnly) {
27694 const nodes = parentNode.childNodes;
27695 const length = nodes.length;
27696 for (let i = 0; i < length; i++) {
27697 const node = nodes[i];
27698 const debugNode = getDebugNode(node);
27699 if (debugNode) {
27700 if (elementsOnly && debugNode instanceof DebugElement__POST_R3__ && predicate(debugNode) &&
27701 matches.indexOf(debugNode) === -1) {
27702 matches.push(debugNode);
27703 }
27704 else if (!elementsOnly && predicate(debugNode) &&
27705 matches.indexOf(debugNode) === -1) {
27706 matches.push(debugNode);
27707 }
27708 _queryNativeNodeDescendants(node, predicate, matches, elementsOnly);
27709 }
27710 }
27711}
27712/**
27713 * Iterates through the property bindings for a given node and generates
27714 * a map of property names to values. This map only contains property bindings
27715 * defined in templates, not in host bindings.
27716 */
27717function collectPropertyBindings(properties, tNode, lView, tData) {
27718 let bindingIndexes = tNode.propertyBindings;
27719 if (bindingIndexes !== null) {
27720 for (let i = 0; i < bindingIndexes.length; i++) {
27721 const bindingIndex = bindingIndexes[i];
27722 const propMetadata = tData[bindingIndex];
27723 const metadataParts = propMetadata.split(INTERPOLATION_DELIMITER);
27724 const propertyName = metadataParts[0];
27725 if (metadataParts.length > 1) {
27726 let value = metadataParts[1];
27727 for (let j = 1; j < metadataParts.length - 1; j++) {
27728 value += renderStringify(lView[bindingIndex + j - 1]) + metadataParts[j + 1];
27729 }
27730 properties[propertyName] = value;
27731 }
27732 else {
27733 properties[propertyName] = lView[bindingIndex];
27734 }
27735 }
27736 }
27737}
27738// Need to keep the nodes in a global Map so that multiple angular apps are supported.
27739const _nativeNodeToDebugNode = new Map();
27740function getDebugNode__PRE_R3__(nativeNode) {
27741 return _nativeNodeToDebugNode.get(nativeNode) || null;
27742}
27743const NG_DEBUG_PROPERTY = '__ng_debug__';
27744function getDebugNode__POST_R3__(nativeNode) {
27745 if (nativeNode instanceof Node) {
27746 if (!(nativeNode.hasOwnProperty(NG_DEBUG_PROPERTY))) {
27747 nativeNode[NG_DEBUG_PROPERTY] = nativeNode.nodeType == Node.ELEMENT_NODE ?
27748 new DebugElement__POST_R3__(nativeNode) :
27749 new DebugNode__POST_R3__(nativeNode);
27750 }
27751 return nativeNode[NG_DEBUG_PROPERTY];
27752 }
27753 return null;
27754}
27755/**
27756 * @publicApi
27757 */
27758const getDebugNode = getDebugNode__POST_R3__;
27759function getDebugNodeR2__PRE_R3__(nativeNode) {
27760 return getDebugNode__PRE_R3__(nativeNode);
27761}
27762function getDebugNodeR2__POST_R3__(_nativeNode) {
27763 return null;
27764}
27765const getDebugNodeR2 = getDebugNodeR2__POST_R3__;
27766function getAllDebugNodes() {
27767 return Array.from(_nativeNodeToDebugNode.values());
27768}
27769function indexDebugNode(node) {
27770 _nativeNodeToDebugNode.set(node.nativeNode, node);
27771}
27772function removeDebugNodeFromIndex(node) {
27773 _nativeNodeToDebugNode.delete(node.nativeNode);
27774}
27775/**
27776 * @publicApi
27777 */
27778const DebugNode = DebugNode__POST_R3__;
27779/**
27780 * @publicApi
27781 */
27782const DebugElement = DebugElement__POST_R3__;
27783
27784/**
27785 * @license
27786 * Copyright Google LLC All Rights Reserved.
27787 *
27788 * Use of this source code is governed by an MIT-style license that can be
27789 * found in the LICENSE file at https://angular.io/license
27790 */
27791class DefaultIterableDifferFactory {
27792 constructor() { }
27793 supports(obj) {
27794 return isListLikeIterable(obj);
27795 }
27796 create(trackByFn) {
27797 return new DefaultIterableDiffer(trackByFn);
27798 }
27799}
27800const trackByIdentity = (index, item) => item;
27801/**
27802 * @deprecated v4.0.0 - Should not be part of public API.
27803 * @publicApi
27804 */
27805class DefaultIterableDiffer {
27806 constructor(trackByFn) {
27807 this.length = 0;
27808 // Keeps track of the used records at any point in time (during & across `_check()` calls)
27809 this._linkedRecords = null;
27810 // Keeps track of the removed records at any point in time during `_check()` calls.
27811 this._unlinkedRecords = null;
27812 this._previousItHead = null;
27813 this._itHead = null;
27814 this._itTail = null;
27815 this._additionsHead = null;
27816 this._additionsTail = null;
27817 this._movesHead = null;
27818 this._movesTail = null;
27819 this._removalsHead = null;
27820 this._removalsTail = null;
27821 // Keeps track of records where custom track by is the same, but item identity has changed
27822 this._identityChangesHead = null;
27823 this._identityChangesTail = null;
27824 this._trackByFn = trackByFn || trackByIdentity;
27825 }
27826 forEachItem(fn) {
27827 let record;
27828 for (record = this._itHead; record !== null; record = record._next) {
27829 fn(record);
27830 }
27831 }
27832 forEachOperation(fn) {
27833 let nextIt = this._itHead;
27834 let nextRemove = this._removalsHead;
27835 let addRemoveOffset = 0;
27836 let moveOffsets = null;
27837 while (nextIt || nextRemove) {
27838 // Figure out which is the next record to process
27839 // Order: remove, add, move
27840 const record = !nextRemove ||
27841 nextIt &&
27842 nextIt.currentIndex <
27843 getPreviousIndex(nextRemove, addRemoveOffset, moveOffsets) ?
27844 nextIt :
27845 nextRemove;
27846 const adjPreviousIndex = getPreviousIndex(record, addRemoveOffset, moveOffsets);
27847 const currentIndex = record.currentIndex;
27848 // consume the item, and adjust the addRemoveOffset and update moveDistance if necessary
27849 if (record === nextRemove) {
27850 addRemoveOffset--;
27851 nextRemove = nextRemove._nextRemoved;
27852 }
27853 else {
27854 nextIt = nextIt._next;
27855 if (record.previousIndex == null) {
27856 addRemoveOffset++;
27857 }
27858 else {
27859 // INVARIANT: currentIndex < previousIndex
27860 if (!moveOffsets)
27861 moveOffsets = [];
27862 const localMovePreviousIndex = adjPreviousIndex - addRemoveOffset;
27863 const localCurrentIndex = currentIndex - addRemoveOffset;
27864 if (localMovePreviousIndex != localCurrentIndex) {
27865 for (let i = 0; i < localMovePreviousIndex; i++) {
27866 const offset = i < moveOffsets.length ? moveOffsets[i] : (moveOffsets[i] = 0);
27867 const index = offset + i;
27868 if (localCurrentIndex <= index && index < localMovePreviousIndex) {
27869 moveOffsets[i] = offset + 1;
27870 }
27871 }
27872 const previousIndex = record.previousIndex;
27873 moveOffsets[previousIndex] = localCurrentIndex - localMovePreviousIndex;
27874 }
27875 }
27876 }
27877 if (adjPreviousIndex !== currentIndex) {
27878 fn(record, adjPreviousIndex, currentIndex);
27879 }
27880 }
27881 }
27882 forEachPreviousItem(fn) {
27883 let record;
27884 for (record = this._previousItHead; record !== null; record = record._nextPrevious) {
27885 fn(record);
27886 }
27887 }
27888 forEachAddedItem(fn) {
27889 let record;
27890 for (record = this._additionsHead; record !== null; record = record._nextAdded) {
27891 fn(record);
27892 }
27893 }
27894 forEachMovedItem(fn) {
27895 let record;
27896 for (record = this._movesHead; record !== null; record = record._nextMoved) {
27897 fn(record);
27898 }
27899 }
27900 forEachRemovedItem(fn) {
27901 let record;
27902 for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
27903 fn(record);
27904 }
27905 }
27906 forEachIdentityChange(fn) {
27907 let record;
27908 for (record = this._identityChangesHead; record !== null; record = record._nextIdentityChange) {
27909 fn(record);
27910 }
27911 }
27912 diff(collection) {
27913 if (collection == null)
27914 collection = [];
27915 if (!isListLikeIterable(collection)) {
27916 throw new Error(`Error trying to diff '${stringify(collection)}'. Only arrays and iterables are allowed`);
27917 }
27918 if (this.check(collection)) {
27919 return this;
27920 }
27921 else {
27922 return null;
27923 }
27924 }
27925 onDestroy() { }
27926 check(collection) {
27927 this._reset();
27928 let record = this._itHead;
27929 let mayBeDirty = false;
27930 let index;
27931 let item;
27932 let itemTrackBy;
27933 if (Array.isArray(collection)) {
27934 this.length = collection.length;
27935 for (let index = 0; index < this.length; index++) {
27936 item = collection[index];
27937 itemTrackBy = this._trackByFn(index, item);
27938 if (record === null || !Object.is(record.trackById, itemTrackBy)) {
27939 record = this._mismatch(record, item, itemTrackBy, index);
27940 mayBeDirty = true;
27941 }
27942 else {
27943 if (mayBeDirty) {
27944 // TODO(misko): can we limit this to duplicates only?
27945 record = this._verifyReinsertion(record, item, itemTrackBy, index);
27946 }
27947 if (!Object.is(record.item, item))
27948 this._addIdentityChange(record, item);
27949 }
27950 record = record._next;
27951 }
27952 }
27953 else {
27954 index = 0;
27955 iterateListLike(collection, (item) => {
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 index++;
27971 });
27972 this.length = index;
27973 }
27974 this._truncate(record);
27975 this.collection = collection;
27976 return this.isDirty;
27977 }
27978 /* CollectionChanges is considered dirty if it has any additions, moves, removals, or identity
27979 * changes.
27980 */
27981 get isDirty() {
27982 return this._additionsHead !== null || this._movesHead !== null ||
27983 this._removalsHead !== null || this._identityChangesHead !== null;
27984 }
27985 /**
27986 * Reset the state of the change objects to show no changes. This means set previousKey to
27987 * currentKey, and clear all of the queues (additions, moves, removals).
27988 * Set the previousIndexes of moved and added items to their currentIndexes
27989 * Reset the list of additions, moves and removals
27990 *
27991 * @internal
27992 */
27993 _reset() {
27994 if (this.isDirty) {
27995 let record;
27996 for (record = this._previousItHead = this._itHead; record !== null; record = record._next) {
27997 record._nextPrevious = record._next;
27998 }
27999 for (record = this._additionsHead; record !== null; record = record._nextAdded) {
28000 record.previousIndex = record.currentIndex;
28001 }
28002 this._additionsHead = this._additionsTail = null;
28003 for (record = this._movesHead; record !== null; record = record._nextMoved) {
28004 record.previousIndex = record.currentIndex;
28005 }
28006 this._movesHead = this._movesTail = null;
28007 this._removalsHead = this._removalsTail = null;
28008 this._identityChangesHead = this._identityChangesTail = null;
28009 // TODO(vicb): when assert gets supported
28010 // assert(!this.isDirty);
28011 }
28012 }
28013 /**
28014 * This is the core function which handles differences between collections.
28015 *
28016 * - `record` is the record which we saw at this position last time. If null then it is a new
28017 * item.
28018 * - `item` is the current item in the collection
28019 * - `index` is the position of the item in the collection
28020 *
28021 * @internal
28022 */
28023 _mismatch(record, item, itemTrackBy, index) {
28024 // The previous record after which we will append the current one.
28025 let previousRecord;
28026 if (record === null) {
28027 previousRecord = this._itTail;
28028 }
28029 else {
28030 previousRecord = record._prev;
28031 // Remove the record from the collection since we know it does not match the item.
28032 this._remove(record);
28033 }
28034 // See if we have evicted the item, which used to be at some anterior position of _itHead list.
28035 record = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);
28036 if (record !== null) {
28037 // It is an item which we have evicted earlier: reinsert it back into the list.
28038 // But first we need to check if identity changed, so we can update in view if necessary.
28039 if (!Object.is(record.item, item))
28040 this._addIdentityChange(record, item);
28041 this._reinsertAfter(record, previousRecord, index);
28042 }
28043 else {
28044 // Attempt to see if the item is at some posterior position of _itHead list.
28045 record = this._linkedRecords === null ? null : this._linkedRecords.get(itemTrackBy, index);
28046 if (record !== null) {
28047 // We have the item in _itHead at/after `index` position. We need to move it forward in the
28048 // collection.
28049 // But first we need to check if identity changed, so we can update in view if necessary.
28050 if (!Object.is(record.item, item))
28051 this._addIdentityChange(record, item);
28052 this._moveAfter(record, previousRecord, index);
28053 }
28054 else {
28055 // It is a new item: add it.
28056 record =
28057 this._addAfter(new IterableChangeRecord_(item, itemTrackBy), previousRecord, index);
28058 }
28059 }
28060 return record;
28061 }
28062 /**
28063 * This check is only needed if an array contains duplicates. (Short circuit of nothing dirty)
28064 *
28065 * Use case: `[a, a]` => `[b, a, a]`
28066 *
28067 * If we did not have this check then the insertion of `b` would:
28068 * 1) evict first `a`
28069 * 2) insert `b` at `0` index.
28070 * 3) leave `a` at index `1` as is. <-- this is wrong!
28071 * 3) reinsert `a` at index 2. <-- this is wrong!
28072 *
28073 * The correct behavior is:
28074 * 1) evict first `a`
28075 * 2) insert `b` at `0` index.
28076 * 3) reinsert `a` at index 1.
28077 * 3) move `a` at from `1` to `2`.
28078 *
28079 *
28080 * Double check that we have not evicted a duplicate item. We need to check if the item type may
28081 * have already been removed:
28082 * The insertion of b will evict the first 'a'. If we don't reinsert it now it will be reinserted
28083 * at the end. Which will show up as the two 'a's switching position. This is incorrect, since a
28084 * better way to think of it is as insert of 'b' rather then switch 'a' with 'b' and then add 'a'
28085 * at the end.
28086 *
28087 * @internal
28088 */
28089 _verifyReinsertion(record, item, itemTrackBy, index) {
28090 let reinsertRecord = this._unlinkedRecords === null ? null : this._unlinkedRecords.get(itemTrackBy, null);
28091 if (reinsertRecord !== null) {
28092 record = this._reinsertAfter(reinsertRecord, record._prev, index);
28093 }
28094 else if (record.currentIndex != index) {
28095 record.currentIndex = index;
28096 this._addToMoves(record, index);
28097 }
28098 return record;
28099 }
28100 /**
28101 * Get rid of any excess {@link IterableChangeRecord_}s from the previous collection
28102 *
28103 * - `record` The first excess {@link IterableChangeRecord_}.
28104 *
28105 * @internal
28106 */
28107 _truncate(record) {
28108 // Anything after that needs to be removed;
28109 while (record !== null) {
28110 const nextRecord = record._next;
28111 this._addToRemovals(this._unlink(record));
28112 record = nextRecord;
28113 }
28114 if (this._unlinkedRecords !== null) {
28115 this._unlinkedRecords.clear();
28116 }
28117 if (this._additionsTail !== null) {
28118 this._additionsTail._nextAdded = null;
28119 }
28120 if (this._movesTail !== null) {
28121 this._movesTail._nextMoved = null;
28122 }
28123 if (this._itTail !== null) {
28124 this._itTail._next = null;
28125 }
28126 if (this._removalsTail !== null) {
28127 this._removalsTail._nextRemoved = null;
28128 }
28129 if (this._identityChangesTail !== null) {
28130 this._identityChangesTail._nextIdentityChange = null;
28131 }
28132 }
28133 /** @internal */
28134 _reinsertAfter(record, prevRecord, index) {
28135 if (this._unlinkedRecords !== null) {
28136 this._unlinkedRecords.remove(record);
28137 }
28138 const prev = record._prevRemoved;
28139 const next = record._nextRemoved;
28140 if (prev === null) {
28141 this._removalsHead = next;
28142 }
28143 else {
28144 prev._nextRemoved = next;
28145 }
28146 if (next === null) {
28147 this._removalsTail = prev;
28148 }
28149 else {
28150 next._prevRemoved = prev;
28151 }
28152 this._insertAfter(record, prevRecord, index);
28153 this._addToMoves(record, index);
28154 return record;
28155 }
28156 /** @internal */
28157 _moveAfter(record, prevRecord, index) {
28158 this._unlink(record);
28159 this._insertAfter(record, prevRecord, index);
28160 this._addToMoves(record, index);
28161 return record;
28162 }
28163 /** @internal */
28164 _addAfter(record, prevRecord, index) {
28165 this._insertAfter(record, prevRecord, index);
28166 if (this._additionsTail === null) {
28167 // TODO(vicb):
28168 // assert(this._additionsHead === null);
28169 this._additionsTail = this._additionsHead = record;
28170 }
28171 else {
28172 // TODO(vicb):
28173 // assert(_additionsTail._nextAdded === null);
28174 // assert(record._nextAdded === null);
28175 this._additionsTail = this._additionsTail._nextAdded = record;
28176 }
28177 return record;
28178 }
28179 /** @internal */
28180 _insertAfter(record, prevRecord, index) {
28181 // TODO(vicb):
28182 // assert(record != prevRecord);
28183 // assert(record._next === null);
28184 // assert(record._prev === null);
28185 const next = prevRecord === null ? this._itHead : prevRecord._next;
28186 // TODO(vicb):
28187 // assert(next != record);
28188 // assert(prevRecord != record);
28189 record._next = next;
28190 record._prev = prevRecord;
28191 if (next === null) {
28192 this._itTail = record;
28193 }
28194 else {
28195 next._prev = record;
28196 }
28197 if (prevRecord === null) {
28198 this._itHead = record;
28199 }
28200 else {
28201 prevRecord._next = record;
28202 }
28203 if (this._linkedRecords === null) {
28204 this._linkedRecords = new _DuplicateMap();
28205 }
28206 this._linkedRecords.put(record);
28207 record.currentIndex = index;
28208 return record;
28209 }
28210 /** @internal */
28211 _remove(record) {
28212 return this._addToRemovals(this._unlink(record));
28213 }
28214 /** @internal */
28215 _unlink(record) {
28216 if (this._linkedRecords !== null) {
28217 this._linkedRecords.remove(record);
28218 }
28219 const prev = record._prev;
28220 const next = record._next;
28221 // TODO(vicb):
28222 // assert((record._prev = null) === null);
28223 // assert((record._next = null) === null);
28224 if (prev === null) {
28225 this._itHead = next;
28226 }
28227 else {
28228 prev._next = next;
28229 }
28230 if (next === null) {
28231 this._itTail = prev;
28232 }
28233 else {
28234 next._prev = prev;
28235 }
28236 return record;
28237 }
28238 /** @internal */
28239 _addToMoves(record, toIndex) {
28240 // TODO(vicb):
28241 // assert(record._nextMoved === null);
28242 if (record.previousIndex === toIndex) {
28243 return record;
28244 }
28245 if (this._movesTail === null) {
28246 // TODO(vicb):
28247 // assert(_movesHead === null);
28248 this._movesTail = this._movesHead = record;
28249 }
28250 else {
28251 // TODO(vicb):
28252 // assert(_movesTail._nextMoved === null);
28253 this._movesTail = this._movesTail._nextMoved = record;
28254 }
28255 return record;
28256 }
28257 _addToRemovals(record) {
28258 if (this._unlinkedRecords === null) {
28259 this._unlinkedRecords = new _DuplicateMap();
28260 }
28261 this._unlinkedRecords.put(record);
28262 record.currentIndex = null;
28263 record._nextRemoved = null;
28264 if (this._removalsTail === null) {
28265 // TODO(vicb):
28266 // assert(_removalsHead === null);
28267 this._removalsTail = this._removalsHead = record;
28268 record._prevRemoved = null;
28269 }
28270 else {
28271 // TODO(vicb):
28272 // assert(_removalsTail._nextRemoved === null);
28273 // assert(record._nextRemoved === null);
28274 record._prevRemoved = this._removalsTail;
28275 this._removalsTail = this._removalsTail._nextRemoved = record;
28276 }
28277 return record;
28278 }
28279 /** @internal */
28280 _addIdentityChange(record, item) {
28281 record.item = item;
28282 if (this._identityChangesTail === null) {
28283 this._identityChangesTail = this._identityChangesHead = record;
28284 }
28285 else {
28286 this._identityChangesTail = this._identityChangesTail._nextIdentityChange = record;
28287 }
28288 return record;
28289 }
28290}
28291class IterableChangeRecord_ {
28292 constructor(item, trackById) {
28293 this.item = item;
28294 this.trackById = trackById;
28295 this.currentIndex = null;
28296 this.previousIndex = null;
28297 /** @internal */
28298 this._nextPrevious = null;
28299 /** @internal */
28300 this._prev = null;
28301 /** @internal */
28302 this._next = null;
28303 /** @internal */
28304 this._prevDup = null;
28305 /** @internal */
28306 this._nextDup = null;
28307 /** @internal */
28308 this._prevRemoved = null;
28309 /** @internal */
28310 this._nextRemoved = null;
28311 /** @internal */
28312 this._nextAdded = null;
28313 /** @internal */
28314 this._nextMoved = null;
28315 /** @internal */
28316 this._nextIdentityChange = null;
28317 }
28318}
28319// A linked list of IterableChangeRecords with the same IterableChangeRecord_.item
28320class _DuplicateItemRecordList {
28321 constructor() {
28322 /** @internal */
28323 this._head = null;
28324 /** @internal */
28325 this._tail = null;
28326 }
28327 /**
28328 * Append the record to the list of duplicates.
28329 *
28330 * Note: by design all records in the list of duplicates hold the same value in record.item.
28331 */
28332 add(record) {
28333 if (this._head === null) {
28334 this._head = this._tail = record;
28335 record._nextDup = null;
28336 record._prevDup = null;
28337 }
28338 else {
28339 // TODO(vicb):
28340 // assert(record.item == _head.item ||
28341 // record.item is num && record.item.isNaN && _head.item is num && _head.item.isNaN);
28342 this._tail._nextDup = record;
28343 record._prevDup = this._tail;
28344 record._nextDup = null;
28345 this._tail = record;
28346 }
28347 }
28348 // Returns a IterableChangeRecord_ having IterableChangeRecord_.trackById == trackById and
28349 // IterableChangeRecord_.currentIndex >= atOrAfterIndex
28350 get(trackById, atOrAfterIndex) {
28351 let record;
28352 for (record = this._head; record !== null; record = record._nextDup) {
28353 if ((atOrAfterIndex === null || atOrAfterIndex <= record.currentIndex) &&
28354 Object.is(record.trackById, trackById)) {
28355 return record;
28356 }
28357 }
28358 return null;
28359 }
28360 /**
28361 * Remove one {@link IterableChangeRecord_} from the list of duplicates.
28362 *
28363 * Returns whether the list of duplicates is empty.
28364 */
28365 remove(record) {
28366 // TODO(vicb):
28367 // assert(() {
28368 // // verify that the record being removed is in the list.
28369 // for (IterableChangeRecord_ cursor = _head; cursor != null; cursor = cursor._nextDup) {
28370 // if (identical(cursor, record)) return true;
28371 // }
28372 // return false;
28373 //});
28374 const prev = record._prevDup;
28375 const next = record._nextDup;
28376 if (prev === null) {
28377 this._head = next;
28378 }
28379 else {
28380 prev._nextDup = next;
28381 }
28382 if (next === null) {
28383 this._tail = prev;
28384 }
28385 else {
28386 next._prevDup = prev;
28387 }
28388 return this._head === null;
28389 }
28390}
28391class _DuplicateMap {
28392 constructor() {
28393 this.map = new Map();
28394 }
28395 put(record) {
28396 const key = record.trackById;
28397 let duplicates = this.map.get(key);
28398 if (!duplicates) {
28399 duplicates = new _DuplicateItemRecordList();
28400 this.map.set(key, duplicates);
28401 }
28402 duplicates.add(record);
28403 }
28404 /**
28405 * Retrieve the `value` using key. Because the IterableChangeRecord_ value may be one which we
28406 * have already iterated over, we use the `atOrAfterIndex` to pretend it is not there.
28407 *
28408 * Use case: `[a, b, c, a, a]` if we are at index `3` which is the second `a` then asking if we
28409 * have any more `a`s needs to return the second `a`.
28410 */
28411 get(trackById, atOrAfterIndex) {
28412 const key = trackById;
28413 const recordList = this.map.get(key);
28414 return recordList ? recordList.get(trackById, atOrAfterIndex) : null;
28415 }
28416 /**
28417 * Removes a {@link IterableChangeRecord_} from the list of duplicates.
28418 *
28419 * The list of duplicates also is removed from the map if it gets empty.
28420 */
28421 remove(record) {
28422 const key = record.trackById;
28423 const recordList = this.map.get(key);
28424 // Remove the list of duplicates when it gets empty
28425 if (recordList.remove(record)) {
28426 this.map.delete(key);
28427 }
28428 return record;
28429 }
28430 get isEmpty() {
28431 return this.map.size === 0;
28432 }
28433 clear() {
28434 this.map.clear();
28435 }
28436}
28437function getPreviousIndex(item, addRemoveOffset, moveOffsets) {
28438 const previousIndex = item.previousIndex;
28439 if (previousIndex === null)
28440 return previousIndex;
28441 let moveOffset = 0;
28442 if (moveOffsets && previousIndex < moveOffsets.length) {
28443 moveOffset = moveOffsets[previousIndex];
28444 }
28445 return previousIndex + addRemoveOffset + moveOffset;
28446}
28447
28448/**
28449 * @license
28450 * Copyright Google LLC All Rights Reserved.
28451 *
28452 * Use of this source code is governed by an MIT-style license that can be
28453 * found in the LICENSE file at https://angular.io/license
28454 */
28455class DefaultKeyValueDifferFactory {
28456 constructor() { }
28457 supports(obj) {
28458 return obj instanceof Map || isJsObject(obj);
28459 }
28460 create() {
28461 return new DefaultKeyValueDiffer();
28462 }
28463}
28464class DefaultKeyValueDiffer {
28465 constructor() {
28466 this._records = new Map();
28467 this._mapHead = null;
28468 // _appendAfter is used in the check loop
28469 this._appendAfter = null;
28470 this._previousMapHead = null;
28471 this._changesHead = null;
28472 this._changesTail = null;
28473 this._additionsHead = null;
28474 this._additionsTail = null;
28475 this._removalsHead = null;
28476 this._removalsTail = null;
28477 }
28478 get isDirty() {
28479 return this._additionsHead !== null || this._changesHead !== null ||
28480 this._removalsHead !== null;
28481 }
28482 forEachItem(fn) {
28483 let record;
28484 for (record = this._mapHead; record !== null; record = record._next) {
28485 fn(record);
28486 }
28487 }
28488 forEachPreviousItem(fn) {
28489 let record;
28490 for (record = this._previousMapHead; record !== null; record = record._nextPrevious) {
28491 fn(record);
28492 }
28493 }
28494 forEachChangedItem(fn) {
28495 let record;
28496 for (record = this._changesHead; record !== null; record = record._nextChanged) {
28497 fn(record);
28498 }
28499 }
28500 forEachAddedItem(fn) {
28501 let record;
28502 for (record = this._additionsHead; record !== null; record = record._nextAdded) {
28503 fn(record);
28504 }
28505 }
28506 forEachRemovedItem(fn) {
28507 let record;
28508 for (record = this._removalsHead; record !== null; record = record._nextRemoved) {
28509 fn(record);
28510 }
28511 }
28512 diff(map) {
28513 if (!map) {
28514 map = new Map();
28515 }
28516 else if (!(map instanceof Map || isJsObject(map))) {
28517 throw new Error(`Error trying to diff '${stringify(map)}'. Only maps and objects are allowed`);
28518 }
28519 return this.check(map) ? this : null;
28520 }
28521 onDestroy() { }
28522 /**
28523 * Check the current state of the map vs the previous.
28524 * The algorithm is optimised for when the keys do no change.
28525 */
28526 check(map) {
28527 this._reset();
28528 let insertBefore = this._mapHead;
28529 this._appendAfter = null;
28530 this._forEach(map, (value, key) => {
28531 if (insertBefore && insertBefore.key === key) {
28532 this._maybeAddToChanges(insertBefore, value);
28533 this._appendAfter = insertBefore;
28534 insertBefore = insertBefore._next;
28535 }
28536 else {
28537 const record = this._getOrCreateRecordForKey(key, value);
28538 insertBefore = this._insertBeforeOrAppend(insertBefore, record);
28539 }
28540 });
28541 // Items remaining at the end of the list have been deleted
28542 if (insertBefore) {
28543 if (insertBefore._prev) {
28544 insertBefore._prev._next = null;
28545 }
28546 this._removalsHead = insertBefore;
28547 for (let record = insertBefore; record !== null; record = record._nextRemoved) {
28548 if (record === this._mapHead) {
28549 this._mapHead = null;
28550 }
28551 this._records.delete(record.key);
28552 record._nextRemoved = record._next;
28553 record.previousValue = record.currentValue;
28554 record.currentValue = null;
28555 record._prev = null;
28556 record._next = null;
28557 }
28558 }
28559 // Make sure tails have no next records from previous runs
28560 if (this._changesTail)
28561 this._changesTail._nextChanged = null;
28562 if (this._additionsTail)
28563 this._additionsTail._nextAdded = null;
28564 return this.isDirty;
28565 }
28566 /**
28567 * Inserts a record before `before` or append at the end of the list when `before` is null.
28568 *
28569 * Notes:
28570 * - This method appends at `this._appendAfter`,
28571 * - This method updates `this._appendAfter`,
28572 * - The return value is the new value for the insertion pointer.
28573 */
28574 _insertBeforeOrAppend(before, record) {
28575 if (before) {
28576 const prev = before._prev;
28577 record._next = before;
28578 record._prev = prev;
28579 before._prev = record;
28580 if (prev) {
28581 prev._next = record;
28582 }
28583 if (before === this._mapHead) {
28584 this._mapHead = record;
28585 }
28586 this._appendAfter = before;
28587 return before;
28588 }
28589 if (this._appendAfter) {
28590 this._appendAfter._next = record;
28591 record._prev = this._appendAfter;
28592 }
28593 else {
28594 this._mapHead = record;
28595 }
28596 this._appendAfter = record;
28597 return null;
28598 }
28599 _getOrCreateRecordForKey(key, value) {
28600 if (this._records.has(key)) {
28601 const record = this._records.get(key);
28602 this._maybeAddToChanges(record, value);
28603 const prev = record._prev;
28604 const next = record._next;
28605 if (prev) {
28606 prev._next = next;
28607 }
28608 if (next) {
28609 next._prev = prev;
28610 }
28611 record._next = null;
28612 record._prev = null;
28613 return record;
28614 }
28615 const record = new KeyValueChangeRecord_(key);
28616 this._records.set(key, record);
28617 record.currentValue = value;
28618 this._addToAdditions(record);
28619 return record;
28620 }
28621 /** @internal */
28622 _reset() {
28623 if (this.isDirty) {
28624 let record;
28625 // let `_previousMapHead` contain the state of the map before the changes
28626 this._previousMapHead = this._mapHead;
28627 for (record = this._previousMapHead; record !== null; record = record._next) {
28628 record._nextPrevious = record._next;
28629 }
28630 // Update `record.previousValue` with the value of the item before the changes
28631 // We need to update all changed items (that's those which have been added and changed)
28632 for (record = this._changesHead; record !== null; record = record._nextChanged) {
28633 record.previousValue = record.currentValue;
28634 }
28635 for (record = this._additionsHead; record != null; record = record._nextAdded) {
28636 record.previousValue = record.currentValue;
28637 }
28638 this._changesHead = this._changesTail = null;
28639 this._additionsHead = this._additionsTail = null;
28640 this._removalsHead = null;
28641 }
28642 }
28643 // Add the record or a given key to the list of changes only when the value has actually changed
28644 _maybeAddToChanges(record, newValue) {
28645 if (!Object.is(newValue, record.currentValue)) {
28646 record.previousValue = record.currentValue;
28647 record.currentValue = newValue;
28648 this._addToChanges(record);
28649 }
28650 }
28651 _addToAdditions(record) {
28652 if (this._additionsHead === null) {
28653 this._additionsHead = this._additionsTail = record;
28654 }
28655 else {
28656 this._additionsTail._nextAdded = record;
28657 this._additionsTail = record;
28658 }
28659 }
28660 _addToChanges(record) {
28661 if (this._changesHead === null) {
28662 this._changesHead = this._changesTail = record;
28663 }
28664 else {
28665 this._changesTail._nextChanged = record;
28666 this._changesTail = record;
28667 }
28668 }
28669 /** @internal */
28670 _forEach(obj, fn) {
28671 if (obj instanceof Map) {
28672 obj.forEach(fn);
28673 }
28674 else {
28675 Object.keys(obj).forEach(k => fn(obj[k], k));
28676 }
28677 }
28678}
28679class KeyValueChangeRecord_ {
28680 constructor(key) {
28681 this.key = key;
28682 this.previousValue = null;
28683 this.currentValue = null;
28684 /** @internal */
28685 this._nextPrevious = null;
28686 /** @internal */
28687 this._next = null;
28688 /** @internal */
28689 this._prev = null;
28690 /** @internal */
28691 this._nextAdded = null;
28692 /** @internal */
28693 this._nextRemoved = null;
28694 /** @internal */
28695 this._nextChanged = null;
28696 }
28697}
28698
28699/**
28700 * @license
28701 * Copyright Google LLC All Rights Reserved.
28702 *
28703 * Use of this source code is governed by an MIT-style license that can be
28704 * found in the LICENSE file at https://angular.io/license
28705 */
28706function defaultIterableDiffersFactory() {
28707 return new IterableDiffers([new DefaultIterableDifferFactory()]);
28708}
28709/**
28710 * A repository of different iterable diffing strategies used by NgFor, NgClass, and others.
28711 *
28712 * @publicApi
28713 */
28714class IterableDiffers {
28715 constructor(factories) {
28716 this.factories = factories;
28717 }
28718 static create(factories, parent) {
28719 if (parent != null) {
28720 const copied = parent.factories.slice();
28721 factories = factories.concat(copied);
28722 }
28723 return new IterableDiffers(factories);
28724 }
28725 /**
28726 * Takes an array of {@link IterableDifferFactory} and returns a provider used to extend the
28727 * inherited {@link IterableDiffers} instance with the provided factories and return a new
28728 * {@link IterableDiffers} instance.
28729 *
28730 * @usageNotes
28731 * ### Example
28732 *
28733 * The following example shows how to extend an existing list of factories,
28734 * which will only be applied to the injector for this component and its children.
28735 * This step is all that's required to make a new {@link IterableDiffer} available.
28736 *
28737 * ```
28738 * @Component({
28739 * viewProviders: [
28740 * IterableDiffers.extend([new ImmutableListDiffer()])
28741 * ]
28742 * })
28743 * ```
28744 */
28745 static extend(factories) {
28746 return {
28747 provide: IterableDiffers,
28748 useFactory: (parent) => {
28749 // if parent is null, it means that we are in the root injector and we have just overridden
28750 // the default injection mechanism for IterableDiffers, in such a case just assume
28751 // `defaultIterableDiffersFactory`.
28752 return IterableDiffers.create(factories, parent || defaultIterableDiffersFactory());
28753 },
28754 // Dependency technically isn't optional, but we can provide a better error message this way.
28755 deps: [[IterableDiffers, new SkipSelf(), new Optional()]]
28756 };
28757 }
28758 find(iterable) {
28759 const factory = this.factories.find(f => f.supports(iterable));
28760 if (factory != null) {
28761 return factory;
28762 }
28763 else {
28764 throw new Error(`Cannot find a differ supporting object '${iterable}' of type '${getTypeNameForDebugging(iterable)}'`);
28765 }
28766 }
28767}
28768/** @nocollapse */
28769IterableDiffers.ɵprov = ɵɵdefineInjectable({ token: IterableDiffers, providedIn: 'root', factory: defaultIterableDiffersFactory });
28770function getTypeNameForDebugging(type) {
28771 return type['name'] || typeof type;
28772}
28773
28774/**
28775 * @license
28776 * Copyright Google LLC All Rights Reserved.
28777 *
28778 * Use of this source code is governed by an MIT-style license that can be
28779 * found in the LICENSE file at https://angular.io/license
28780 */
28781function defaultKeyValueDiffersFactory() {
28782 return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
28783}
28784/**
28785 * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
28786 *
28787 * @publicApi
28788 */
28789class KeyValueDiffers {
28790 constructor(factories) {
28791 this.factories = factories;
28792 }
28793 static create(factories, parent) {
28794 if (parent) {
28795 const copied = parent.factories.slice();
28796 factories = factories.concat(copied);
28797 }
28798 return new KeyValueDiffers(factories);
28799 }
28800 /**
28801 * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the
28802 * inherited {@link KeyValueDiffers} instance with the provided factories and return a new
28803 * {@link KeyValueDiffers} instance.
28804 *
28805 * @usageNotes
28806 * ### Example
28807 *
28808 * The following example shows how to extend an existing list of factories,
28809 * which will only be applied to the injector for this component and its children.
28810 * This step is all that's required to make a new {@link KeyValueDiffer} available.
28811 *
28812 * ```
28813 * @Component({
28814 * viewProviders: [
28815 * KeyValueDiffers.extend([new ImmutableMapDiffer()])
28816 * ]
28817 * })
28818 * ```
28819 */
28820 static extend(factories) {
28821 return {
28822 provide: KeyValueDiffers,
28823 useFactory: (parent) => {
28824 // if parent is null, it means that we are in the root injector and we have just overridden
28825 // the default injection mechanism for KeyValueDiffers, in such a case just assume
28826 // `defaultKeyValueDiffersFactory`.
28827 return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
28828 },
28829 // Dependency technically isn't optional, but we can provide a better error message this way.
28830 deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
28831 };
28832 }
28833 find(kv) {
28834 const factory = this.factories.find(f => f.supports(kv));
28835 if (factory) {
28836 return factory;
28837 }
28838 throw new Error(`Cannot find a differ supporting object '${kv}'`);
28839 }
28840}
28841/** @nocollapse */
28842KeyValueDiffers.ɵprov = ɵɵdefineInjectable({ token: KeyValueDiffers, providedIn: 'root', factory: defaultKeyValueDiffersFactory });
28843
28844/**
28845 * @license
28846 * Copyright Google LLC All Rights Reserved.
28847 *
28848 * Use of this source code is governed by an MIT-style license that can be
28849 * found in the LICENSE file at https://angular.io/license
28850 */
28851/**
28852 * Structural diffing for `Object`s and `Map`s.
28853 */
28854const keyValDiff = [new DefaultKeyValueDifferFactory()];
28855/**
28856 * Structural diffing for `Iterable` types such as `Array`s.
28857 */
28858const iterableDiff = [new DefaultIterableDifferFactory()];
28859const defaultIterableDiffers = new IterableDiffers(iterableDiff);
28860const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
28861
28862/**
28863 * @license
28864 * Copyright Google LLC All Rights Reserved.
28865 *
28866 * Use of this source code is governed by an MIT-style license that can be
28867 * found in the LICENSE file at https://angular.io/license
28868 */
28869
28870/**
28871 * @license
28872 * Copyright Google LLC All Rights Reserved.
28873 *
28874 * Use of this source code is governed by an MIT-style license that can be
28875 * found in the LICENSE file at https://angular.io/license
28876 */
28877const _CORE_PLATFORM_PROVIDERS = [
28878 // Set a default platform name for platforms that don't set it explicitly.
28879 { provide: PLATFORM_ID, useValue: 'unknown' },
28880 { provide: PlatformRef, deps: [Injector] },
28881 { provide: TestabilityRegistry, deps: [] },
28882 { provide: Console, deps: [] },
28883];
28884/**
28885 * This platform has to be included in any other platform
28886 *
28887 * @publicApi
28888 */
28889const platformCore = createPlatformFactory(null, 'core', _CORE_PLATFORM_PROVIDERS);
28890
28891/**
28892 * @license
28893 * Copyright Google LLC All Rights Reserved.
28894 *
28895 * Use of this source code is governed by an MIT-style license that can be
28896 * found in the LICENSE file at https://angular.io/license
28897 */
28898function _iterableDiffersFactory() {
28899 return defaultIterableDiffers;
28900}
28901function _keyValueDiffersFactory() {
28902 return defaultKeyValueDiffers;
28903}
28904function _localeFactory(locale) {
28905 return locale || getGlobalLocale();
28906}
28907/**
28908 * Work out the locale from the potential global properties.
28909 *
28910 * * Closure Compiler: use `goog.getLocale()`.
28911 * * Ivy enabled: use `$localize.locale`
28912 */
28913function getGlobalLocale() {
28914 if (typeof ngI18nClosureMode !== 'undefined' && ngI18nClosureMode &&
28915 typeof goog !== 'undefined' && goog.getLocale() !== 'en') {
28916 // * The default `goog.getLocale()` value is `en`, while Angular used `en-US`.
28917 // * In order to preserve backwards compatibility, we use Angular default value over
28918 // Closure Compiler's one.
28919 return goog.getLocale();
28920 }
28921 else {
28922 // KEEP `typeof $localize !== 'undefined' && $localize.locale` IN SYNC WITH THE LOCALIZE
28923 // COMPILE-TIME INLINER.
28924 //
28925 // * During compile time inlining of translations the expression will be replaced
28926 // with a string literal that is the current locale. Other forms of this expression are not
28927 // guaranteed to be replaced.
28928 //
28929 // * During runtime translation evaluation, the developer is required to set `$localize.locale`
28930 // if required, or just to provide their own `LOCALE_ID` provider.
28931 return (ivyEnabled && typeof $localize !== 'undefined' && $localize.locale) ||
28932 DEFAULT_LOCALE_ID;
28933 }
28934}
28935/**
28936 * A built-in [dependency injection token](guide/glossary#di-token)
28937 * that is used to configure the root injector for bootstrapping.
28938 */
28939const APPLICATION_MODULE_PROVIDERS = [
28940 {
28941 provide: ApplicationRef,
28942 useClass: ApplicationRef,
28943 deps: [NgZone, Injector, ErrorHandler, ComponentFactoryResolver$1, ApplicationInitStatus]
28944 },
28945 { provide: SCHEDULER, deps: [NgZone], useFactory: zoneSchedulerFactory },
28946 {
28947 provide: ApplicationInitStatus,
28948 useClass: ApplicationInitStatus,
28949 deps: [[new Optional(), APP_INITIALIZER]]
28950 },
28951 { provide: Compiler, useClass: Compiler, deps: [] },
28952 APP_ID_RANDOM_PROVIDER,
28953 { provide: IterableDiffers, useFactory: _iterableDiffersFactory, deps: [] },
28954 { provide: KeyValueDiffers, useFactory: _keyValueDiffersFactory, deps: [] },
28955 {
28956 provide: LOCALE_ID,
28957 useFactory: _localeFactory,
28958 deps: [[new Inject(LOCALE_ID), new Optional(), new SkipSelf()]]
28959 },
28960 { provide: DEFAULT_CURRENCY_CODE, useValue: USD_CURRENCY_CODE },
28961];
28962/**
28963 * Schedule work at next available slot.
28964 *
28965 * In Ivy this is just `requestAnimationFrame`. For compatibility reasons when bootstrapped
28966 * using `platformRef.bootstrap` we need to use `NgZone.onStable` as the scheduling mechanism.
28967 * This overrides the scheduling mechanism in Ivy to `NgZone.onStable`.
28968 *
28969 * @param ngZone NgZone to use for scheduling.
28970 */
28971function zoneSchedulerFactory(ngZone) {
28972 let queue = [];
28973 ngZone.onStable.subscribe(() => {
28974 while (queue.length) {
28975 queue.pop()();
28976 }
28977 });
28978 return function (fn) {
28979 queue.push(fn);
28980 };
28981}
28982/**
28983 * Configures the root injector for an app with
28984 * providers of `@angular/core` dependencies that `ApplicationRef` needs
28985 * to bootstrap components.
28986 *
28987 * Re-exported by `BrowserModule`, which is included automatically in the root
28988 * `AppModule` when you create a new app with the CLI `new` command.
28989 *
28990 * @publicApi
28991 */
28992class ApplicationModule {
28993 // Inject ApplicationRef to make it eager...
28994 constructor(appRef) { }
28995}
28996ApplicationModule.ɵfac = function ApplicationModule_Factory(t) { return new (t || ApplicationModule)(ɵɵinject(ApplicationRef)); };
28997ApplicationModule.ɵmod = /*@__PURE__*/ ɵɵdefineNgModule({ type: ApplicationModule });
28998ApplicationModule.ɵinj = /*@__PURE__*/ ɵɵdefineInjector({ providers: APPLICATION_MODULE_PROVIDERS });
28999(function () {
29000 (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
29001 type: NgModule,
29002 args: [{ providers: APPLICATION_MODULE_PROVIDERS }]
29003 }], function () { return [{ type: ApplicationRef }]; }, null);
29004})();
29005
29006/**
29007 * @license
29008 * Copyright Google LLC All Rights Reserved.
29009 *
29010 * Use of this source code is governed by an MIT-style license that can be
29011 * found in the LICENSE file at https://angular.io/license
29012 */
29013// Called before each cycle of a view's check to detect whether this is in the
29014// initState for which we need to call ngOnInit, ngAfterContentInit or ngAfterViewInit
29015// lifecycle methods. Returns true if this check cycle should call lifecycle
29016// methods.
29017function shiftInitState(view, priorInitState, newInitState) {
29018 // Only update the InitState if we are currently in the prior state.
29019 // For example, only move into CallingInit if we are in BeforeInit. Only
29020 // move into CallingContentInit if we are in CallingInit. Normally this will
29021 // always be true because of how checkCycle is called in checkAndUpdateView.
29022 // However, if checkAndUpdateView is called recursively or if an exception is
29023 // thrown while checkAndUpdateView is running, checkAndUpdateView starts over
29024 // from the beginning. This ensures the state is monotonically increasing,
29025 // terminating in the AfterInit state, which ensures the Init methods are called
29026 // at least once and only once.
29027 const state = view.state;
29028 const initState = state & 1792 /* InitState_Mask */;
29029 if (initState === priorInitState) {
29030 view.state = (state & ~1792 /* InitState_Mask */) | newInitState;
29031 view.initIndex = -1;
29032 return true;
29033 }
29034 return initState === newInitState;
29035}
29036// Returns true if the lifecycle init method should be called for the node with
29037// the given init index.
29038function shouldCallLifecycleInitHook(view, initState, index) {
29039 if ((view.state & 1792 /* InitState_Mask */) === initState && view.initIndex <= index) {
29040 view.initIndex = index + 1;
29041 return true;
29042 }
29043 return false;
29044}
29045/**
29046 * Node instance data.
29047 *
29048 * We have a separate type per NodeType to save memory
29049 * (TextData | ElementData | ProviderData | PureExpressionData | QueryList<any>)
29050 *
29051 * To keep our code monomorphic,
29052 * we prohibit using `NodeData` directly but enforce the use of accessors (`asElementData`, ...).
29053 * This way, no usage site can get a `NodeData` from view.nodes and then use it for different
29054 * purposes.
29055 */
29056class NodeData {
29057}
29058/**
29059 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29060 */
29061function asTextData(view, index) {
29062 return view.nodes[index];
29063}
29064/**
29065 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29066 */
29067function asElementData(view, index) {
29068 return view.nodes[index];
29069}
29070/**
29071 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29072 */
29073function asProviderData(view, index) {
29074 return view.nodes[index];
29075}
29076/**
29077 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29078 */
29079function asPureExpressionData(view, index) {
29080 return view.nodes[index];
29081}
29082/**
29083 * Accessor for view.nodes, enforcing that every usage site stays monomorphic.
29084 */
29085function asQueryList(view, index) {
29086 return view.nodes[index];
29087}
29088class DebugContext {
29089}
29090/**
29091 * This object is used to prevent cycles in the source files and to have a place where
29092 * debug mode can hook it. It is lazily filled when `isDevMode` is known.
29093 */
29094const Services = {
29095 setCurrentNode: undefined,
29096 createRootView: undefined,
29097 createEmbeddedView: undefined,
29098 createComponentView: undefined,
29099 createNgModuleRef: undefined,
29100 overrideProvider: undefined,
29101 overrideComponentView: undefined,
29102 clearOverrides: undefined,
29103 checkAndUpdateView: undefined,
29104 checkNoChangesView: undefined,
29105 destroyView: undefined,
29106 resolveDep: undefined,
29107 createDebugContext: undefined,
29108 handleEvent: undefined,
29109 updateDirectives: undefined,
29110 updateRenderer: undefined,
29111 dirtyParentQueries: undefined,
29112};
29113
29114/**
29115 * @license
29116 * Copyright Google LLC All Rights Reserved.
29117 *
29118 * Use of this source code is governed by an MIT-style license that can be
29119 * found in the LICENSE file at https://angular.io/license
29120 */
29121function expressionChangedAfterItHasBeenCheckedError(context, oldValue, currValue, isFirstCheck) {
29122 let msg = `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '${oldValue}'. Current value: '${currValue}'.`;
29123 if (isFirstCheck) {
29124 msg +=
29125 ` It seems like the view has been created after its parent and its children have been dirty checked.` +
29126 ` Has it been created in a change detection hook ?`;
29127 }
29128 return viewDebugError(msg, context);
29129}
29130function viewWrappedDebugError(err, context) {
29131 if (!(err instanceof Error)) {
29132 // errors that are not Error instances don't have a stack,
29133 // so it is ok to wrap them into a new Error object...
29134 err = new Error(err.toString());
29135 }
29136 _addDebugContext(err, context);
29137 return err;
29138}
29139function viewDebugError(msg, context) {
29140 const err = new Error(msg);
29141 _addDebugContext(err, context);
29142 return err;
29143}
29144function _addDebugContext(err, context) {
29145 err[ERROR_DEBUG_CONTEXT] = context;
29146 err[ERROR_LOGGER] = context.logError.bind(context);
29147}
29148function isViewDebugError(err) {
29149 return !!getDebugContext(err);
29150}
29151function viewDestroyedError(action) {
29152 return new Error(`ViewDestroyedError: Attempt to use a destroyed view: ${action}`);
29153}
29154
29155/**
29156 * @license
29157 * Copyright Google LLC All Rights Reserved.
29158 *
29159 * Use of this source code is governed by an MIT-style license that can be
29160 * found in the LICENSE file at https://angular.io/license
29161 */
29162const NOOP = () => { };
29163const _tokenKeyCache = new Map();
29164function tokenKey(token) {
29165 let key = _tokenKeyCache.get(token);
29166 if (!key) {
29167 key = stringify(token) + '_' + _tokenKeyCache.size;
29168 _tokenKeyCache.set(token, key);
29169 }
29170 return key;
29171}
29172const UNDEFINED_RENDERER_TYPE_ID = '$$undefined';
29173const EMPTY_RENDERER_TYPE_ID = '$$empty';
29174// Attention: this function is called as top level function.
29175// Putting any logic in here will destroy closure tree shaking!
29176function createRendererType2(values) {
29177 return {
29178 id: UNDEFINED_RENDERER_TYPE_ID,
29179 styles: values.styles,
29180 encapsulation: values.encapsulation,
29181 data: values.data
29182 };
29183}
29184let _renderCompCount = 0;
29185function resolveRendererType2(type) {
29186 if (type && type.id === UNDEFINED_RENDERER_TYPE_ID) {
29187 // first time we see this RendererType2. Initialize it...
29188 const isFilled = ((type.encapsulation != null && type.encapsulation !== ViewEncapsulation$1.None) ||
29189 type.styles.length || Object.keys(type.data).length);
29190 if (isFilled) {
29191 type.id = `c${_renderCompCount++}`;
29192 }
29193 else {
29194 type.id = EMPTY_RENDERER_TYPE_ID;
29195 }
29196 }
29197 if (type && type.id === EMPTY_RENDERER_TYPE_ID) {
29198 type = null;
29199 }
29200 return type || null;
29201}
29202function checkBinding(view, def, bindingIdx, value) {
29203 const oldValues = view.oldValues;
29204 if ((view.state & 2 /* FirstCheck */) ||
29205 !Object.is(oldValues[def.bindingIndex + bindingIdx], value)) {
29206 return true;
29207 }
29208 return false;
29209}
29210function checkAndUpdateBinding(view, def, bindingIdx, value) {
29211 if (checkBinding(view, def, bindingIdx, value)) {
29212 view.oldValues[def.bindingIndex + bindingIdx] = value;
29213 return true;
29214 }
29215 return false;
29216}
29217function checkBindingNoChanges(view, def, bindingIdx, value) {
29218 const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
29219 if ((view.state & 1 /* BeforeFirstCheck */) || !devModeEqual(oldValue, value)) {
29220 const bindingName = def.bindings[bindingIdx].name;
29221 throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, def.nodeIndex), `${bindingName}: ${oldValue}`, `${bindingName}: ${value}`, (view.state & 1 /* BeforeFirstCheck */) !== 0);
29222 }
29223}
29224function markParentViewsForCheck(view) {
29225 let currView = view;
29226 while (currView) {
29227 if (currView.def.flags & 2 /* OnPush */) {
29228 currView.state |= 8 /* ChecksEnabled */;
29229 }
29230 currView = currView.viewContainerParent || currView.parent;
29231 }
29232}
29233function markParentViewsForCheckProjectedViews(view, endView) {
29234 let currView = view;
29235 while (currView && currView !== endView) {
29236 currView.state |= 64 /* CheckProjectedViews */;
29237 currView = currView.viewContainerParent || currView.parent;
29238 }
29239}
29240function dispatchEvent(view, nodeIndex, eventName, event) {
29241 try {
29242 const nodeDef = view.def.nodes[nodeIndex];
29243 const startView = nodeDef.flags & 33554432 /* ComponentView */ ?
29244 asElementData(view, nodeIndex).componentView :
29245 view;
29246 markParentViewsForCheck(startView);
29247 return Services.handleEvent(view, nodeIndex, eventName, event);
29248 }
29249 catch (e) {
29250 // Attention: Don't rethrow, as it would cancel Observable subscriptions!
29251 view.root.errorHandler.handleError(e);
29252 }
29253}
29254function declaredViewContainer(view) {
29255 if (view.parent) {
29256 const parentView = view.parent;
29257 return asElementData(parentView, view.parentNodeDef.nodeIndex);
29258 }
29259 return null;
29260}
29261/**
29262 * for component views, this is the host element.
29263 * for embedded views, this is the index of the parent node
29264 * that contains the view container.
29265 */
29266function viewParentEl(view) {
29267 const parentView = view.parent;
29268 if (parentView) {
29269 return view.parentNodeDef.parent;
29270 }
29271 else {
29272 return null;
29273 }
29274}
29275function renderNode(view, def) {
29276 switch (def.flags & 201347067 /* Types */) {
29277 case 1 /* TypeElement */:
29278 return asElementData(view, def.nodeIndex).renderElement;
29279 case 2 /* TypeText */:
29280 return asTextData(view, def.nodeIndex).renderText;
29281 }
29282}
29283function elementEventFullName(target, name) {
29284 return target ? `${target}:${name}` : name;
29285}
29286function isComponentView(view) {
29287 return !!view.parent && !!(view.parentNodeDef.flags & 32768 /* Component */);
29288}
29289function isEmbeddedView(view) {
29290 return !!view.parent && !(view.parentNodeDef.flags & 32768 /* Component */);
29291}
29292function filterQueryId(queryId) {
29293 return 1 << (queryId % 32);
29294}
29295function splitMatchedQueriesDsl(matchedQueriesDsl) {
29296 const matchedQueries = {};
29297 let matchedQueryIds = 0;
29298 const references = {};
29299 if (matchedQueriesDsl) {
29300 matchedQueriesDsl.forEach(([queryId, valueType]) => {
29301 if (typeof queryId === 'number') {
29302 matchedQueries[queryId] = valueType;
29303 matchedQueryIds |= filterQueryId(queryId);
29304 }
29305 else {
29306 references[queryId] = valueType;
29307 }
29308 });
29309 }
29310 return { matchedQueries, references, matchedQueryIds };
29311}
29312function splitDepsDsl(deps, sourceName) {
29313 return deps.map(value => {
29314 let token;
29315 let flags;
29316 if (Array.isArray(value)) {
29317 [flags, token] = value;
29318 }
29319 else {
29320 flags = 0 /* None */;
29321 token = value;
29322 }
29323 if (token && (typeof token === 'function' || typeof token === 'object') && sourceName) {
29324 Object.defineProperty(token, SOURCE, { value: sourceName, configurable: true });
29325 }
29326 return { flags, token, tokenKey: tokenKey(token) };
29327 });
29328}
29329function getParentRenderElement(view, renderHost, def) {
29330 let renderParent = def.renderParent;
29331 if (renderParent) {
29332 if ((renderParent.flags & 1 /* TypeElement */) === 0 ||
29333 (renderParent.flags & 33554432 /* ComponentView */) === 0 ||
29334 (renderParent.element.componentRendererType &&
29335 (renderParent.element.componentRendererType.encapsulation ===
29336 ViewEncapsulation$1.ShadowDom ||
29337 // TODO(FW-2290): remove the `encapsulation === 1` fallback logic in v12.
29338 // @ts-ignore TODO: Remove as part of FW-2290. TS complains about us dealing with an enum
29339 // value that is not known (but previously was the value for ViewEncapsulation.Native)
29340 renderParent.element.componentRendererType.encapsulation === 1))) {
29341 // only children of non components, or children of components with native encapsulation should
29342 // be attached.
29343 return asElementData(view, def.renderParent.nodeIndex).renderElement;
29344 }
29345 }
29346 else {
29347 return renderHost;
29348 }
29349}
29350const DEFINITION_CACHE = new WeakMap();
29351function resolveDefinition(factory) {
29352 let value = DEFINITION_CACHE.get(factory);
29353 if (!value) {
29354 value = factory(() => NOOP);
29355 value.factory = factory;
29356 DEFINITION_CACHE.set(factory, value);
29357 }
29358 return value;
29359}
29360function rootRenderNodes(view) {
29361 const renderNodes = [];
29362 visitRootRenderNodes(view, 0 /* Collect */, undefined, undefined, renderNodes);
29363 return renderNodes;
29364}
29365function visitRootRenderNodes(view, action, parentNode, nextSibling, target) {
29366 // We need to re-compute the parent node in case the nodes have been moved around manually
29367 if (action === 3 /* RemoveChild */) {
29368 parentNode = view.renderer.parentNode(renderNode(view, view.def.lastRenderRootNode));
29369 }
29370 visitSiblingRenderNodes(view, action, 0, view.def.nodes.length - 1, parentNode, nextSibling, target);
29371}
29372function visitSiblingRenderNodes(view, action, startIndex, endIndex, parentNode, nextSibling, target) {
29373 for (let i = startIndex; i <= endIndex; i++) {
29374 const nodeDef = view.def.nodes[i];
29375 if (nodeDef.flags & (1 /* TypeElement */ | 2 /* TypeText */ | 8 /* TypeNgContent */)) {
29376 visitRenderNode(view, nodeDef, action, parentNode, nextSibling, target);
29377 }
29378 // jump to next sibling
29379 i += nodeDef.childCount;
29380 }
29381}
29382function visitProjectedRenderNodes(view, ngContentIndex, action, parentNode, nextSibling, target) {
29383 let compView = view;
29384 while (compView && !isComponentView(compView)) {
29385 compView = compView.parent;
29386 }
29387 const hostView = compView.parent;
29388 const hostElDef = viewParentEl(compView);
29389 const startIndex = hostElDef.nodeIndex + 1;
29390 const endIndex = hostElDef.nodeIndex + hostElDef.childCount;
29391 for (let i = startIndex; i <= endIndex; i++) {
29392 const nodeDef = hostView.def.nodes[i];
29393 if (nodeDef.ngContentIndex === ngContentIndex) {
29394 visitRenderNode(hostView, nodeDef, action, parentNode, nextSibling, target);
29395 }
29396 // jump to next sibling
29397 i += nodeDef.childCount;
29398 }
29399 if (!hostView.parent) {
29400 // a root view
29401 const projectedNodes = view.root.projectableNodes[ngContentIndex];
29402 if (projectedNodes) {
29403 for (let i = 0; i < projectedNodes.length; i++) {
29404 execRenderNodeAction(view, projectedNodes[i], action, parentNode, nextSibling, target);
29405 }
29406 }
29407 }
29408}
29409function visitRenderNode(view, nodeDef, action, parentNode, nextSibling, target) {
29410 if (nodeDef.flags & 8 /* TypeNgContent */) {
29411 visitProjectedRenderNodes(view, nodeDef.ngContent.index, action, parentNode, nextSibling, target);
29412 }
29413 else {
29414 const rn = renderNode(view, nodeDef);
29415 if (action === 3 /* RemoveChild */ && (nodeDef.flags & 33554432 /* ComponentView */) &&
29416 (nodeDef.bindingFlags & 48 /* CatSyntheticProperty */)) {
29417 // Note: we might need to do both actions.
29418 if (nodeDef.bindingFlags & (16 /* SyntheticProperty */)) {
29419 execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
29420 }
29421 if (nodeDef.bindingFlags & (32 /* SyntheticHostProperty */)) {
29422 const compView = asElementData(view, nodeDef.nodeIndex).componentView;
29423 execRenderNodeAction(compView, rn, action, parentNode, nextSibling, target);
29424 }
29425 }
29426 else {
29427 execRenderNodeAction(view, rn, action, parentNode, nextSibling, target);
29428 }
29429 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
29430 const embeddedViews = asElementData(view, nodeDef.nodeIndex).viewContainer._embeddedViews;
29431 for (let k = 0; k < embeddedViews.length; k++) {
29432 visitRootRenderNodes(embeddedViews[k], action, parentNode, nextSibling, target);
29433 }
29434 }
29435 if (nodeDef.flags & 1 /* TypeElement */ && !nodeDef.element.name) {
29436 visitSiblingRenderNodes(view, action, nodeDef.nodeIndex + 1, nodeDef.nodeIndex + nodeDef.childCount, parentNode, nextSibling, target);
29437 }
29438 }
29439}
29440function execRenderNodeAction(view, renderNode, action, parentNode, nextSibling, target) {
29441 const renderer = view.renderer;
29442 switch (action) {
29443 case 1 /* AppendChild */:
29444 renderer.appendChild(parentNode, renderNode);
29445 break;
29446 case 2 /* InsertBefore */:
29447 renderer.insertBefore(parentNode, renderNode, nextSibling);
29448 break;
29449 case 3 /* RemoveChild */:
29450 renderer.removeChild(parentNode, renderNode);
29451 break;
29452 case 0 /* Collect */:
29453 target.push(renderNode);
29454 break;
29455 }
29456}
29457const NS_PREFIX_RE = /^:([^:]+):(.+)$/;
29458function splitNamespace(name) {
29459 if (name[0] === ':') {
29460 const match = name.match(NS_PREFIX_RE);
29461 return [match[1], match[2]];
29462 }
29463 return ['', name];
29464}
29465function calcBindingFlags(bindings) {
29466 let flags = 0;
29467 for (let i = 0; i < bindings.length; i++) {
29468 flags |= bindings[i].flags;
29469 }
29470 return flags;
29471}
29472function interpolate(valueCount, constAndInterp) {
29473 let result = '';
29474 for (let i = 0; i < valueCount * 2; i = i + 2) {
29475 result = result + constAndInterp[i] + _toStringWithNull(constAndInterp[i + 1]);
29476 }
29477 return result + constAndInterp[valueCount * 2];
29478}
29479function inlineInterpolate(valueCount, c0, a1, c1, a2, c2, a3, c3, a4, c4, a5, c5, a6, c6, a7, c7, a8, c8, a9, c9) {
29480 switch (valueCount) {
29481 case 1:
29482 return c0 + _toStringWithNull(a1) + c1;
29483 case 2:
29484 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2;
29485 case 3:
29486 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29487 c3;
29488 case 4:
29489 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29490 c3 + _toStringWithNull(a4) + c4;
29491 case 5:
29492 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29493 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5;
29494 case 6:
29495 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29496 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) + c6;
29497 case 7:
29498 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29499 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
29500 c6 + _toStringWithNull(a7) + c7;
29501 case 8:
29502 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29503 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
29504 c6 + _toStringWithNull(a7) + c7 + _toStringWithNull(a8) + c8;
29505 case 9:
29506 return c0 + _toStringWithNull(a1) + c1 + _toStringWithNull(a2) + c2 + _toStringWithNull(a3) +
29507 c3 + _toStringWithNull(a4) + c4 + _toStringWithNull(a5) + c5 + _toStringWithNull(a6) +
29508 c6 + _toStringWithNull(a7) + c7 + _toStringWithNull(a8) + c8 + _toStringWithNull(a9) + c9;
29509 default:
29510 throw new Error(`Does not support more than 9 expressions`);
29511 }
29512}
29513function _toStringWithNull(v) {
29514 return v != null ? v.toString() : '';
29515}
29516const EMPTY_MAP = {};
29517
29518/**
29519 * @license
29520 * Copyright Google LLC All Rights Reserved.
29521 *
29522 * Use of this source code is governed by an MIT-style license that can be
29523 * found in the LICENSE file at https://angular.io/license
29524 */
29525function anchorDef(flags, matchedQueriesDsl, ngContentIndex, childCount, handleEvent, templateFactory) {
29526 flags |= 1 /* TypeElement */;
29527 const { matchedQueries, references, matchedQueryIds } = splitMatchedQueriesDsl(matchedQueriesDsl);
29528 const template = templateFactory ? resolveDefinition(templateFactory) : null;
29529 return {
29530 // will bet set by the view definition
29531 nodeIndex: -1,
29532 parent: null,
29533 renderParent: null,
29534 bindingIndex: -1,
29535 outputIndex: -1,
29536 // regular values
29537 flags,
29538 checkIndex: -1,
29539 childFlags: 0,
29540 directChildFlags: 0,
29541 childMatchedQueries: 0,
29542 matchedQueries,
29543 matchedQueryIds,
29544 references,
29545 ngContentIndex,
29546 childCount,
29547 bindings: [],
29548 bindingFlags: 0,
29549 outputs: [],
29550 element: {
29551 ns: null,
29552 name: null,
29553 attrs: null,
29554 template,
29555 componentProvider: null,
29556 componentView: null,
29557 componentRendererType: null,
29558 publicProviders: null,
29559 allProviders: null,
29560 handleEvent: handleEvent || NOOP
29561 },
29562 provider: null,
29563 text: null,
29564 query: null,
29565 ngContent: null
29566 };
29567}
29568function elementDef(checkIndex, flags, matchedQueriesDsl, ngContentIndex, childCount, namespaceAndName, fixedAttrs = [], bindings, outputs, handleEvent, componentView, componentRendererType) {
29569 if (!handleEvent) {
29570 handleEvent = NOOP;
29571 }
29572 const { matchedQueries, references, matchedQueryIds } = splitMatchedQueriesDsl(matchedQueriesDsl);
29573 let ns = null;
29574 let name = null;
29575 if (namespaceAndName) {
29576 [ns, name] = splitNamespace(namespaceAndName);
29577 }
29578 bindings = bindings || [];
29579 const bindingDefs = [];
29580 for (let i = 0; i < bindings.length; i++) {
29581 const [bindingFlags, namespaceAndName, suffixOrSecurityContext] = bindings[i];
29582 const [ns, name] = splitNamespace(namespaceAndName);
29583 let securityContext = undefined;
29584 let suffix = undefined;
29585 switch (bindingFlags & 15 /* Types */) {
29586 case 4 /* TypeElementStyle */:
29587 suffix = suffixOrSecurityContext;
29588 break;
29589 case 1 /* TypeElementAttribute */:
29590 case 8 /* TypeProperty */:
29591 securityContext = suffixOrSecurityContext;
29592 break;
29593 }
29594 bindingDefs[i] =
29595 { flags: bindingFlags, ns, name, nonMinifiedName: name, securityContext, suffix };
29596 }
29597 outputs = outputs || [];
29598 const outputDefs = [];
29599 for (let i = 0; i < outputs.length; i++) {
29600 const [target, eventName] = outputs[i];
29601 outputDefs[i] =
29602 { type: 0 /* ElementOutput */, target: target, eventName, propName: null };
29603 }
29604 fixedAttrs = fixedAttrs || [];
29605 const attrs = fixedAttrs.map(([namespaceAndName, value]) => {
29606 const [ns, name] = splitNamespace(namespaceAndName);
29607 return [ns, name, value];
29608 });
29609 componentRendererType = resolveRendererType2(componentRendererType);
29610 if (componentView) {
29611 flags |= 33554432 /* ComponentView */;
29612 }
29613 flags |= 1 /* TypeElement */;
29614 return {
29615 // will bet set by the view definition
29616 nodeIndex: -1,
29617 parent: null,
29618 renderParent: null,
29619 bindingIndex: -1,
29620 outputIndex: -1,
29621 // regular values
29622 checkIndex,
29623 flags,
29624 childFlags: 0,
29625 directChildFlags: 0,
29626 childMatchedQueries: 0,
29627 matchedQueries,
29628 matchedQueryIds,
29629 references,
29630 ngContentIndex,
29631 childCount,
29632 bindings: bindingDefs,
29633 bindingFlags: calcBindingFlags(bindingDefs),
29634 outputs: outputDefs,
29635 element: {
29636 ns,
29637 name,
29638 attrs,
29639 template: null,
29640 // will bet set by the view definition
29641 componentProvider: null,
29642 componentView: componentView || null,
29643 componentRendererType: componentRendererType,
29644 publicProviders: null,
29645 allProviders: null,
29646 handleEvent: handleEvent || NOOP,
29647 },
29648 provider: null,
29649 text: null,
29650 query: null,
29651 ngContent: null
29652 };
29653}
29654function createElement(view, renderHost, def) {
29655 const elDef = def.element;
29656 const rootSelectorOrNode = view.root.selectorOrNode;
29657 const renderer = view.renderer;
29658 let el;
29659 if (view.parent || !rootSelectorOrNode) {
29660 if (elDef.name) {
29661 el = renderer.createElement(elDef.name, elDef.ns);
29662 }
29663 else {
29664 el = renderer.createComment('');
29665 }
29666 const parentEl = getParentRenderElement(view, renderHost, def);
29667 if (parentEl) {
29668 renderer.appendChild(parentEl, el);
29669 }
29670 }
29671 else {
29672 // when using native Shadow DOM, do not clear the root element contents to allow slot projection
29673 const preserveContent = (!!elDef.componentRendererType &&
29674 elDef.componentRendererType.encapsulation === ViewEncapsulation$1.ShadowDom);
29675 el = renderer.selectRootElement(rootSelectorOrNode, preserveContent);
29676 }
29677 if (elDef.attrs) {
29678 for (let i = 0; i < elDef.attrs.length; i++) {
29679 const [ns, name, value] = elDef.attrs[i];
29680 renderer.setAttribute(el, name, value, ns);
29681 }
29682 }
29683 return el;
29684}
29685function listenToElementOutputs(view, compView, def, el) {
29686 for (let i = 0; i < def.outputs.length; i++) {
29687 const output = def.outputs[i];
29688 const handleEventClosure = renderEventHandlerClosure(view, def.nodeIndex, elementEventFullName(output.target, output.eventName));
29689 let listenTarget = output.target;
29690 let listenerView = view;
29691 if (output.target === 'component') {
29692 listenTarget = null;
29693 listenerView = compView;
29694 }
29695 const disposable = listenerView.renderer.listen(listenTarget || el, output.eventName, handleEventClosure);
29696 view.disposables[def.outputIndex + i] = disposable;
29697 }
29698}
29699function renderEventHandlerClosure(view, index, eventName) {
29700 return (event) => dispatchEvent(view, index, eventName, event);
29701}
29702function checkAndUpdateElementInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
29703 const bindLen = def.bindings.length;
29704 let changed = false;
29705 if (bindLen > 0 && checkAndUpdateElementValue(view, def, 0, v0))
29706 changed = true;
29707 if (bindLen > 1 && checkAndUpdateElementValue(view, def, 1, v1))
29708 changed = true;
29709 if (bindLen > 2 && checkAndUpdateElementValue(view, def, 2, v2))
29710 changed = true;
29711 if (bindLen > 3 && checkAndUpdateElementValue(view, def, 3, v3))
29712 changed = true;
29713 if (bindLen > 4 && checkAndUpdateElementValue(view, def, 4, v4))
29714 changed = true;
29715 if (bindLen > 5 && checkAndUpdateElementValue(view, def, 5, v5))
29716 changed = true;
29717 if (bindLen > 6 && checkAndUpdateElementValue(view, def, 6, v6))
29718 changed = true;
29719 if (bindLen > 7 && checkAndUpdateElementValue(view, def, 7, v7))
29720 changed = true;
29721 if (bindLen > 8 && checkAndUpdateElementValue(view, def, 8, v8))
29722 changed = true;
29723 if (bindLen > 9 && checkAndUpdateElementValue(view, def, 9, v9))
29724 changed = true;
29725 return changed;
29726}
29727function checkAndUpdateElementDynamic(view, def, values) {
29728 let changed = false;
29729 for (let i = 0; i < values.length; i++) {
29730 if (checkAndUpdateElementValue(view, def, i, values[i]))
29731 changed = true;
29732 }
29733 return changed;
29734}
29735function checkAndUpdateElementValue(view, def, bindingIdx, value) {
29736 if (!checkAndUpdateBinding(view, def, bindingIdx, value)) {
29737 return false;
29738 }
29739 const binding = def.bindings[bindingIdx];
29740 const elData = asElementData(view, def.nodeIndex);
29741 const renderNode = elData.renderElement;
29742 const name = binding.name;
29743 switch (binding.flags & 15 /* Types */) {
29744 case 1 /* TypeElementAttribute */:
29745 setElementAttribute(view, binding, renderNode, binding.ns, name, value);
29746 break;
29747 case 2 /* TypeElementClass */:
29748 setElementClass(view, renderNode, name, value);
29749 break;
29750 case 4 /* TypeElementStyle */:
29751 setElementStyle(view, binding, renderNode, name, value);
29752 break;
29753 case 8 /* TypeProperty */:
29754 const bindView = (def.flags & 33554432 /* ComponentView */ &&
29755 binding.flags & 32 /* SyntheticHostProperty */) ?
29756 elData.componentView :
29757 view;
29758 setElementProperty(bindView, binding, renderNode, name, value);
29759 break;
29760 }
29761 return true;
29762}
29763function setElementAttribute(view, binding, renderNode, ns, name, value) {
29764 const securityContext = binding.securityContext;
29765 let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
29766 renderValue = renderValue != null ? renderValue.toString() : null;
29767 const renderer = view.renderer;
29768 if (value != null) {
29769 renderer.setAttribute(renderNode, name, renderValue, ns);
29770 }
29771 else {
29772 renderer.removeAttribute(renderNode, name, ns);
29773 }
29774}
29775function setElementClass(view, renderNode, name, value) {
29776 const renderer = view.renderer;
29777 if (value) {
29778 renderer.addClass(renderNode, name);
29779 }
29780 else {
29781 renderer.removeClass(renderNode, name);
29782 }
29783}
29784function setElementStyle(view, binding, renderNode, name, value) {
29785 let renderValue = view.root.sanitizer.sanitize(SecurityContext.STYLE, value);
29786 if (renderValue != null) {
29787 renderValue = renderValue.toString();
29788 const unit = binding.suffix;
29789 if (unit != null) {
29790 renderValue = renderValue + unit;
29791 }
29792 }
29793 else {
29794 renderValue = null;
29795 }
29796 const renderer = view.renderer;
29797 if (renderValue != null) {
29798 renderer.setStyle(renderNode, name, renderValue);
29799 }
29800 else {
29801 renderer.removeStyle(renderNode, name);
29802 }
29803}
29804function setElementProperty(view, binding, renderNode, name, value) {
29805 const securityContext = binding.securityContext;
29806 let renderValue = securityContext ? view.root.sanitizer.sanitize(securityContext, value) : value;
29807 view.renderer.setProperty(renderNode, name, renderValue);
29808}
29809
29810/**
29811 * @license
29812 * Copyright Google LLC All Rights Reserved.
29813 *
29814 * Use of this source code is governed by an MIT-style license that can be
29815 * found in the LICENSE file at https://angular.io/license
29816 */
29817const UNDEFINED_VALUE = {};
29818const InjectorRefTokenKey$1 = tokenKey(Injector);
29819const INJECTORRefTokenKey$1 = tokenKey(INJECTOR);
29820const NgModuleRefTokenKey = tokenKey(NgModuleRef$1);
29821function moduleProvideDef(flags, token, value, deps) {
29822 // Need to resolve forwardRefs as e.g. for `useValue` we
29823 // lowered the expression and then stopped evaluating it,
29824 // i.e. also didn't unwrap it.
29825 value = resolveForwardRef(value);
29826 const depDefs = splitDepsDsl(deps, stringify(token));
29827 return {
29828 // will bet set by the module definition
29829 index: -1,
29830 deps: depDefs,
29831 flags,
29832 token,
29833 value
29834 };
29835}
29836function moduleDef(providers) {
29837 const providersByKey = {};
29838 const modules = [];
29839 let scope = null;
29840 for (let i = 0; i < providers.length; i++) {
29841 const provider = providers[i];
29842 if (provider.token === INJECTOR_SCOPE) {
29843 scope = provider.value;
29844 }
29845 if (provider.flags & 1073741824 /* TypeNgModule */) {
29846 modules.push(provider.token);
29847 }
29848 provider.index = i;
29849 providersByKey[tokenKey(provider.token)] = provider;
29850 }
29851 return {
29852 // Will be filled later...
29853 factory: null,
29854 providersByKey,
29855 providers,
29856 modules,
29857 scope: scope,
29858 };
29859}
29860function initNgModule(data) {
29861 const def = data._def;
29862 const providers = data._providers = newArray(def.providers.length);
29863 for (let i = 0; i < def.providers.length; i++) {
29864 const provDef = def.providers[i];
29865 if (!(provDef.flags & 4096 /* LazyProvider */)) {
29866 // Make sure the provider has not been already initialized outside this loop.
29867 if (providers[i] === undefined) {
29868 providers[i] = _createProviderInstance$1(data, provDef);
29869 }
29870 }
29871 }
29872}
29873function resolveNgModuleDep(data, depDef, notFoundValue = Injector.THROW_IF_NOT_FOUND) {
29874 const former = setCurrentInjector(data);
29875 try {
29876 if (depDef.flags & 8 /* Value */) {
29877 return depDef.token;
29878 }
29879 if (depDef.flags & 2 /* Optional */) {
29880 notFoundValue = null;
29881 }
29882 if (depDef.flags & 1 /* SkipSelf */) {
29883 return data._parent.get(depDef.token, notFoundValue);
29884 }
29885 const tokenKey = depDef.tokenKey;
29886 switch (tokenKey) {
29887 case InjectorRefTokenKey$1:
29888 case INJECTORRefTokenKey$1:
29889 case NgModuleRefTokenKey:
29890 return data;
29891 }
29892 const providerDef = data._def.providersByKey[tokenKey];
29893 let injectableDef;
29894 if (providerDef) {
29895 let providerInstance = data._providers[providerDef.index];
29896 if (providerInstance === undefined) {
29897 providerInstance = data._providers[providerDef.index] =
29898 _createProviderInstance$1(data, providerDef);
29899 }
29900 return providerInstance === UNDEFINED_VALUE ? undefined : providerInstance;
29901 }
29902 else if ((injectableDef = getInjectableDef(depDef.token)) && targetsModule(data, injectableDef)) {
29903 const index = data._providers.length;
29904 data._def.providers[index] = data._def.providersByKey[depDef.tokenKey] = {
29905 flags: 1024 /* TypeFactoryProvider */ | 4096 /* LazyProvider */,
29906 value: injectableDef.factory,
29907 deps: [],
29908 index,
29909 token: depDef.token,
29910 };
29911 data._providers[index] = UNDEFINED_VALUE;
29912 return (data._providers[index] =
29913 _createProviderInstance$1(data, data._def.providersByKey[depDef.tokenKey]));
29914 }
29915 else if (depDef.flags & 4 /* Self */) {
29916 return notFoundValue;
29917 }
29918 return data._parent.get(depDef.token, notFoundValue);
29919 }
29920 finally {
29921 setCurrentInjector(former);
29922 }
29923}
29924function moduleTransitivelyPresent(ngModule, scope) {
29925 return ngModule._def.modules.indexOf(scope) > -1;
29926}
29927function targetsModule(ngModule, def) {
29928 const providedIn = resolveForwardRef(def.providedIn);
29929 return providedIn != null &&
29930 (providedIn === 'any' || providedIn === ngModule._def.scope ||
29931 moduleTransitivelyPresent(ngModule, providedIn));
29932}
29933function _createProviderInstance$1(ngModule, providerDef) {
29934 let injectable;
29935 switch (providerDef.flags & 201347067 /* Types */) {
29936 case 512 /* TypeClassProvider */:
29937 injectable = _createClass(ngModule, providerDef.value, providerDef.deps);
29938 break;
29939 case 1024 /* TypeFactoryProvider */:
29940 injectable = _callFactory(ngModule, providerDef.value, providerDef.deps);
29941 break;
29942 case 2048 /* TypeUseExistingProvider */:
29943 injectable = resolveNgModuleDep(ngModule, providerDef.deps[0]);
29944 break;
29945 case 256 /* TypeValueProvider */:
29946 injectable = providerDef.value;
29947 break;
29948 }
29949 // The read of `ngOnDestroy` here is slightly expensive as it's megamorphic, so it should be
29950 // avoided if possible. The sequence of checks here determines whether ngOnDestroy needs to be
29951 // checked. It might not if the `injectable` isn't an object or if NodeFlags.OnDestroy is already
29952 // set (ngOnDestroy was detected statically).
29953 if (injectable !== UNDEFINED_VALUE && injectable !== null && typeof injectable === 'object' &&
29954 !(providerDef.flags & 131072 /* OnDestroy */) && typeof injectable.ngOnDestroy === 'function') {
29955 providerDef.flags |= 131072 /* OnDestroy */;
29956 }
29957 return injectable === undefined ? UNDEFINED_VALUE : injectable;
29958}
29959function _createClass(ngModule, ctor, deps) {
29960 const len = deps.length;
29961 switch (len) {
29962 case 0:
29963 return new ctor();
29964 case 1:
29965 return new ctor(resolveNgModuleDep(ngModule, deps[0]));
29966 case 2:
29967 return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
29968 case 3:
29969 return new ctor(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2]));
29970 default:
29971 const depValues = [];
29972 for (let i = 0; i < len; i++) {
29973 depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
29974 }
29975 return new ctor(...depValues);
29976 }
29977}
29978function _callFactory(ngModule, factory, deps) {
29979 const len = deps.length;
29980 switch (len) {
29981 case 0:
29982 return factory();
29983 case 1:
29984 return factory(resolveNgModuleDep(ngModule, deps[0]));
29985 case 2:
29986 return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]));
29987 case 3:
29988 return factory(resolveNgModuleDep(ngModule, deps[0]), resolveNgModuleDep(ngModule, deps[1]), resolveNgModuleDep(ngModule, deps[2]));
29989 default:
29990 const depValues = [];
29991 for (let i = 0; i < len; i++) {
29992 depValues[i] = resolveNgModuleDep(ngModule, deps[i]);
29993 }
29994 return factory(...depValues);
29995 }
29996}
29997function callNgModuleLifecycle(ngModule, lifecycles) {
29998 const def = ngModule._def;
29999 const destroyed = new Set();
30000 for (let i = 0; i < def.providers.length; i++) {
30001 const provDef = def.providers[i];
30002 if (provDef.flags & 131072 /* OnDestroy */) {
30003 const instance = ngModule._providers[i];
30004 if (instance && instance !== UNDEFINED_VALUE) {
30005 const onDestroy = instance.ngOnDestroy;
30006 if (typeof onDestroy === 'function' && !destroyed.has(instance)) {
30007 onDestroy.apply(instance);
30008 destroyed.add(instance);
30009 }
30010 }
30011 }
30012 }
30013}
30014
30015/**
30016 * @license
30017 * Copyright Google LLC All Rights Reserved.
30018 *
30019 * Use of this source code is governed by an MIT-style license that can be
30020 * found in the LICENSE file at https://angular.io/license
30021 */
30022function attachEmbeddedView(parentView, elementData, viewIndex, view) {
30023 let embeddedViews = elementData.viewContainer._embeddedViews;
30024 if (viewIndex === null || viewIndex === undefined) {
30025 viewIndex = embeddedViews.length;
30026 }
30027 view.viewContainerParent = parentView;
30028 addToArray(embeddedViews, viewIndex, view);
30029 attachProjectedView(elementData, view);
30030 Services.dirtyParentQueries(view);
30031 const prevView = viewIndex > 0 ? embeddedViews[viewIndex - 1] : null;
30032 renderAttachEmbeddedView(elementData, prevView, view);
30033}
30034function attachProjectedView(vcElementData, view) {
30035 const dvcElementData = declaredViewContainer(view);
30036 if (!dvcElementData || dvcElementData === vcElementData ||
30037 view.state & 16 /* IsProjectedView */) {
30038 return;
30039 }
30040 // Note: For performance reasons, we
30041 // - add a view to template._projectedViews only 1x throughout its lifetime,
30042 // and remove it not until the view is destroyed.
30043 // (hard, as when a parent view is attached/detached we would need to attach/detach all
30044 // nested projected views as well, even across component boundaries).
30045 // - don't track the insertion order of views in the projected views array
30046 // (hard, as when the views of the same template are inserted different view containers)
30047 view.state |= 16 /* IsProjectedView */;
30048 let projectedViews = dvcElementData.template._projectedViews;
30049 if (!projectedViews) {
30050 projectedViews = dvcElementData.template._projectedViews = [];
30051 }
30052 projectedViews.push(view);
30053 // Note: we are changing the NodeDef here as we cannot calculate
30054 // the fact whether a template is used for projection during compilation.
30055 markNodeAsProjectedTemplate(view.parent.def, view.parentNodeDef);
30056}
30057function markNodeAsProjectedTemplate(viewDef, nodeDef) {
30058 if (nodeDef.flags & 4 /* ProjectedTemplate */) {
30059 return;
30060 }
30061 viewDef.nodeFlags |= 4 /* ProjectedTemplate */;
30062 nodeDef.flags |= 4 /* ProjectedTemplate */;
30063 let parentNodeDef = nodeDef.parent;
30064 while (parentNodeDef) {
30065 parentNodeDef.childFlags |= 4 /* ProjectedTemplate */;
30066 parentNodeDef = parentNodeDef.parent;
30067 }
30068}
30069function detachEmbeddedView(elementData, viewIndex) {
30070 const embeddedViews = elementData.viewContainer._embeddedViews;
30071 if (viewIndex == null || viewIndex >= embeddedViews.length) {
30072 viewIndex = embeddedViews.length - 1;
30073 }
30074 if (viewIndex < 0) {
30075 return null;
30076 }
30077 const view = embeddedViews[viewIndex];
30078 view.viewContainerParent = null;
30079 removeFromArray(embeddedViews, viewIndex);
30080 // See attachProjectedView for why we don't update projectedViews here.
30081 Services.dirtyParentQueries(view);
30082 renderDetachView(view);
30083 return view;
30084}
30085function detachProjectedView(view) {
30086 if (!(view.state & 16 /* IsProjectedView */)) {
30087 return;
30088 }
30089 const dvcElementData = declaredViewContainer(view);
30090 if (dvcElementData) {
30091 const projectedViews = dvcElementData.template._projectedViews;
30092 if (projectedViews) {
30093 removeFromArray(projectedViews, projectedViews.indexOf(view));
30094 Services.dirtyParentQueries(view);
30095 }
30096 }
30097}
30098function moveEmbeddedView(elementData, oldViewIndex, newViewIndex) {
30099 const embeddedViews = elementData.viewContainer._embeddedViews;
30100 const view = embeddedViews[oldViewIndex];
30101 removeFromArray(embeddedViews, oldViewIndex);
30102 if (newViewIndex == null) {
30103 newViewIndex = embeddedViews.length;
30104 }
30105 addToArray(embeddedViews, newViewIndex, view);
30106 // Note: Don't need to change projectedViews as the order in there
30107 // as always invalid...
30108 Services.dirtyParentQueries(view);
30109 renderDetachView(view);
30110 const prevView = newViewIndex > 0 ? embeddedViews[newViewIndex - 1] : null;
30111 renderAttachEmbeddedView(elementData, prevView, view);
30112 return view;
30113}
30114function renderAttachEmbeddedView(elementData, prevView, view) {
30115 const prevRenderNode = prevView ? renderNode(prevView, prevView.def.lastRenderRootNode) : elementData.renderElement;
30116 const parentNode = view.renderer.parentNode(prevRenderNode);
30117 const nextSibling = view.renderer.nextSibling(prevRenderNode);
30118 // Note: We can't check if `nextSibling` is present, as on WebWorkers it will always be!
30119 // However, browsers automatically do `appendChild` when there is no `nextSibling`.
30120 visitRootRenderNodes(view, 2 /* InsertBefore */, parentNode, nextSibling, undefined);
30121}
30122function renderDetachView(view) {
30123 visitRootRenderNodes(view, 3 /* RemoveChild */, null, null, undefined);
30124}
30125
30126/**
30127 * @license
30128 * Copyright Google LLC All Rights Reserved.
30129 *
30130 * Use of this source code is governed by an MIT-style license that can be
30131 * found in the LICENSE file at https://angular.io/license
30132 */
30133const EMPTY_CONTEXT = {};
30134// Attention: this function is called as top level function.
30135// Putting any logic in here will destroy closure tree shaking!
30136function createComponentFactory(selector, componentType, viewDefFactory, inputs, outputs, ngContentSelectors) {
30137 return new ComponentFactory_(selector, componentType, viewDefFactory, inputs, outputs, ngContentSelectors);
30138}
30139function getComponentViewDefinitionFactory(componentFactory) {
30140 return componentFactory.viewDefFactory;
30141}
30142class ComponentFactory_ extends ComponentFactory$1 {
30143 constructor(selector, componentType, viewDefFactory, _inputs, _outputs, ngContentSelectors) {
30144 // Attention: this ctor is called as top level function.
30145 // Putting any logic in here will destroy closure tree shaking!
30146 super();
30147 this.selector = selector;
30148 this.componentType = componentType;
30149 this._inputs = _inputs;
30150 this._outputs = _outputs;
30151 this.ngContentSelectors = ngContentSelectors;
30152 this.viewDefFactory = viewDefFactory;
30153 }
30154 get inputs() {
30155 const inputsArr = [];
30156 const inputs = this._inputs;
30157 for (let propName in inputs) {
30158 const templateName = inputs[propName];
30159 inputsArr.push({ propName, templateName });
30160 }
30161 return inputsArr;
30162 }
30163 get outputs() {
30164 const outputsArr = [];
30165 for (let propName in this._outputs) {
30166 const templateName = this._outputs[propName];
30167 outputsArr.push({ propName, templateName });
30168 }
30169 return outputsArr;
30170 }
30171 /**
30172 * Creates a new component.
30173 */
30174 create(injector, projectableNodes, rootSelectorOrNode, ngModule) {
30175 if (!ngModule) {
30176 throw new Error('ngModule should be provided');
30177 }
30178 const viewDef = resolveDefinition(this.viewDefFactory);
30179 const componentNodeIndex = viewDef.nodes[0].element.componentProvider.nodeIndex;
30180 const view = Services.createRootView(injector, projectableNodes || [], rootSelectorOrNode, viewDef, ngModule, EMPTY_CONTEXT);
30181 const component = asProviderData(view, componentNodeIndex).instance;
30182 if (rootSelectorOrNode) {
30183 view.renderer.setAttribute(asElementData(view, 0).renderElement, 'ng-version', VERSION.full);
30184 }
30185 return new ComponentRef_(view, new ViewRef_(view), component);
30186 }
30187}
30188class ComponentRef_ extends ComponentRef$1 {
30189 constructor(_view, _viewRef, _component) {
30190 super();
30191 this._view = _view;
30192 this._viewRef = _viewRef;
30193 this._component = _component;
30194 this._elDef = this._view.def.nodes[0];
30195 this.hostView = _viewRef;
30196 this.changeDetectorRef = _viewRef;
30197 this.instance = _component;
30198 }
30199 get location() {
30200 return new ElementRef(asElementData(this._view, this._elDef.nodeIndex).renderElement);
30201 }
30202 get injector() {
30203 return new Injector_(this._view, this._elDef);
30204 }
30205 get componentType() {
30206 return this._component.constructor;
30207 }
30208 destroy() {
30209 this._viewRef.destroy();
30210 }
30211 onDestroy(callback) {
30212 this._viewRef.onDestroy(callback);
30213 }
30214}
30215function createViewContainerData(view, elDef, elData) {
30216 return new ViewContainerRef_(view, elDef, elData);
30217}
30218class ViewContainerRef_ {
30219 constructor(_view, _elDef, _data) {
30220 this._view = _view;
30221 this._elDef = _elDef;
30222 this._data = _data;
30223 /**
30224 * @internal
30225 */
30226 this._embeddedViews = [];
30227 }
30228 get element() {
30229 return new ElementRef(this._data.renderElement);
30230 }
30231 get injector() {
30232 return new Injector_(this._view, this._elDef);
30233 }
30234 /** @deprecated No replacement */
30235 get parentInjector() {
30236 let view = this._view;
30237 let elDef = this._elDef.parent;
30238 while (!elDef && view) {
30239 elDef = viewParentEl(view);
30240 view = view.parent;
30241 }
30242 return view ? new Injector_(view, elDef) : new Injector_(this._view, null);
30243 }
30244 clear() {
30245 const len = this._embeddedViews.length;
30246 for (let i = len - 1; i >= 0; i--) {
30247 const view = detachEmbeddedView(this._data, i);
30248 Services.destroyView(view);
30249 }
30250 }
30251 get(index) {
30252 const view = this._embeddedViews[index];
30253 if (view) {
30254 const ref = new ViewRef_(view);
30255 ref.attachToViewContainerRef(this);
30256 return ref;
30257 }
30258 return null;
30259 }
30260 get length() {
30261 return this._embeddedViews.length;
30262 }
30263 createEmbeddedView(templateRef, context, index) {
30264 const viewRef = templateRef.createEmbeddedView(context || {});
30265 this.insert(viewRef, index);
30266 return viewRef;
30267 }
30268 createComponent(componentFactoryOrType, indexOrOptions, injector, projectableNodes, ngModuleRef) {
30269 if (typeof ngDevMode === 'undefined' || ngDevMode) {
30270 assertEqual(typeof componentFactoryOrType !== 'function', true, 'ViewEngine does not support Type as an argument for \'componentFactoryOrType\'');
30271 assertEqual(typeof indexOrOptions !== 'object', true, 'ViewEngine does not support options as an object provided via second argument');
30272 }
30273 const index = indexOrOptions;
30274 const contextInjector = injector || this.parentInjector;
30275 const componentFactory = componentFactoryOrType;
30276 if (!ngModuleRef && !(componentFactory instanceof ComponentFactoryBoundToModule)) {
30277 ngModuleRef = contextInjector.get(NgModuleRef$1);
30278 }
30279 const componentRef = componentFactory.create(contextInjector, projectableNodes, undefined, ngModuleRef);
30280 this.insert(componentRef.hostView, index);
30281 return componentRef;
30282 }
30283 insert(viewRef, index) {
30284 if (viewRef.destroyed) {
30285 throw new Error('Cannot insert a destroyed View in a ViewContainer!');
30286 }
30287 const viewRef_ = viewRef;
30288 const viewData = viewRef_._view;
30289 attachEmbeddedView(this._view, this._data, index, viewData);
30290 viewRef_.attachToViewContainerRef(this);
30291 return viewRef;
30292 }
30293 move(viewRef, currentIndex) {
30294 if (viewRef.destroyed) {
30295 throw new Error('Cannot move a destroyed View in a ViewContainer!');
30296 }
30297 const previousIndex = this._embeddedViews.indexOf(viewRef._view);
30298 moveEmbeddedView(this._data, previousIndex, currentIndex);
30299 return viewRef;
30300 }
30301 indexOf(viewRef) {
30302 return this._embeddedViews.indexOf(viewRef._view);
30303 }
30304 remove(index) {
30305 const viewData = detachEmbeddedView(this._data, index);
30306 if (viewData) {
30307 Services.destroyView(viewData);
30308 }
30309 }
30310 detach(index) {
30311 const view = detachEmbeddedView(this._data, index);
30312 return view ? new ViewRef_(view) : null;
30313 }
30314}
30315function createChangeDetectorRef(view) {
30316 return new ViewRef_(view);
30317}
30318class ViewRef_ {
30319 constructor(_view) {
30320 this._view = _view;
30321 this._viewContainerRef = null;
30322 this._appRef = null;
30323 }
30324 get rootNodes() {
30325 return rootRenderNodes(this._view);
30326 }
30327 get context() {
30328 return this._view.context;
30329 }
30330 set context(value) {
30331 this._view.context = value;
30332 }
30333 get destroyed() {
30334 return (this._view.state & 128 /* Destroyed */) !== 0;
30335 }
30336 markForCheck() {
30337 markParentViewsForCheck(this._view);
30338 }
30339 detach() {
30340 this._view.state &= ~4 /* Attached */;
30341 }
30342 detectChanges() {
30343 const fs = this._view.root.rendererFactory;
30344 if (fs.begin) {
30345 fs.begin();
30346 }
30347 try {
30348 Services.checkAndUpdateView(this._view);
30349 }
30350 finally {
30351 if (fs.end) {
30352 fs.end();
30353 }
30354 }
30355 }
30356 checkNoChanges() {
30357 Services.checkNoChangesView(this._view);
30358 }
30359 reattach() {
30360 this._view.state |= 4 /* Attached */;
30361 }
30362 onDestroy(callback) {
30363 if (!this._view.disposables) {
30364 this._view.disposables = [];
30365 }
30366 this._view.disposables.push(callback);
30367 }
30368 destroy() {
30369 if (this._appRef) {
30370 this._appRef.detachView(this);
30371 }
30372 else if (this._viewContainerRef) {
30373 this._viewContainerRef.detach(this._viewContainerRef.indexOf(this));
30374 }
30375 Services.destroyView(this._view);
30376 }
30377 detachFromAppRef() {
30378 this._appRef = null;
30379 renderDetachView(this._view);
30380 Services.dirtyParentQueries(this._view);
30381 }
30382 attachToAppRef(appRef) {
30383 if (this._viewContainerRef) {
30384 throw new Error('This view is already attached to a ViewContainer!');
30385 }
30386 this._appRef = appRef;
30387 }
30388 attachToViewContainerRef(vcRef) {
30389 if (this._appRef) {
30390 throw new Error('This view is already attached directly to the ApplicationRef!');
30391 }
30392 this._viewContainerRef = vcRef;
30393 }
30394}
30395function createTemplateData(view, def) {
30396 return new TemplateRef_(view, def);
30397}
30398class TemplateRef_ extends TemplateRef {
30399 constructor(_parentView, _def) {
30400 super();
30401 this._parentView = _parentView;
30402 this._def = _def;
30403 }
30404 createEmbeddedView(context) {
30405 return new ViewRef_(Services.createEmbeddedView(this._parentView, this._def, this._def.element.template, context));
30406 }
30407 get elementRef() {
30408 return new ElementRef(asElementData(this._parentView, this._def.nodeIndex).renderElement);
30409 }
30410}
30411function createInjector(view, elDef) {
30412 return new Injector_(view, elDef);
30413}
30414class Injector_ {
30415 constructor(view, elDef) {
30416 this.view = view;
30417 this.elDef = elDef;
30418 }
30419 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND) {
30420 const allowPrivateServices = this.elDef ? (this.elDef.flags & 33554432 /* ComponentView */) !== 0 : false;
30421 return Services.resolveDep(this.view, this.elDef, allowPrivateServices, { flags: 0 /* None */, token, tokenKey: tokenKey(token) }, notFoundValue);
30422 }
30423}
30424function nodeValue(view, index) {
30425 const def = view.def.nodes[index];
30426 if (def.flags & 1 /* TypeElement */) {
30427 const elData = asElementData(view, def.nodeIndex);
30428 return def.element.template ? elData.template : elData.renderElement;
30429 }
30430 else if (def.flags & 2 /* TypeText */) {
30431 return asTextData(view, def.nodeIndex).renderText;
30432 }
30433 else if (def.flags & (20224 /* CatProvider */ | 16 /* TypePipe */)) {
30434 return asProviderData(view, def.nodeIndex).instance;
30435 }
30436 throw new Error(`Illegal state: read nodeValue for node index ${index}`);
30437}
30438function createNgModuleRef(moduleType, parent, bootstrapComponents, def) {
30439 return new NgModuleRef_(moduleType, parent, bootstrapComponents, def);
30440}
30441class NgModuleRef_ {
30442 constructor(_moduleType, _parent, _bootstrapComponents, _def) {
30443 this._moduleType = _moduleType;
30444 this._parent = _parent;
30445 this._bootstrapComponents = _bootstrapComponents;
30446 this._def = _def;
30447 this._destroyListeners = [];
30448 this._destroyed = false;
30449 this.injector = this;
30450 initNgModule(this);
30451 }
30452 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, injectFlags = InjectFlags.Default) {
30453 let flags = 0 /* None */;
30454 if (injectFlags & InjectFlags.SkipSelf) {
30455 flags |= 1 /* SkipSelf */;
30456 }
30457 else if (injectFlags & InjectFlags.Self) {
30458 flags |= 4 /* Self */;
30459 }
30460 return resolveNgModuleDep(this, { token: token, tokenKey: tokenKey(token), flags: flags }, notFoundValue);
30461 }
30462 get instance() {
30463 return this.get(this._moduleType);
30464 }
30465 get componentFactoryResolver() {
30466 return this.get(ComponentFactoryResolver$1);
30467 }
30468 destroy() {
30469 if (this._destroyed) {
30470 throw new Error(`The ng module ${stringify(this.instance.constructor)} has already been destroyed.`);
30471 }
30472 this._destroyed = true;
30473 callNgModuleLifecycle(this, 131072 /* OnDestroy */);
30474 this._destroyListeners.forEach((listener) => listener());
30475 }
30476 onDestroy(callback) {
30477 this._destroyListeners.push(callback);
30478 }
30479}
30480
30481/**
30482 * @license
30483 * Copyright Google LLC All Rights Reserved.
30484 *
30485 * Use of this source code is governed by an MIT-style license that can be
30486 * found in the LICENSE file at https://angular.io/license
30487 */
30488const Renderer2TokenKey = tokenKey(Renderer2);
30489const ElementRefTokenKey = tokenKey(ElementRef);
30490const ViewContainerRefTokenKey = tokenKey(ViewContainerRef);
30491const TemplateRefTokenKey = tokenKey(TemplateRef);
30492const ChangeDetectorRefTokenKey = tokenKey(ChangeDetectorRef);
30493const InjectorRefTokenKey = tokenKey(Injector);
30494const INJECTORRefTokenKey = tokenKey(INJECTOR);
30495function directiveDef(checkIndex, flags, matchedQueries, childCount, ctor, deps, props, outputs) {
30496 const bindings = [];
30497 if (props) {
30498 for (let prop in props) {
30499 const [bindingIndex, nonMinifiedName] = props[prop];
30500 bindings[bindingIndex] = {
30501 flags: 8 /* TypeProperty */,
30502 name: prop,
30503 nonMinifiedName,
30504 ns: null,
30505 securityContext: null,
30506 suffix: null
30507 };
30508 }
30509 }
30510 const outputDefs = [];
30511 if (outputs) {
30512 for (let propName in outputs) {
30513 outputDefs.push({ type: 1 /* DirectiveOutput */, propName, target: null, eventName: outputs[propName] });
30514 }
30515 }
30516 flags |= 16384 /* TypeDirective */;
30517 return _def(checkIndex, flags, matchedQueries, childCount, ctor, ctor, deps, bindings, outputDefs);
30518}
30519function pipeDef(flags, ctor, deps) {
30520 flags |= 16 /* TypePipe */;
30521 return _def(-1, flags, null, 0, ctor, ctor, deps);
30522}
30523function providerDef(flags, matchedQueries, token, value, deps) {
30524 return _def(-1, flags, matchedQueries, 0, token, value, deps);
30525}
30526function _def(checkIndex, flags, matchedQueriesDsl, childCount, token, value, deps, bindings, outputs) {
30527 const { matchedQueries, references, matchedQueryIds } = splitMatchedQueriesDsl(matchedQueriesDsl);
30528 if (!outputs) {
30529 outputs = [];
30530 }
30531 if (!bindings) {
30532 bindings = [];
30533 }
30534 // Need to resolve forwardRefs as e.g. for `useValue` we
30535 // lowered the expression and then stopped evaluating it,
30536 // i.e. also didn't unwrap it.
30537 value = resolveForwardRef(value);
30538 const depDefs = splitDepsDsl(deps, stringify(token));
30539 return {
30540 // will bet set by the view definition
30541 nodeIndex: -1,
30542 parent: null,
30543 renderParent: null,
30544 bindingIndex: -1,
30545 outputIndex: -1,
30546 // regular values
30547 checkIndex,
30548 flags,
30549 childFlags: 0,
30550 directChildFlags: 0,
30551 childMatchedQueries: 0,
30552 matchedQueries,
30553 matchedQueryIds,
30554 references,
30555 ngContentIndex: -1,
30556 childCount,
30557 bindings,
30558 bindingFlags: calcBindingFlags(bindings),
30559 outputs,
30560 element: null,
30561 provider: { token, value, deps: depDefs },
30562 text: null,
30563 query: null,
30564 ngContent: null
30565 };
30566}
30567function createProviderInstance(view, def) {
30568 return _createProviderInstance(view, def);
30569}
30570function createPipeInstance(view, def) {
30571 // deps are looked up from component.
30572 let compView = view;
30573 while (compView.parent && !isComponentView(compView)) {
30574 compView = compView.parent;
30575 }
30576 // pipes can see the private services of the component
30577 const allowPrivateServices = true;
30578 // pipes are always eager and classes!
30579 return createClass(compView.parent, viewParentEl(compView), allowPrivateServices, def.provider.value, def.provider.deps);
30580}
30581function createDirectiveInstance(view, def) {
30582 // components can see other private services, other directives can't.
30583 const allowPrivateServices = (def.flags & 32768 /* Component */) > 0;
30584 // directives are always eager and classes!
30585 const instance = createClass(view, def.parent, allowPrivateServices, def.provider.value, def.provider.deps);
30586 if (def.outputs.length) {
30587 for (let i = 0; i < def.outputs.length; i++) {
30588 const output = def.outputs[i];
30589 const outputObservable = instance[output.propName];
30590 if (isObservable(outputObservable)) {
30591 const subscription = outputObservable.subscribe(eventHandlerClosure(view, def.parent.nodeIndex, output.eventName));
30592 view.disposables[def.outputIndex + i] = subscription.unsubscribe.bind(subscription);
30593 }
30594 else {
30595 throw new Error(`@Output ${output.propName} not initialized in '${instance.constructor.name}'.`);
30596 }
30597 }
30598 }
30599 return instance;
30600}
30601function eventHandlerClosure(view, index, eventName) {
30602 return (event) => dispatchEvent(view, index, eventName, event);
30603}
30604function checkAndUpdateDirectiveInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
30605 const providerData = asProviderData(view, def.nodeIndex);
30606 const directive = providerData.instance;
30607 let changed = false;
30608 let changes = undefined;
30609 const bindLen = def.bindings.length;
30610 if (bindLen > 0 && checkBinding(view, def, 0, v0)) {
30611 changed = true;
30612 changes = updateProp(view, providerData, def, 0, v0, changes);
30613 }
30614 if (bindLen > 1 && checkBinding(view, def, 1, v1)) {
30615 changed = true;
30616 changes = updateProp(view, providerData, def, 1, v1, changes);
30617 }
30618 if (bindLen > 2 && checkBinding(view, def, 2, v2)) {
30619 changed = true;
30620 changes = updateProp(view, providerData, def, 2, v2, changes);
30621 }
30622 if (bindLen > 3 && checkBinding(view, def, 3, v3)) {
30623 changed = true;
30624 changes = updateProp(view, providerData, def, 3, v3, changes);
30625 }
30626 if (bindLen > 4 && checkBinding(view, def, 4, v4)) {
30627 changed = true;
30628 changes = updateProp(view, providerData, def, 4, v4, changes);
30629 }
30630 if (bindLen > 5 && checkBinding(view, def, 5, v5)) {
30631 changed = true;
30632 changes = updateProp(view, providerData, def, 5, v5, changes);
30633 }
30634 if (bindLen > 6 && checkBinding(view, def, 6, v6)) {
30635 changed = true;
30636 changes = updateProp(view, providerData, def, 6, v6, changes);
30637 }
30638 if (bindLen > 7 && checkBinding(view, def, 7, v7)) {
30639 changed = true;
30640 changes = updateProp(view, providerData, def, 7, v7, changes);
30641 }
30642 if (bindLen > 8 && checkBinding(view, def, 8, v8)) {
30643 changed = true;
30644 changes = updateProp(view, providerData, def, 8, v8, changes);
30645 }
30646 if (bindLen > 9 && checkBinding(view, def, 9, v9)) {
30647 changed = true;
30648 changes = updateProp(view, providerData, def, 9, v9, changes);
30649 }
30650 if (changes) {
30651 directive.ngOnChanges(changes);
30652 }
30653 if ((def.flags & 65536 /* OnInit */) &&
30654 shouldCallLifecycleInitHook(view, 256 /* InitState_CallingOnInit */, def.nodeIndex)) {
30655 directive.ngOnInit();
30656 }
30657 if (def.flags & 262144 /* DoCheck */) {
30658 directive.ngDoCheck();
30659 }
30660 return changed;
30661}
30662function checkAndUpdateDirectiveDynamic(view, def, values) {
30663 const providerData = asProviderData(view, def.nodeIndex);
30664 const directive = providerData.instance;
30665 let changed = false;
30666 let changes = undefined;
30667 for (let i = 0; i < values.length; i++) {
30668 if (checkBinding(view, def, i, values[i])) {
30669 changed = true;
30670 changes = updateProp(view, providerData, def, i, values[i], changes);
30671 }
30672 }
30673 if (changes) {
30674 directive.ngOnChanges(changes);
30675 }
30676 if ((def.flags & 65536 /* OnInit */) &&
30677 shouldCallLifecycleInitHook(view, 256 /* InitState_CallingOnInit */, def.nodeIndex)) {
30678 directive.ngOnInit();
30679 }
30680 if (def.flags & 262144 /* DoCheck */) {
30681 directive.ngDoCheck();
30682 }
30683 return changed;
30684}
30685function _createProviderInstance(view, def) {
30686 // private services can see other private services
30687 const allowPrivateServices = (def.flags & 8192 /* PrivateProvider */) > 0;
30688 const providerDef = def.provider;
30689 switch (def.flags & 201347067 /* Types */) {
30690 case 512 /* TypeClassProvider */:
30691 return createClass(view, def.parent, allowPrivateServices, providerDef.value, providerDef.deps);
30692 case 1024 /* TypeFactoryProvider */:
30693 return callFactory(view, def.parent, allowPrivateServices, providerDef.value, providerDef.deps);
30694 case 2048 /* TypeUseExistingProvider */:
30695 return resolveDep(view, def.parent, allowPrivateServices, providerDef.deps[0]);
30696 case 256 /* TypeValueProvider */:
30697 return providerDef.value;
30698 }
30699}
30700function createClass(view, elDef, allowPrivateServices, ctor, deps) {
30701 const len = deps.length;
30702 switch (len) {
30703 case 0:
30704 return new ctor();
30705 case 1:
30706 return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]));
30707 case 2:
30708 return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]));
30709 case 3:
30710 return new ctor(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2]));
30711 default:
30712 const depValues = [];
30713 for (let i = 0; i < len; i++) {
30714 depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i]));
30715 }
30716 return new ctor(...depValues);
30717 }
30718}
30719function callFactory(view, elDef, allowPrivateServices, factory, deps) {
30720 const len = deps.length;
30721 switch (len) {
30722 case 0:
30723 return factory();
30724 case 1:
30725 return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]));
30726 case 2:
30727 return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]));
30728 case 3:
30729 return factory(resolveDep(view, elDef, allowPrivateServices, deps[0]), resolveDep(view, elDef, allowPrivateServices, deps[1]), resolveDep(view, elDef, allowPrivateServices, deps[2]));
30730 default:
30731 const depValues = [];
30732 for (let i = 0; i < len; i++) {
30733 depValues.push(resolveDep(view, elDef, allowPrivateServices, deps[i]));
30734 }
30735 return factory(...depValues);
30736 }
30737}
30738function resolveDep(view, elDef, allowPrivateServices, depDef, notFoundValue = Injector.THROW_IF_NOT_FOUND) {
30739 if (depDef.flags & 8 /* Value */) {
30740 return depDef.token;
30741 }
30742 const startView = view;
30743 if (depDef.flags & 2 /* Optional */) {
30744 notFoundValue = null;
30745 }
30746 const tokenKey = depDef.tokenKey;
30747 if (tokenKey === ChangeDetectorRefTokenKey) {
30748 // directives on the same element as a component should be able to control the change detector
30749 // of that component as well.
30750 allowPrivateServices = !!(elDef && elDef.element.componentView);
30751 }
30752 if (elDef && (depDef.flags & 1 /* SkipSelf */)) {
30753 allowPrivateServices = false;
30754 elDef = elDef.parent;
30755 }
30756 let searchView = view;
30757 while (searchView) {
30758 if (elDef) {
30759 switch (tokenKey) {
30760 case Renderer2TokenKey: {
30761 const compView = findCompView(searchView, elDef, allowPrivateServices);
30762 return compView.renderer;
30763 }
30764 case ElementRefTokenKey:
30765 return new ElementRef(asElementData(searchView, elDef.nodeIndex).renderElement);
30766 case ViewContainerRefTokenKey:
30767 return asElementData(searchView, elDef.nodeIndex).viewContainer;
30768 case TemplateRefTokenKey: {
30769 if (elDef.element.template) {
30770 return asElementData(searchView, elDef.nodeIndex).template;
30771 }
30772 break;
30773 }
30774 case ChangeDetectorRefTokenKey: {
30775 let cdView = findCompView(searchView, elDef, allowPrivateServices);
30776 return createChangeDetectorRef(cdView);
30777 }
30778 case InjectorRefTokenKey:
30779 case INJECTORRefTokenKey:
30780 return createInjector(searchView, elDef);
30781 default:
30782 const providerDef = (allowPrivateServices ? elDef.element.allProviders :
30783 elDef.element.publicProviders)[tokenKey];
30784 if (providerDef) {
30785 let providerData = asProviderData(searchView, providerDef.nodeIndex);
30786 if (!providerData) {
30787 providerData = { instance: _createProviderInstance(searchView, providerDef) };
30788 searchView.nodes[providerDef.nodeIndex] = providerData;
30789 }
30790 return providerData.instance;
30791 }
30792 }
30793 }
30794 allowPrivateServices = isComponentView(searchView);
30795 elDef = viewParentEl(searchView);
30796 searchView = searchView.parent;
30797 if (depDef.flags & 4 /* Self */) {
30798 searchView = null;
30799 }
30800 }
30801 const value = startView.root.injector.get(depDef.token, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR);
30802 if (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR ||
30803 notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR) {
30804 // Return the value from the root element injector when
30805 // - it provides it
30806 // (value !== NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
30807 // - the module injector should not be checked
30808 // (notFoundValue === NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR)
30809 return value;
30810 }
30811 return startView.root.ngModule.injector.get(depDef.token, notFoundValue);
30812}
30813function findCompView(view, elDef, allowPrivateServices) {
30814 let compView;
30815 if (allowPrivateServices) {
30816 compView = asElementData(view, elDef.nodeIndex).componentView;
30817 }
30818 else {
30819 compView = view;
30820 while (compView.parent && !isComponentView(compView)) {
30821 compView = compView.parent;
30822 }
30823 }
30824 return compView;
30825}
30826function updateProp(view, providerData, def, bindingIdx, value, changes) {
30827 if (def.flags & 32768 /* Component */) {
30828 const compView = asElementData(view, def.parent.nodeIndex).componentView;
30829 if (compView.def.flags & 2 /* OnPush */) {
30830 compView.state |= 8 /* ChecksEnabled */;
30831 }
30832 }
30833 const binding = def.bindings[bindingIdx];
30834 const propName = binding.name;
30835 // Note: This is still safe with Closure Compiler as
30836 // the user passed in the property name as an object has to `providerDef`,
30837 // so Closure Compiler will have renamed the property correctly already.
30838 providerData.instance[propName] = value;
30839 if (def.flags & 524288 /* OnChanges */) {
30840 changes = changes || {};
30841 const oldValue = view.oldValues[def.bindingIndex + bindingIdx];
30842 const binding = def.bindings[bindingIdx];
30843 changes[binding.nonMinifiedName] =
30844 new SimpleChange(oldValue, value, (view.state & 2 /* FirstCheck */) !== 0);
30845 }
30846 view.oldValues[def.bindingIndex + bindingIdx] = value;
30847 return changes;
30848}
30849// This function calls the ngAfterContentCheck, ngAfterContentInit,
30850// ngAfterViewCheck, and ngAfterViewInit lifecycle hooks (depending on the node
30851// flags in lifecycle). Unlike ngDoCheck, ngOnChanges and ngOnInit, which are
30852// called during a pre-order traversal of the view tree (that is calling the
30853// parent hooks before the child hooks) these events are sent in using a
30854// post-order traversal of the tree (children before parents). This changes the
30855// meaning of initIndex in the view state. For ngOnInit, initIndex tracks the
30856// expected nodeIndex which a ngOnInit should be called. When sending
30857// ngAfterContentInit and ngAfterViewInit it is the expected count of
30858// ngAfterContentInit or ngAfterViewInit methods that have been called. This
30859// ensure that despite being called recursively or after picking up after an
30860// exception, the ngAfterContentInit or ngAfterViewInit will be called on the
30861// correct nodes. Consider for example, the following (where E is an element
30862// and D is a directive)
30863// Tree: pre-order index post-order index
30864// E1 0 6
30865// E2 1 1
30866// D3 2 0
30867// E4 3 5
30868// E5 4 4
30869// E6 5 2
30870// E7 6 3
30871// As can be seen, the post-order index has an unclear relationship to the
30872// pre-order index (postOrderIndex === preOrderIndex - parentCount +
30873// childCount). Since number of calls to ngAfterContentInit and ngAfterViewInit
30874// are stable (will be the same for the same view regardless of exceptions or
30875// recursion) we just need to count them which will roughly correspond to the
30876// post-order index (it skips elements and directives that do not have
30877// lifecycle hooks).
30878//
30879// For example, if an exception is raised in the E6.onAfterViewInit() the
30880// initIndex is left at 3 (by shouldCallLifecycleInitHook() which set it to
30881// initIndex + 1). When checkAndUpdateView() is called again D3, E2 and E6 will
30882// not have their ngAfterViewInit() called but, starting with E7, the rest of
30883// the view will begin getting ngAfterViewInit() called until a check and
30884// pass is complete.
30885//
30886// This algorthim also handles recursion. Consider if E4's ngAfterViewInit()
30887// indirectly calls E1's ChangeDetectorRef.detectChanges(). The expected
30888// initIndex is set to 6, the recusive checkAndUpdateView() starts walk again.
30889// D3, E2, E6, E7, E5 and E4 are skipped, ngAfterViewInit() is called on E1.
30890// When the recursion returns the initIndex will be 7 so E1 is skipped as it
30891// has already been called in the recursively called checkAnUpdateView().
30892function callLifecycleHooksChildrenFirst(view, lifecycles) {
30893 if (!(view.def.nodeFlags & lifecycles)) {
30894 return;
30895 }
30896 const nodes = view.def.nodes;
30897 let initIndex = 0;
30898 for (let i = 0; i < nodes.length; i++) {
30899 const nodeDef = nodes[i];
30900 let parent = nodeDef.parent;
30901 if (!parent && nodeDef.flags & lifecycles) {
30902 // matching root node (e.g. a pipe)
30903 callProviderLifecycles(view, i, nodeDef.flags & lifecycles, initIndex++);
30904 }
30905 if ((nodeDef.childFlags & lifecycles) === 0) {
30906 // no child matches one of the lifecycles
30907 i += nodeDef.childCount;
30908 }
30909 while (parent && (parent.flags & 1 /* TypeElement */) &&
30910 i === parent.nodeIndex + parent.childCount) {
30911 // last child of an element
30912 if (parent.directChildFlags & lifecycles) {
30913 initIndex = callElementProvidersLifecycles(view, parent, lifecycles, initIndex);
30914 }
30915 parent = parent.parent;
30916 }
30917 }
30918}
30919function callElementProvidersLifecycles(view, elDef, lifecycles, initIndex) {
30920 for (let i = elDef.nodeIndex + 1; i <= elDef.nodeIndex + elDef.childCount; i++) {
30921 const nodeDef = view.def.nodes[i];
30922 if (nodeDef.flags & lifecycles) {
30923 callProviderLifecycles(view, i, nodeDef.flags & lifecycles, initIndex++);
30924 }
30925 // only visit direct children
30926 i += nodeDef.childCount;
30927 }
30928 return initIndex;
30929}
30930function callProviderLifecycles(view, index, lifecycles, initIndex) {
30931 const providerData = asProviderData(view, index);
30932 if (!providerData) {
30933 return;
30934 }
30935 const provider = providerData.instance;
30936 if (!provider) {
30937 return;
30938 }
30939 Services.setCurrentNode(view, index);
30940 if (lifecycles & 1048576 /* AfterContentInit */ &&
30941 shouldCallLifecycleInitHook(view, 512 /* InitState_CallingAfterContentInit */, initIndex)) {
30942 provider.ngAfterContentInit();
30943 }
30944 if (lifecycles & 2097152 /* AfterContentChecked */) {
30945 provider.ngAfterContentChecked();
30946 }
30947 if (lifecycles & 4194304 /* AfterViewInit */ &&
30948 shouldCallLifecycleInitHook(view, 768 /* InitState_CallingAfterViewInit */, initIndex)) {
30949 provider.ngAfterViewInit();
30950 }
30951 if (lifecycles & 8388608 /* AfterViewChecked */) {
30952 provider.ngAfterViewChecked();
30953 }
30954 if (lifecycles & 131072 /* OnDestroy */) {
30955 provider.ngOnDestroy();
30956 }
30957}
30958
30959/**
30960 * @license
30961 * Copyright Google LLC All Rights Reserved.
30962 *
30963 * Use of this source code is governed by an MIT-style license that can be
30964 * found in the LICENSE file at https://angular.io/license
30965 */
30966function queryDef(flags, id, bindings) {
30967 let bindingDefs = [];
30968 for (let propName in bindings) {
30969 const bindingType = bindings[propName];
30970 bindingDefs.push({ propName, bindingType });
30971 }
30972 return {
30973 // will bet set by the view definition
30974 nodeIndex: -1,
30975 parent: null,
30976 renderParent: null,
30977 bindingIndex: -1,
30978 outputIndex: -1,
30979 // regular values
30980 // TODO(vicb): check
30981 checkIndex: -1,
30982 flags,
30983 childFlags: 0,
30984 directChildFlags: 0,
30985 childMatchedQueries: 0,
30986 ngContentIndex: -1,
30987 matchedQueries: {},
30988 matchedQueryIds: 0,
30989 references: {},
30990 childCount: 0,
30991 bindings: [],
30992 bindingFlags: 0,
30993 outputs: [],
30994 element: null,
30995 provider: null,
30996 text: null,
30997 query: { id, filterId: filterQueryId(id), bindings: bindingDefs },
30998 ngContent: null
30999 };
31000}
31001function createQuery(emitDistinctChangesOnly) {
31002 return new QueryList(emitDistinctChangesOnly);
31003}
31004function dirtyParentQueries(view) {
31005 const queryIds = view.def.nodeMatchedQueries;
31006 while (view.parent && isEmbeddedView(view)) {
31007 let tplDef = view.parentNodeDef;
31008 view = view.parent;
31009 // content queries
31010 const end = tplDef.nodeIndex + tplDef.childCount;
31011 for (let i = 0; i <= end; i++) {
31012 const nodeDef = view.def.nodes[i];
31013 if ((nodeDef.flags & 67108864 /* TypeContentQuery */) &&
31014 (nodeDef.flags & 536870912 /* DynamicQuery */) &&
31015 (nodeDef.query.filterId & queryIds) === nodeDef.query.filterId) {
31016 asQueryList(view, i).setDirty();
31017 }
31018 if ((nodeDef.flags & 1 /* TypeElement */ && i + nodeDef.childCount < tplDef.nodeIndex) ||
31019 !(nodeDef.childFlags & 67108864 /* TypeContentQuery */) ||
31020 !(nodeDef.childFlags & 536870912 /* DynamicQuery */)) {
31021 // skip elements that don't contain the template element or no query.
31022 i += nodeDef.childCount;
31023 }
31024 }
31025 }
31026 // view queries
31027 if (view.def.nodeFlags & 134217728 /* TypeViewQuery */) {
31028 for (let i = 0; i < view.def.nodes.length; i++) {
31029 const nodeDef = view.def.nodes[i];
31030 if ((nodeDef.flags & 134217728 /* TypeViewQuery */) && (nodeDef.flags & 536870912 /* DynamicQuery */)) {
31031 asQueryList(view, i).setDirty();
31032 }
31033 // only visit the root nodes
31034 i += nodeDef.childCount;
31035 }
31036 }
31037}
31038function checkAndUpdateQuery(view, nodeDef) {
31039 const queryList = asQueryList(view, nodeDef.nodeIndex);
31040 if (!queryList.dirty) {
31041 return;
31042 }
31043 let directiveInstance;
31044 let newValues = undefined;
31045 if (nodeDef.flags & 67108864 /* TypeContentQuery */) {
31046 const elementDef = nodeDef.parent.parent;
31047 newValues = calcQueryValues(view, elementDef.nodeIndex, elementDef.nodeIndex + elementDef.childCount, nodeDef.query, []);
31048 directiveInstance = asProviderData(view, nodeDef.parent.nodeIndex).instance;
31049 }
31050 else if (nodeDef.flags & 134217728 /* TypeViewQuery */) {
31051 newValues = calcQueryValues(view, 0, view.def.nodes.length - 1, nodeDef.query, []);
31052 directiveInstance = view.component;
31053 }
31054 queryList.reset(newValues, unwrapElementRef);
31055 const bindings = nodeDef.query.bindings;
31056 let notify = false;
31057 for (let i = 0; i < bindings.length; i++) {
31058 const binding = bindings[i];
31059 let boundValue;
31060 switch (binding.bindingType) {
31061 case 0 /* First */:
31062 boundValue = queryList.first;
31063 break;
31064 case 1 /* All */:
31065 boundValue = queryList;
31066 notify = true;
31067 break;
31068 }
31069 directiveInstance[binding.propName] = boundValue;
31070 }
31071 if (notify) {
31072 queryList.notifyOnChanges();
31073 }
31074}
31075function calcQueryValues(view, startIndex, endIndex, queryDef, values) {
31076 for (let i = startIndex; i <= endIndex; i++) {
31077 const nodeDef = view.def.nodes[i];
31078 const valueType = nodeDef.matchedQueries[queryDef.id];
31079 if (valueType != null) {
31080 values.push(getQueryValue(view, nodeDef, valueType));
31081 }
31082 if (nodeDef.flags & 1 /* TypeElement */ && nodeDef.element.template &&
31083 (nodeDef.element.template.nodeMatchedQueries & queryDef.filterId) ===
31084 queryDef.filterId) {
31085 const elementData = asElementData(view, i);
31086 // check embedded views that were attached at the place of their template,
31087 // but process child nodes first if some match the query (see issue #16568)
31088 if ((nodeDef.childMatchedQueries & queryDef.filterId) === queryDef.filterId) {
31089 calcQueryValues(view, i + 1, i + nodeDef.childCount, queryDef, values);
31090 i += nodeDef.childCount;
31091 }
31092 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
31093 const embeddedViews = elementData.viewContainer._embeddedViews;
31094 for (let k = 0; k < embeddedViews.length; k++) {
31095 const embeddedView = embeddedViews[k];
31096 const dvc = declaredViewContainer(embeddedView);
31097 if (dvc && dvc === elementData) {
31098 calcQueryValues(embeddedView, 0, embeddedView.def.nodes.length - 1, queryDef, values);
31099 }
31100 }
31101 }
31102 const projectedViews = elementData.template._projectedViews;
31103 if (projectedViews) {
31104 for (let k = 0; k < projectedViews.length; k++) {
31105 const projectedView = projectedViews[k];
31106 calcQueryValues(projectedView, 0, projectedView.def.nodes.length - 1, queryDef, values);
31107 }
31108 }
31109 }
31110 if ((nodeDef.childMatchedQueries & queryDef.filterId) !== queryDef.filterId) {
31111 // if no child matches the query, skip the children.
31112 i += nodeDef.childCount;
31113 }
31114 }
31115 return values;
31116}
31117function getQueryValue(view, nodeDef, queryValueType) {
31118 if (queryValueType != null) {
31119 // a match
31120 switch (queryValueType) {
31121 case 1 /* RenderElement */:
31122 return asElementData(view, nodeDef.nodeIndex).renderElement;
31123 case 0 /* ElementRef */:
31124 return new ElementRef(asElementData(view, nodeDef.nodeIndex).renderElement);
31125 case 2 /* TemplateRef */:
31126 return asElementData(view, nodeDef.nodeIndex).template;
31127 case 3 /* ViewContainerRef */:
31128 return asElementData(view, nodeDef.nodeIndex).viewContainer;
31129 case 4 /* Provider */:
31130 return asProviderData(view, nodeDef.nodeIndex).instance;
31131 }
31132 }
31133}
31134
31135/**
31136 * @license
31137 * Copyright Google LLC All Rights Reserved.
31138 *
31139 * Use of this source code is governed by an MIT-style license that can be
31140 * found in the LICENSE file at https://angular.io/license
31141 */
31142function ngContentDef(ngContentIndex, index) {
31143 return {
31144 // will bet set by the view definition
31145 nodeIndex: -1,
31146 parent: null,
31147 renderParent: null,
31148 bindingIndex: -1,
31149 outputIndex: -1,
31150 // regular values
31151 checkIndex: -1,
31152 flags: 8 /* TypeNgContent */,
31153 childFlags: 0,
31154 directChildFlags: 0,
31155 childMatchedQueries: 0,
31156 matchedQueries: {},
31157 matchedQueryIds: 0,
31158 references: {},
31159 ngContentIndex,
31160 childCount: 0,
31161 bindings: [],
31162 bindingFlags: 0,
31163 outputs: [],
31164 element: null,
31165 provider: null,
31166 text: null,
31167 query: null,
31168 ngContent: { index }
31169 };
31170}
31171function appendNgContent(view, renderHost, def) {
31172 const parentEl = getParentRenderElement(view, renderHost, def);
31173 if (!parentEl) {
31174 // Nothing to do if there is no parent element.
31175 return;
31176 }
31177 const ngContentIndex = def.ngContent.index;
31178 visitProjectedRenderNodes(view, ngContentIndex, 1 /* AppendChild */, parentEl, null, undefined);
31179}
31180
31181/**
31182 * @license
31183 * Copyright Google LLC All Rights Reserved.
31184 *
31185 * Use of this source code is governed by an MIT-style license that can be
31186 * found in the LICENSE file at https://angular.io/license
31187 */
31188function purePipeDef(checkIndex, argCount) {
31189 // argCount + 1 to include the pipe as first arg
31190 return _pureExpressionDef(128 /* TypePurePipe */, checkIndex, newArray(argCount + 1));
31191}
31192function pureArrayDef(checkIndex, argCount) {
31193 return _pureExpressionDef(32 /* TypePureArray */, checkIndex, newArray(argCount));
31194}
31195function pureObjectDef(checkIndex, propToIndex) {
31196 const keys = Object.keys(propToIndex);
31197 const nbKeys = keys.length;
31198 const propertyNames = [];
31199 for (let i = 0; i < nbKeys; i++) {
31200 const key = keys[i];
31201 const index = propToIndex[key];
31202 propertyNames.push(key);
31203 }
31204 return _pureExpressionDef(64 /* TypePureObject */, checkIndex, propertyNames);
31205}
31206function _pureExpressionDef(flags, checkIndex, propertyNames) {
31207 const bindings = [];
31208 for (let i = 0; i < propertyNames.length; i++) {
31209 const prop = propertyNames[i];
31210 bindings.push({
31211 flags: 8 /* TypeProperty */,
31212 name: prop,
31213 ns: null,
31214 nonMinifiedName: prop,
31215 securityContext: null,
31216 suffix: null
31217 });
31218 }
31219 return {
31220 // will bet set by the view definition
31221 nodeIndex: -1,
31222 parent: null,
31223 renderParent: null,
31224 bindingIndex: -1,
31225 outputIndex: -1,
31226 // regular values
31227 checkIndex,
31228 flags,
31229 childFlags: 0,
31230 directChildFlags: 0,
31231 childMatchedQueries: 0,
31232 matchedQueries: {},
31233 matchedQueryIds: 0,
31234 references: {},
31235 ngContentIndex: -1,
31236 childCount: 0,
31237 bindings,
31238 bindingFlags: calcBindingFlags(bindings),
31239 outputs: [],
31240 element: null,
31241 provider: null,
31242 text: null,
31243 query: null,
31244 ngContent: null
31245 };
31246}
31247function createPureExpression(view, def) {
31248 return { value: undefined };
31249}
31250function checkAndUpdatePureExpressionInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31251 const bindings = def.bindings;
31252 let changed = false;
31253 const bindLen = bindings.length;
31254 if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0))
31255 changed = true;
31256 if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1))
31257 changed = true;
31258 if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2))
31259 changed = true;
31260 if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3))
31261 changed = true;
31262 if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4))
31263 changed = true;
31264 if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5))
31265 changed = true;
31266 if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6))
31267 changed = true;
31268 if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7))
31269 changed = true;
31270 if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8))
31271 changed = true;
31272 if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9))
31273 changed = true;
31274 if (changed) {
31275 const data = asPureExpressionData(view, def.nodeIndex);
31276 let value;
31277 switch (def.flags & 201347067 /* Types */) {
31278 case 32 /* TypePureArray */:
31279 value = [];
31280 if (bindLen > 0)
31281 value.push(v0);
31282 if (bindLen > 1)
31283 value.push(v1);
31284 if (bindLen > 2)
31285 value.push(v2);
31286 if (bindLen > 3)
31287 value.push(v3);
31288 if (bindLen > 4)
31289 value.push(v4);
31290 if (bindLen > 5)
31291 value.push(v5);
31292 if (bindLen > 6)
31293 value.push(v6);
31294 if (bindLen > 7)
31295 value.push(v7);
31296 if (bindLen > 8)
31297 value.push(v8);
31298 if (bindLen > 9)
31299 value.push(v9);
31300 break;
31301 case 64 /* TypePureObject */:
31302 value = {};
31303 if (bindLen > 0)
31304 value[bindings[0].name] = v0;
31305 if (bindLen > 1)
31306 value[bindings[1].name] = v1;
31307 if (bindLen > 2)
31308 value[bindings[2].name] = v2;
31309 if (bindLen > 3)
31310 value[bindings[3].name] = v3;
31311 if (bindLen > 4)
31312 value[bindings[4].name] = v4;
31313 if (bindLen > 5)
31314 value[bindings[5].name] = v5;
31315 if (bindLen > 6)
31316 value[bindings[6].name] = v6;
31317 if (bindLen > 7)
31318 value[bindings[7].name] = v7;
31319 if (bindLen > 8)
31320 value[bindings[8].name] = v8;
31321 if (bindLen > 9)
31322 value[bindings[9].name] = v9;
31323 break;
31324 case 128 /* TypePurePipe */:
31325 const pipe = v0;
31326 switch (bindLen) {
31327 case 1:
31328 value = pipe.transform(v0);
31329 break;
31330 case 2:
31331 value = pipe.transform(v1);
31332 break;
31333 case 3:
31334 value = pipe.transform(v1, v2);
31335 break;
31336 case 4:
31337 value = pipe.transform(v1, v2, v3);
31338 break;
31339 case 5:
31340 value = pipe.transform(v1, v2, v3, v4);
31341 break;
31342 case 6:
31343 value = pipe.transform(v1, v2, v3, v4, v5);
31344 break;
31345 case 7:
31346 value = pipe.transform(v1, v2, v3, v4, v5, v6);
31347 break;
31348 case 8:
31349 value = pipe.transform(v1, v2, v3, v4, v5, v6, v7);
31350 break;
31351 case 9:
31352 value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8);
31353 break;
31354 case 10:
31355 value = pipe.transform(v1, v2, v3, v4, v5, v6, v7, v8, v9);
31356 break;
31357 }
31358 break;
31359 }
31360 data.value = value;
31361 }
31362 return changed;
31363}
31364function checkAndUpdatePureExpressionDynamic(view, def, values) {
31365 const bindings = def.bindings;
31366 let changed = false;
31367 for (let i = 0; i < values.length; i++) {
31368 // Note: We need to loop over all values, so that
31369 // the old values are updates as well!
31370 if (checkAndUpdateBinding(view, def, i, values[i])) {
31371 changed = true;
31372 }
31373 }
31374 if (changed) {
31375 const data = asPureExpressionData(view, def.nodeIndex);
31376 let value;
31377 switch (def.flags & 201347067 /* Types */) {
31378 case 32 /* TypePureArray */:
31379 value = values;
31380 break;
31381 case 64 /* TypePureObject */:
31382 value = {};
31383 for (let i = 0; i < values.length; i++) {
31384 value[bindings[i].name] = values[i];
31385 }
31386 break;
31387 case 128 /* TypePurePipe */:
31388 const pipe = values[0];
31389 const params = values.slice(1);
31390 value = pipe.transform(...params);
31391 break;
31392 }
31393 data.value = value;
31394 }
31395 return changed;
31396}
31397
31398/**
31399 * @license
31400 * Copyright Google LLC All Rights Reserved.
31401 *
31402 * Use of this source code is governed by an MIT-style license that can be
31403 * found in the LICENSE file at https://angular.io/license
31404 */
31405function textDef(checkIndex, ngContentIndex, staticText) {
31406 const bindings = [];
31407 for (let i = 1; i < staticText.length; i++) {
31408 bindings[i - 1] = {
31409 flags: 8 /* TypeProperty */,
31410 name: null,
31411 ns: null,
31412 nonMinifiedName: null,
31413 securityContext: null,
31414 suffix: staticText[i],
31415 };
31416 }
31417 return {
31418 // will bet set by the view definition
31419 nodeIndex: -1,
31420 parent: null,
31421 renderParent: null,
31422 bindingIndex: -1,
31423 outputIndex: -1,
31424 // regular values
31425 checkIndex,
31426 flags: 2 /* TypeText */,
31427 childFlags: 0,
31428 directChildFlags: 0,
31429 childMatchedQueries: 0,
31430 matchedQueries: {},
31431 matchedQueryIds: 0,
31432 references: {},
31433 ngContentIndex,
31434 childCount: 0,
31435 bindings,
31436 bindingFlags: 8 /* TypeProperty */,
31437 outputs: [],
31438 element: null,
31439 provider: null,
31440 text: { prefix: staticText[0] },
31441 query: null,
31442 ngContent: null,
31443 };
31444}
31445function createText(view, renderHost, def) {
31446 let renderNode;
31447 const renderer = view.renderer;
31448 renderNode = renderer.createText(def.text.prefix);
31449 const parentEl = getParentRenderElement(view, renderHost, def);
31450 if (parentEl) {
31451 renderer.appendChild(parentEl, renderNode);
31452 }
31453 return { renderText: renderNode };
31454}
31455function checkAndUpdateTextInline(view, def, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31456 let changed = false;
31457 const bindings = def.bindings;
31458 const bindLen = bindings.length;
31459 if (bindLen > 0 && checkAndUpdateBinding(view, def, 0, v0))
31460 changed = true;
31461 if (bindLen > 1 && checkAndUpdateBinding(view, def, 1, v1))
31462 changed = true;
31463 if (bindLen > 2 && checkAndUpdateBinding(view, def, 2, v2))
31464 changed = true;
31465 if (bindLen > 3 && checkAndUpdateBinding(view, def, 3, v3))
31466 changed = true;
31467 if (bindLen > 4 && checkAndUpdateBinding(view, def, 4, v4))
31468 changed = true;
31469 if (bindLen > 5 && checkAndUpdateBinding(view, def, 5, v5))
31470 changed = true;
31471 if (bindLen > 6 && checkAndUpdateBinding(view, def, 6, v6))
31472 changed = true;
31473 if (bindLen > 7 && checkAndUpdateBinding(view, def, 7, v7))
31474 changed = true;
31475 if (bindLen > 8 && checkAndUpdateBinding(view, def, 8, v8))
31476 changed = true;
31477 if (bindLen > 9 && checkAndUpdateBinding(view, def, 9, v9))
31478 changed = true;
31479 if (changed) {
31480 let value = def.text.prefix;
31481 if (bindLen > 0)
31482 value += _addInterpolationPart(v0, bindings[0]);
31483 if (bindLen > 1)
31484 value += _addInterpolationPart(v1, bindings[1]);
31485 if (bindLen > 2)
31486 value += _addInterpolationPart(v2, bindings[2]);
31487 if (bindLen > 3)
31488 value += _addInterpolationPart(v3, bindings[3]);
31489 if (bindLen > 4)
31490 value += _addInterpolationPart(v4, bindings[4]);
31491 if (bindLen > 5)
31492 value += _addInterpolationPart(v5, bindings[5]);
31493 if (bindLen > 6)
31494 value += _addInterpolationPart(v6, bindings[6]);
31495 if (bindLen > 7)
31496 value += _addInterpolationPart(v7, bindings[7]);
31497 if (bindLen > 8)
31498 value += _addInterpolationPart(v8, bindings[8]);
31499 if (bindLen > 9)
31500 value += _addInterpolationPart(v9, bindings[9]);
31501 const renderNode = asTextData(view, def.nodeIndex).renderText;
31502 view.renderer.setValue(renderNode, value);
31503 }
31504 return changed;
31505}
31506function checkAndUpdateTextDynamic(view, def, values) {
31507 const bindings = def.bindings;
31508 let changed = false;
31509 for (let i = 0; i < values.length; i++) {
31510 // Note: We need to loop over all values, so that
31511 // the old values are updates as well!
31512 if (checkAndUpdateBinding(view, def, i, values[i])) {
31513 changed = true;
31514 }
31515 }
31516 if (changed) {
31517 let value = '';
31518 for (let i = 0; i < values.length; i++) {
31519 value = value + _addInterpolationPart(values[i], bindings[i]);
31520 }
31521 value = def.text.prefix + value;
31522 const renderNode = asTextData(view, def.nodeIndex).renderText;
31523 view.renderer.setValue(renderNode, value);
31524 }
31525 return changed;
31526}
31527function _addInterpolationPart(value, binding) {
31528 const valueStr = value != null ? value.toString() : '';
31529 return valueStr + binding.suffix;
31530}
31531
31532/**
31533 * @license
31534 * Copyright Google LLC All Rights Reserved.
31535 *
31536 * Use of this source code is governed by an MIT-style license that can be
31537 * found in the LICENSE file at https://angular.io/license
31538 */
31539function viewDef(flags, nodes, updateDirectives, updateRenderer) {
31540 // clone nodes and set auto calculated values
31541 let viewBindingCount = 0;
31542 let viewDisposableCount = 0;
31543 let viewNodeFlags = 0;
31544 let viewRootNodeFlags = 0;
31545 let viewMatchedQueries = 0;
31546 let currentParent = null;
31547 let currentRenderParent = null;
31548 let currentElementHasPublicProviders = false;
31549 let currentElementHasPrivateProviders = false;
31550 let lastRenderRootNode = null;
31551 for (let i = 0; i < nodes.length; i++) {
31552 const node = nodes[i];
31553 node.nodeIndex = i;
31554 node.parent = currentParent;
31555 node.bindingIndex = viewBindingCount;
31556 node.outputIndex = viewDisposableCount;
31557 node.renderParent = currentRenderParent;
31558 viewNodeFlags |= node.flags;
31559 viewMatchedQueries |= node.matchedQueryIds;
31560 if (node.element) {
31561 const elDef = node.element;
31562 elDef.publicProviders =
31563 currentParent ? currentParent.element.publicProviders : Object.create(null);
31564 elDef.allProviders = elDef.publicProviders;
31565 // Note: We assume that all providers of an element are before any child element!
31566 currentElementHasPublicProviders = false;
31567 currentElementHasPrivateProviders = false;
31568 if (node.element.template) {
31569 viewMatchedQueries |= node.element.template.nodeMatchedQueries;
31570 }
31571 }
31572 validateNode(currentParent, node, nodes.length);
31573 viewBindingCount += node.bindings.length;
31574 viewDisposableCount += node.outputs.length;
31575 if (!currentRenderParent && (node.flags & 3 /* CatRenderNode */)) {
31576 lastRenderRootNode = node;
31577 }
31578 if (node.flags & 20224 /* CatProvider */) {
31579 if (!currentElementHasPublicProviders) {
31580 currentElementHasPublicProviders = true;
31581 // Use prototypical inheritance to not get O(n^2) complexity...
31582 currentParent.element.publicProviders =
31583 Object.create(currentParent.element.publicProviders);
31584 currentParent.element.allProviders = currentParent.element.publicProviders;
31585 }
31586 const isPrivateService = (node.flags & 8192 /* PrivateProvider */) !== 0;
31587 const isComponent = (node.flags & 32768 /* Component */) !== 0;
31588 if (!isPrivateService || isComponent) {
31589 currentParent.element.publicProviders[tokenKey(node.provider.token)] = node;
31590 }
31591 else {
31592 if (!currentElementHasPrivateProviders) {
31593 currentElementHasPrivateProviders = true;
31594 // Use prototypical inheritance to not get O(n^2) complexity...
31595 currentParent.element.allProviders =
31596 Object.create(currentParent.element.publicProviders);
31597 }
31598 currentParent.element.allProviders[tokenKey(node.provider.token)] = node;
31599 }
31600 if (isComponent) {
31601 currentParent.element.componentProvider = node;
31602 }
31603 }
31604 if (currentParent) {
31605 currentParent.childFlags |= node.flags;
31606 currentParent.directChildFlags |= node.flags;
31607 currentParent.childMatchedQueries |= node.matchedQueryIds;
31608 if (node.element && node.element.template) {
31609 currentParent.childMatchedQueries |= node.element.template.nodeMatchedQueries;
31610 }
31611 }
31612 else {
31613 viewRootNodeFlags |= node.flags;
31614 }
31615 if (node.childCount > 0) {
31616 currentParent = node;
31617 if (!isNgContainer(node)) {
31618 currentRenderParent = node;
31619 }
31620 }
31621 else {
31622 // When the current node has no children, check if it is the last children of its parent.
31623 // When it is, propagate the flags up.
31624 // The loop is required because an element could be the last transitive children of several
31625 // elements. We loop to either the root or the highest opened element (= with remaining
31626 // children)
31627 while (currentParent && i === currentParent.nodeIndex + currentParent.childCount) {
31628 const newParent = currentParent.parent;
31629 if (newParent) {
31630 newParent.childFlags |= currentParent.childFlags;
31631 newParent.childMatchedQueries |= currentParent.childMatchedQueries;
31632 }
31633 currentParent = newParent;
31634 // We also need to update the render parent & account for ng-container
31635 if (currentParent && isNgContainer(currentParent)) {
31636 currentRenderParent = currentParent.renderParent;
31637 }
31638 else {
31639 currentRenderParent = currentParent;
31640 }
31641 }
31642 }
31643 }
31644 const handleEvent = (view, nodeIndex, eventName, event) => nodes[nodeIndex].element.handleEvent(view, eventName, event);
31645 return {
31646 // Will be filled later...
31647 factory: null,
31648 nodeFlags: viewNodeFlags,
31649 rootNodeFlags: viewRootNodeFlags,
31650 nodeMatchedQueries: viewMatchedQueries,
31651 flags,
31652 nodes: nodes,
31653 updateDirectives: updateDirectives || NOOP,
31654 updateRenderer: updateRenderer || NOOP,
31655 handleEvent,
31656 bindingCount: viewBindingCount,
31657 outputCount: viewDisposableCount,
31658 lastRenderRootNode
31659 };
31660}
31661function isNgContainer(node) {
31662 return (node.flags & 1 /* TypeElement */) !== 0 && node.element.name === null;
31663}
31664function validateNode(parent, node, nodeCount) {
31665 const template = node.element && node.element.template;
31666 if (template) {
31667 if (!template.lastRenderRootNode) {
31668 throw new Error(`Illegal State: Embedded templates without nodes are not allowed!`);
31669 }
31670 if (template.lastRenderRootNode &&
31671 template.lastRenderRootNode.flags & 16777216 /* EmbeddedViews */) {
31672 throw new Error(`Illegal State: Last root node of a template can't have embedded views, at index ${node.nodeIndex}!`);
31673 }
31674 }
31675 if (node.flags & 20224 /* CatProvider */) {
31676 const parentFlags = parent ? parent.flags : 0;
31677 if ((parentFlags & 1 /* TypeElement */) === 0) {
31678 throw new Error(`Illegal State: StaticProvider/Directive nodes need to be children of elements or anchors, at index ${node.nodeIndex}!`);
31679 }
31680 }
31681 if (node.query) {
31682 if (node.flags & 67108864 /* TypeContentQuery */ &&
31683 (!parent || (parent.flags & 16384 /* TypeDirective */) === 0)) {
31684 throw new Error(`Illegal State: Content Query nodes need to be children of directives, at index ${node.nodeIndex}!`);
31685 }
31686 if (node.flags & 134217728 /* TypeViewQuery */ && parent) {
31687 throw new Error(`Illegal State: View Query nodes have to be top level nodes, at index ${node.nodeIndex}!`);
31688 }
31689 }
31690 if (node.childCount) {
31691 const parentEnd = parent ? parent.nodeIndex + parent.childCount : nodeCount - 1;
31692 if (node.nodeIndex <= parentEnd && node.nodeIndex + node.childCount > parentEnd) {
31693 throw new Error(`Illegal State: childCount of node leads outside of parent, at index ${node.nodeIndex}!`);
31694 }
31695 }
31696}
31697function createEmbeddedView(parent, anchorDef, viewDef, context) {
31698 // embedded views are seen as siblings to the anchor, so we need
31699 // to get the parent of the anchor and use it as parentIndex.
31700 const view = createView(parent.root, parent.renderer, parent, anchorDef, viewDef);
31701 initView(view, parent.component, context);
31702 createViewNodes(view);
31703 return view;
31704}
31705function createRootView(root, def, context) {
31706 const view = createView(root, root.renderer, null, null, def);
31707 initView(view, context, context);
31708 createViewNodes(view);
31709 return view;
31710}
31711function createComponentView(parentView, nodeDef, viewDef, hostElement) {
31712 const rendererType = nodeDef.element.componentRendererType;
31713 let compRenderer;
31714 if (!rendererType) {
31715 compRenderer = parentView.root.renderer;
31716 }
31717 else {
31718 compRenderer = parentView.root.rendererFactory.createRenderer(hostElement, rendererType);
31719 }
31720 return createView(parentView.root, compRenderer, parentView, nodeDef.element.componentProvider, viewDef);
31721}
31722function createView(root, renderer, parent, parentNodeDef, def) {
31723 const nodes = new Array(def.nodes.length);
31724 const disposables = def.outputCount ? new Array(def.outputCount) : null;
31725 const view = {
31726 def,
31727 parent,
31728 viewContainerParent: null,
31729 parentNodeDef,
31730 context: null,
31731 component: null,
31732 nodes,
31733 state: 13 /* CatInit */,
31734 root,
31735 renderer,
31736 oldValues: new Array(def.bindingCount),
31737 disposables,
31738 initIndex: -1
31739 };
31740 return view;
31741}
31742function initView(view, component, context) {
31743 view.component = component;
31744 view.context = context;
31745}
31746function createViewNodes(view) {
31747 let renderHost;
31748 if (isComponentView(view)) {
31749 const hostDef = view.parentNodeDef;
31750 renderHost = asElementData(view.parent, hostDef.parent.nodeIndex).renderElement;
31751 }
31752 const def = view.def;
31753 const nodes = view.nodes;
31754 for (let i = 0; i < def.nodes.length; i++) {
31755 const nodeDef = def.nodes[i];
31756 Services.setCurrentNode(view, i);
31757 let nodeData;
31758 switch (nodeDef.flags & 201347067 /* Types */) {
31759 case 1 /* TypeElement */:
31760 const el = createElement(view, renderHost, nodeDef);
31761 let componentView = undefined;
31762 if (nodeDef.flags & 33554432 /* ComponentView */) {
31763 const compViewDef = resolveDefinition(nodeDef.element.componentView);
31764 componentView = Services.createComponentView(view, nodeDef, compViewDef, el);
31765 }
31766 listenToElementOutputs(view, componentView, nodeDef, el);
31767 nodeData = {
31768 renderElement: el,
31769 componentView,
31770 viewContainer: null,
31771 template: nodeDef.element.template ? createTemplateData(view, nodeDef) : undefined
31772 };
31773 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
31774 nodeData.viewContainer = createViewContainerData(view, nodeDef, nodeData);
31775 }
31776 break;
31777 case 2 /* TypeText */:
31778 nodeData = createText(view, renderHost, nodeDef);
31779 break;
31780 case 512 /* TypeClassProvider */:
31781 case 1024 /* TypeFactoryProvider */:
31782 case 2048 /* TypeUseExistingProvider */:
31783 case 256 /* TypeValueProvider */: {
31784 nodeData = nodes[i];
31785 if (!nodeData && !(nodeDef.flags & 4096 /* LazyProvider */)) {
31786 const instance = createProviderInstance(view, nodeDef);
31787 nodeData = { instance };
31788 }
31789 break;
31790 }
31791 case 16 /* TypePipe */: {
31792 const instance = createPipeInstance(view, nodeDef);
31793 nodeData = { instance };
31794 break;
31795 }
31796 case 16384 /* TypeDirective */: {
31797 nodeData = nodes[i];
31798 if (!nodeData) {
31799 const instance = createDirectiveInstance(view, nodeDef);
31800 nodeData = { instance };
31801 }
31802 if (nodeDef.flags & 32768 /* Component */) {
31803 const compView = asElementData(view, nodeDef.parent.nodeIndex).componentView;
31804 initView(compView, nodeData.instance, nodeData.instance);
31805 }
31806 break;
31807 }
31808 case 32 /* TypePureArray */:
31809 case 64 /* TypePureObject */:
31810 case 128 /* TypePurePipe */:
31811 nodeData = createPureExpression(view, nodeDef);
31812 break;
31813 case 67108864 /* TypeContentQuery */:
31814 case 134217728 /* TypeViewQuery */:
31815 nodeData = createQuery((nodeDef.flags & -2147483648 /* EmitDistinctChangesOnly */) ===
31816 -2147483648 /* EmitDistinctChangesOnly */);
31817 break;
31818 case 8 /* TypeNgContent */:
31819 appendNgContent(view, renderHost, nodeDef);
31820 // no runtime data needed for NgContent...
31821 nodeData = undefined;
31822 break;
31823 }
31824 nodes[i] = nodeData;
31825 }
31826 // Create the ViewData.nodes of component views after we created everything else,
31827 // so that e.g. ng-content works
31828 execComponentViewsAction(view, ViewAction.CreateViewNodes);
31829 // fill static content and view queries
31830 execQueriesAction(view, 67108864 /* TypeContentQuery */ | 134217728 /* TypeViewQuery */, 268435456 /* StaticQuery */, 0 /* CheckAndUpdate */);
31831}
31832function checkNoChangesView(view) {
31833 markProjectedViewsForCheck(view);
31834 Services.updateDirectives(view, 1 /* CheckNoChanges */);
31835 execEmbeddedViewsAction(view, ViewAction.CheckNoChanges);
31836 Services.updateRenderer(view, 1 /* CheckNoChanges */);
31837 execComponentViewsAction(view, ViewAction.CheckNoChanges);
31838 // Note: We don't check queries for changes as we didn't do this in v2.x.
31839 // TODO(tbosch): investigate if we can enable the check again in v5.x with a nicer error message.
31840 view.state &= ~(64 /* CheckProjectedViews */ | 32 /* CheckProjectedView */);
31841}
31842function checkAndUpdateView(view) {
31843 if (view.state & 1 /* BeforeFirstCheck */) {
31844 view.state &= ~1 /* BeforeFirstCheck */;
31845 view.state |= 2 /* FirstCheck */;
31846 }
31847 else {
31848 view.state &= ~2 /* FirstCheck */;
31849 }
31850 shiftInitState(view, 0 /* InitState_BeforeInit */, 256 /* InitState_CallingOnInit */);
31851 markProjectedViewsForCheck(view);
31852 Services.updateDirectives(view, 0 /* CheckAndUpdate */);
31853 execEmbeddedViewsAction(view, ViewAction.CheckAndUpdate);
31854 execQueriesAction(view, 67108864 /* TypeContentQuery */, 536870912 /* DynamicQuery */, 0 /* CheckAndUpdate */);
31855 let callInit = shiftInitState(view, 256 /* InitState_CallingOnInit */, 512 /* InitState_CallingAfterContentInit */);
31856 callLifecycleHooksChildrenFirst(view, 2097152 /* AfterContentChecked */ | (callInit ? 1048576 /* AfterContentInit */ : 0));
31857 Services.updateRenderer(view, 0 /* CheckAndUpdate */);
31858 execComponentViewsAction(view, ViewAction.CheckAndUpdate);
31859 execQueriesAction(view, 134217728 /* TypeViewQuery */, 536870912 /* DynamicQuery */, 0 /* CheckAndUpdate */);
31860 callInit = shiftInitState(view, 512 /* InitState_CallingAfterContentInit */, 768 /* InitState_CallingAfterViewInit */);
31861 callLifecycleHooksChildrenFirst(view, 8388608 /* AfterViewChecked */ | (callInit ? 4194304 /* AfterViewInit */ : 0));
31862 if (view.def.flags & 2 /* OnPush */) {
31863 view.state &= ~8 /* ChecksEnabled */;
31864 }
31865 view.state &= ~(64 /* CheckProjectedViews */ | 32 /* CheckProjectedView */);
31866 shiftInitState(view, 768 /* InitState_CallingAfterViewInit */, 1024 /* InitState_AfterInit */);
31867}
31868function checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31869 if (argStyle === 0 /* Inline */) {
31870 return checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31871 }
31872 else {
31873 return checkAndUpdateNodeDynamic(view, nodeDef, v0);
31874 }
31875}
31876function markProjectedViewsForCheck(view) {
31877 const def = view.def;
31878 if (!(def.nodeFlags & 4 /* ProjectedTemplate */)) {
31879 return;
31880 }
31881 for (let i = 0; i < def.nodes.length; i++) {
31882 const nodeDef = def.nodes[i];
31883 if (nodeDef.flags & 4 /* ProjectedTemplate */) {
31884 const projectedViews = asElementData(view, i).template._projectedViews;
31885 if (projectedViews) {
31886 for (let i = 0; i < projectedViews.length; i++) {
31887 const projectedView = projectedViews[i];
31888 projectedView.state |= 32 /* CheckProjectedView */;
31889 markParentViewsForCheckProjectedViews(projectedView, view);
31890 }
31891 }
31892 }
31893 else if ((nodeDef.childFlags & 4 /* ProjectedTemplate */) === 0) {
31894 // a parent with leafs
31895 // no child is a component,
31896 // then skip the children
31897 i += nodeDef.childCount;
31898 }
31899 }
31900}
31901function checkAndUpdateNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31902 switch (nodeDef.flags & 201347067 /* Types */) {
31903 case 1 /* TypeElement */:
31904 return checkAndUpdateElementInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31905 case 2 /* TypeText */:
31906 return checkAndUpdateTextInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31907 case 16384 /* TypeDirective */:
31908 return checkAndUpdateDirectiveInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31909 case 32 /* TypePureArray */:
31910 case 64 /* TypePureObject */:
31911 case 128 /* TypePurePipe */:
31912 return checkAndUpdatePureExpressionInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31913 default:
31914 throw 'unreachable';
31915 }
31916}
31917function checkAndUpdateNodeDynamic(view, nodeDef, values) {
31918 switch (nodeDef.flags & 201347067 /* Types */) {
31919 case 1 /* TypeElement */:
31920 return checkAndUpdateElementDynamic(view, nodeDef, values);
31921 case 2 /* TypeText */:
31922 return checkAndUpdateTextDynamic(view, nodeDef, values);
31923 case 16384 /* TypeDirective */:
31924 return checkAndUpdateDirectiveDynamic(view, nodeDef, values);
31925 case 32 /* TypePureArray */:
31926 case 64 /* TypePureObject */:
31927 case 128 /* TypePurePipe */:
31928 return checkAndUpdatePureExpressionDynamic(view, nodeDef, values);
31929 default:
31930 throw 'unreachable';
31931 }
31932}
31933function checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31934 if (argStyle === 0 /* Inline */) {
31935 checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
31936 }
31937 else {
31938 checkNoChangesNodeDynamic(view, nodeDef, v0);
31939 }
31940 // Returning false is ok here as we would have thrown in case of a change.
31941 return false;
31942}
31943function checkNoChangesNodeInline(view, nodeDef, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
31944 const bindLen = nodeDef.bindings.length;
31945 if (bindLen > 0)
31946 checkBindingNoChanges(view, nodeDef, 0, v0);
31947 if (bindLen > 1)
31948 checkBindingNoChanges(view, nodeDef, 1, v1);
31949 if (bindLen > 2)
31950 checkBindingNoChanges(view, nodeDef, 2, v2);
31951 if (bindLen > 3)
31952 checkBindingNoChanges(view, nodeDef, 3, v3);
31953 if (bindLen > 4)
31954 checkBindingNoChanges(view, nodeDef, 4, v4);
31955 if (bindLen > 5)
31956 checkBindingNoChanges(view, nodeDef, 5, v5);
31957 if (bindLen > 6)
31958 checkBindingNoChanges(view, nodeDef, 6, v6);
31959 if (bindLen > 7)
31960 checkBindingNoChanges(view, nodeDef, 7, v7);
31961 if (bindLen > 8)
31962 checkBindingNoChanges(view, nodeDef, 8, v8);
31963 if (bindLen > 9)
31964 checkBindingNoChanges(view, nodeDef, 9, v9);
31965}
31966function checkNoChangesNodeDynamic(view, nodeDef, values) {
31967 for (let i = 0; i < values.length; i++) {
31968 checkBindingNoChanges(view, nodeDef, i, values[i]);
31969 }
31970}
31971/**
31972 * Workaround https://github.com/angular/tsickle/issues/497
31973 * @suppress {misplacedTypeAnnotation}
31974 */
31975function checkNoChangesQuery(view, nodeDef) {
31976 const queryList = asQueryList(view, nodeDef.nodeIndex);
31977 if (queryList.dirty) {
31978 throw expressionChangedAfterItHasBeenCheckedError(Services.createDebugContext(view, nodeDef.nodeIndex), `Query ${nodeDef.query.id} not dirty`, `Query ${nodeDef.query.id} dirty`, (view.state & 1 /* BeforeFirstCheck */) !== 0);
31979 }
31980}
31981function destroyView(view) {
31982 if (view.state & 128 /* Destroyed */) {
31983 return;
31984 }
31985 execEmbeddedViewsAction(view, ViewAction.Destroy);
31986 execComponentViewsAction(view, ViewAction.Destroy);
31987 callLifecycleHooksChildrenFirst(view, 131072 /* OnDestroy */);
31988 if (view.disposables) {
31989 for (let i = 0; i < view.disposables.length; i++) {
31990 view.disposables[i]();
31991 }
31992 }
31993 detachProjectedView(view);
31994 if (view.renderer.destroyNode) {
31995 destroyViewNodes(view);
31996 }
31997 if (isComponentView(view)) {
31998 view.renderer.destroy();
31999 }
32000 view.state |= 128 /* Destroyed */;
32001}
32002function destroyViewNodes(view) {
32003 const len = view.def.nodes.length;
32004 for (let i = 0; i < len; i++) {
32005 const def = view.def.nodes[i];
32006 if (def.flags & 1 /* TypeElement */) {
32007 view.renderer.destroyNode(asElementData(view, i).renderElement);
32008 }
32009 else if (def.flags & 2 /* TypeText */) {
32010 view.renderer.destroyNode(asTextData(view, i).renderText);
32011 }
32012 else if (def.flags & 67108864 /* TypeContentQuery */ || def.flags & 134217728 /* TypeViewQuery */) {
32013 asQueryList(view, i).destroy();
32014 }
32015 }
32016}
32017var ViewAction;
32018(function (ViewAction) {
32019 ViewAction[ViewAction["CreateViewNodes"] = 0] = "CreateViewNodes";
32020 ViewAction[ViewAction["CheckNoChanges"] = 1] = "CheckNoChanges";
32021 ViewAction[ViewAction["CheckNoChangesProjectedViews"] = 2] = "CheckNoChangesProjectedViews";
32022 ViewAction[ViewAction["CheckAndUpdate"] = 3] = "CheckAndUpdate";
32023 ViewAction[ViewAction["CheckAndUpdateProjectedViews"] = 4] = "CheckAndUpdateProjectedViews";
32024 ViewAction[ViewAction["Destroy"] = 5] = "Destroy";
32025})(ViewAction || (ViewAction = {}));
32026function execComponentViewsAction(view, action) {
32027 const def = view.def;
32028 if (!(def.nodeFlags & 33554432 /* ComponentView */)) {
32029 return;
32030 }
32031 for (let i = 0; i < def.nodes.length; i++) {
32032 const nodeDef = def.nodes[i];
32033 if (nodeDef.flags & 33554432 /* ComponentView */) {
32034 // a leaf
32035 callViewAction(asElementData(view, i).componentView, action);
32036 }
32037 else if ((nodeDef.childFlags & 33554432 /* ComponentView */) === 0) {
32038 // a parent with leafs
32039 // no child is a component,
32040 // then skip the children
32041 i += nodeDef.childCount;
32042 }
32043 }
32044}
32045function execEmbeddedViewsAction(view, action) {
32046 const def = view.def;
32047 if (!(def.nodeFlags & 16777216 /* EmbeddedViews */)) {
32048 return;
32049 }
32050 for (let i = 0; i < def.nodes.length; i++) {
32051 const nodeDef = def.nodes[i];
32052 if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
32053 // a leaf
32054 const embeddedViews = asElementData(view, i).viewContainer._embeddedViews;
32055 for (let k = 0; k < embeddedViews.length; k++) {
32056 callViewAction(embeddedViews[k], action);
32057 }
32058 }
32059 else if ((nodeDef.childFlags & 16777216 /* EmbeddedViews */) === 0) {
32060 // a parent with leafs
32061 // no child is a component,
32062 // then skip the children
32063 i += nodeDef.childCount;
32064 }
32065 }
32066}
32067function callViewAction(view, action) {
32068 const viewState = view.state;
32069 switch (action) {
32070 case ViewAction.CheckNoChanges:
32071 if ((viewState & 128 /* Destroyed */) === 0) {
32072 if ((viewState & 12 /* CatDetectChanges */) === 12 /* CatDetectChanges */) {
32073 checkNoChangesView(view);
32074 }
32075 else if (viewState & 64 /* CheckProjectedViews */) {
32076 execProjectedViewsAction(view, ViewAction.CheckNoChangesProjectedViews);
32077 }
32078 }
32079 break;
32080 case ViewAction.CheckNoChangesProjectedViews:
32081 if ((viewState & 128 /* Destroyed */) === 0) {
32082 if (viewState & 32 /* CheckProjectedView */) {
32083 checkNoChangesView(view);
32084 }
32085 else if (viewState & 64 /* CheckProjectedViews */) {
32086 execProjectedViewsAction(view, action);
32087 }
32088 }
32089 break;
32090 case ViewAction.CheckAndUpdate:
32091 if ((viewState & 128 /* Destroyed */) === 0) {
32092 if ((viewState & 12 /* CatDetectChanges */) === 12 /* CatDetectChanges */) {
32093 checkAndUpdateView(view);
32094 }
32095 else if (viewState & 64 /* CheckProjectedViews */) {
32096 execProjectedViewsAction(view, ViewAction.CheckAndUpdateProjectedViews);
32097 }
32098 }
32099 break;
32100 case ViewAction.CheckAndUpdateProjectedViews:
32101 if ((viewState & 128 /* Destroyed */) === 0) {
32102 if (viewState & 32 /* CheckProjectedView */) {
32103 checkAndUpdateView(view);
32104 }
32105 else if (viewState & 64 /* CheckProjectedViews */) {
32106 execProjectedViewsAction(view, action);
32107 }
32108 }
32109 break;
32110 case ViewAction.Destroy:
32111 // Note: destroyView recurses over all views,
32112 // so we don't need to special case projected views here.
32113 destroyView(view);
32114 break;
32115 case ViewAction.CreateViewNodes:
32116 createViewNodes(view);
32117 break;
32118 }
32119}
32120function execProjectedViewsAction(view, action) {
32121 execEmbeddedViewsAction(view, action);
32122 execComponentViewsAction(view, action);
32123}
32124function execQueriesAction(view, queryFlags, staticDynamicQueryFlag, checkType) {
32125 if (!(view.def.nodeFlags & queryFlags) || !(view.def.nodeFlags & staticDynamicQueryFlag)) {
32126 return;
32127 }
32128 const nodeCount = view.def.nodes.length;
32129 for (let i = 0; i < nodeCount; i++) {
32130 const nodeDef = view.def.nodes[i];
32131 if ((nodeDef.flags & queryFlags) && (nodeDef.flags & staticDynamicQueryFlag)) {
32132 Services.setCurrentNode(view, nodeDef.nodeIndex);
32133 switch (checkType) {
32134 case 0 /* CheckAndUpdate */:
32135 checkAndUpdateQuery(view, nodeDef);
32136 break;
32137 case 1 /* CheckNoChanges */:
32138 checkNoChangesQuery(view, nodeDef);
32139 break;
32140 }
32141 }
32142 if (!(nodeDef.childFlags & queryFlags) || !(nodeDef.childFlags & staticDynamicQueryFlag)) {
32143 // no child has a matching query
32144 // then skip the children
32145 i += nodeDef.childCount;
32146 }
32147 }
32148}
32149
32150/**
32151 * @license
32152 * Copyright Google LLC All Rights Reserved.
32153 *
32154 * Use of this source code is governed by an MIT-style license that can be
32155 * found in the LICENSE file at https://angular.io/license
32156 */
32157let initialized = false;
32158function initServicesIfNeeded() {
32159 if (initialized) {
32160 return;
32161 }
32162 initialized = true;
32163 const services = isDevMode() ? createDebugServices() : createProdServices();
32164 Services.setCurrentNode = services.setCurrentNode;
32165 Services.createRootView = services.createRootView;
32166 Services.createEmbeddedView = services.createEmbeddedView;
32167 Services.createComponentView = services.createComponentView;
32168 Services.createNgModuleRef = services.createNgModuleRef;
32169 Services.overrideProvider = services.overrideProvider;
32170 Services.overrideComponentView = services.overrideComponentView;
32171 Services.clearOverrides = services.clearOverrides;
32172 Services.checkAndUpdateView = services.checkAndUpdateView;
32173 Services.checkNoChangesView = services.checkNoChangesView;
32174 Services.destroyView = services.destroyView;
32175 Services.resolveDep = resolveDep;
32176 Services.createDebugContext = services.createDebugContext;
32177 Services.handleEvent = services.handleEvent;
32178 Services.updateDirectives = services.updateDirectives;
32179 Services.updateRenderer = services.updateRenderer;
32180 Services.dirtyParentQueries = dirtyParentQueries;
32181}
32182function createProdServices() {
32183 return {
32184 setCurrentNode: () => { },
32185 createRootView: createProdRootView,
32186 createEmbeddedView: createEmbeddedView,
32187 createComponentView: createComponentView,
32188 createNgModuleRef: createNgModuleRef,
32189 overrideProvider: NOOP,
32190 overrideComponentView: NOOP,
32191 clearOverrides: NOOP,
32192 checkAndUpdateView: checkAndUpdateView,
32193 checkNoChangesView: checkNoChangesView,
32194 destroyView: destroyView,
32195 createDebugContext: (view, nodeIndex) => new DebugContext_(view, nodeIndex),
32196 handleEvent: (view, nodeIndex, eventName, event) => view.def.handleEvent(view, nodeIndex, eventName, event),
32197 updateDirectives: (view, checkType) => view.def.updateDirectives(checkType === 0 /* CheckAndUpdate */ ? prodCheckAndUpdateNode : prodCheckNoChangesNode, view),
32198 updateRenderer: (view, checkType) => view.def.updateRenderer(checkType === 0 /* CheckAndUpdate */ ? prodCheckAndUpdateNode : prodCheckNoChangesNode, view),
32199 };
32200}
32201function createDebugServices() {
32202 return {
32203 setCurrentNode: debugSetCurrentNode,
32204 createRootView: debugCreateRootView,
32205 createEmbeddedView: debugCreateEmbeddedView,
32206 createComponentView: debugCreateComponentView,
32207 createNgModuleRef: debugCreateNgModuleRef,
32208 overrideProvider: debugOverrideProvider,
32209 overrideComponentView: debugOverrideComponentView,
32210 clearOverrides: debugClearOverrides,
32211 checkAndUpdateView: debugCheckAndUpdateView,
32212 checkNoChangesView: debugCheckNoChangesView,
32213 destroyView: debugDestroyView,
32214 createDebugContext: (view, nodeIndex) => new DebugContext_(view, nodeIndex),
32215 handleEvent: debugHandleEvent,
32216 updateDirectives: debugUpdateDirectives,
32217 updateRenderer: debugUpdateRenderer,
32218 };
32219}
32220function createProdRootView(elInjector, projectableNodes, rootSelectorOrNode, def, ngModule, context) {
32221 const rendererFactory = ngModule.injector.get(RendererFactory2);
32222 return createRootView(createRootData(elInjector, ngModule, rendererFactory, projectableNodes, rootSelectorOrNode), def, context);
32223}
32224function debugCreateRootView(elInjector, projectableNodes, rootSelectorOrNode, def, ngModule, context) {
32225 const rendererFactory = ngModule.injector.get(RendererFactory2);
32226 const root = createRootData(elInjector, ngModule, new DebugRendererFactory2(rendererFactory), projectableNodes, rootSelectorOrNode);
32227 const defWithOverride = applyProviderOverridesToView(def);
32228 return callWithDebugContext(DebugAction.create, createRootView, null, [root, defWithOverride, context]);
32229}
32230function createRootData(elInjector, ngModule, rendererFactory, projectableNodes, rootSelectorOrNode) {
32231 const sanitizer = ngModule.injector.get(Sanitizer);
32232 const errorHandler = ngModule.injector.get(ErrorHandler);
32233 const renderer = rendererFactory.createRenderer(null, null);
32234 return {
32235 ngModule,
32236 injector: elInjector,
32237 projectableNodes,
32238 selectorOrNode: rootSelectorOrNode,
32239 sanitizer,
32240 rendererFactory,
32241 renderer,
32242 errorHandler
32243 };
32244}
32245function debugCreateEmbeddedView(parentView, anchorDef, viewDef, context) {
32246 const defWithOverride = applyProviderOverridesToView(viewDef);
32247 return callWithDebugContext(DebugAction.create, createEmbeddedView, null, [parentView, anchorDef, defWithOverride, context]);
32248}
32249function debugCreateComponentView(parentView, nodeDef, viewDef, hostElement) {
32250 const overrideComponentView = viewDefOverrides.get(nodeDef.element.componentProvider.provider.token);
32251 if (overrideComponentView) {
32252 viewDef = overrideComponentView;
32253 }
32254 else {
32255 viewDef = applyProviderOverridesToView(viewDef);
32256 }
32257 return callWithDebugContext(DebugAction.create, createComponentView, null, [parentView, nodeDef, viewDef, hostElement]);
32258}
32259function debugCreateNgModuleRef(moduleType, parentInjector, bootstrapComponents, def) {
32260 const defWithOverride = applyProviderOverridesToNgModule(def);
32261 return createNgModuleRef(moduleType, parentInjector, bootstrapComponents, defWithOverride);
32262}
32263const providerOverrides = new Map();
32264const providerOverridesWithScope = new Map();
32265const viewDefOverrides = new Map();
32266function debugOverrideProvider(override) {
32267 providerOverrides.set(override.token, override);
32268 let injectableDef;
32269 if (typeof override.token === 'function' && (injectableDef = getInjectableDef(override.token)) &&
32270 typeof injectableDef.providedIn === 'function') {
32271 providerOverridesWithScope.set(override.token, override);
32272 }
32273}
32274function debugOverrideComponentView(comp, compFactory) {
32275 const hostViewDef = resolveDefinition(getComponentViewDefinitionFactory(compFactory));
32276 const compViewDef = resolveDefinition(hostViewDef.nodes[0].element.componentView);
32277 viewDefOverrides.set(comp, compViewDef);
32278}
32279function debugClearOverrides() {
32280 providerOverrides.clear();
32281 providerOverridesWithScope.clear();
32282 viewDefOverrides.clear();
32283}
32284// Notes about the algorithm:
32285// 1) Locate the providers of an element and check if one of them was overwritten
32286// 2) Change the providers of that element
32287//
32288// We only create new data structures if we need to, to keep perf impact
32289// reasonable.
32290function applyProviderOverridesToView(def) {
32291 if (providerOverrides.size === 0) {
32292 return def;
32293 }
32294 const elementIndicesWithOverwrittenProviders = findElementIndicesWithOverwrittenProviders(def);
32295 if (elementIndicesWithOverwrittenProviders.length === 0) {
32296 return def;
32297 }
32298 // clone the whole view definition,
32299 // as it maintains references between the nodes that are hard to update.
32300 def = def.factory(() => NOOP);
32301 for (let i = 0; i < elementIndicesWithOverwrittenProviders.length; i++) {
32302 applyProviderOverridesToElement(def, elementIndicesWithOverwrittenProviders[i]);
32303 }
32304 return def;
32305 function findElementIndicesWithOverwrittenProviders(def) {
32306 const elIndicesWithOverwrittenProviders = [];
32307 let lastElementDef = null;
32308 for (let i = 0; i < def.nodes.length; i++) {
32309 const nodeDef = def.nodes[i];
32310 if (nodeDef.flags & 1 /* TypeElement */) {
32311 lastElementDef = nodeDef;
32312 }
32313 if (lastElementDef && nodeDef.flags & 3840 /* CatProviderNoDirective */ &&
32314 providerOverrides.has(nodeDef.provider.token)) {
32315 elIndicesWithOverwrittenProviders.push(lastElementDef.nodeIndex);
32316 lastElementDef = null;
32317 }
32318 }
32319 return elIndicesWithOverwrittenProviders;
32320 }
32321 function applyProviderOverridesToElement(viewDef, elIndex) {
32322 for (let i = elIndex + 1; i < viewDef.nodes.length; i++) {
32323 const nodeDef = viewDef.nodes[i];
32324 if (nodeDef.flags & 1 /* TypeElement */) {
32325 // stop at the next element
32326 return;
32327 }
32328 if (nodeDef.flags & 3840 /* CatProviderNoDirective */) {
32329 const provider = nodeDef.provider;
32330 const override = providerOverrides.get(provider.token);
32331 if (override) {
32332 nodeDef.flags = (nodeDef.flags & ~3840 /* CatProviderNoDirective */) | override.flags;
32333 provider.deps = splitDepsDsl(override.deps);
32334 provider.value = override.value;
32335 }
32336 }
32337 }
32338 }
32339}
32340// Notes about the algorithm:
32341// We only create new data structures if we need to, to keep perf impact
32342// reasonable.
32343function applyProviderOverridesToNgModule(def) {
32344 const { hasOverrides, hasDeprecatedOverrides } = calcHasOverrides(def);
32345 if (!hasOverrides) {
32346 return def;
32347 }
32348 // clone the whole view definition,
32349 // as it maintains references between the nodes that are hard to update.
32350 def = def.factory(() => NOOP);
32351 applyProviderOverrides(def);
32352 return def;
32353 function calcHasOverrides(def) {
32354 let hasOverrides = false;
32355 let hasDeprecatedOverrides = false;
32356 if (providerOverrides.size === 0) {
32357 return { hasOverrides, hasDeprecatedOverrides };
32358 }
32359 def.providers.forEach(node => {
32360 const override = providerOverrides.get(node.token);
32361 if ((node.flags & 3840 /* CatProviderNoDirective */) && override) {
32362 hasOverrides = true;
32363 hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
32364 }
32365 });
32366 def.modules.forEach(module => {
32367 providerOverridesWithScope.forEach((override, token) => {
32368 if (resolveForwardRef(getInjectableDef(token).providedIn) === module) {
32369 hasOverrides = true;
32370 hasDeprecatedOverrides = hasDeprecatedOverrides || override.deprecatedBehavior;
32371 }
32372 });
32373 });
32374 return { hasOverrides, hasDeprecatedOverrides };
32375 }
32376 function applyProviderOverrides(def) {
32377 for (let i = 0; i < def.providers.length; i++) {
32378 const provider = def.providers[i];
32379 if (hasDeprecatedOverrides) {
32380 // We had a bug where me made
32381 // all providers lazy. Keep this logic behind a flag
32382 // for migrating existing users.
32383 provider.flags |= 4096 /* LazyProvider */;
32384 }
32385 const override = providerOverrides.get(provider.token);
32386 if (override) {
32387 provider.flags = (provider.flags & ~3840 /* CatProviderNoDirective */) | override.flags;
32388 provider.deps = splitDepsDsl(override.deps);
32389 provider.value = override.value;
32390 }
32391 }
32392 if (providerOverridesWithScope.size > 0) {
32393 let moduleSet = new Set(def.modules);
32394 providerOverridesWithScope.forEach((override, token) => {
32395 if (moduleSet.has(resolveForwardRef(getInjectableDef(token).providedIn))) {
32396 let provider = {
32397 token: token,
32398 flags: override.flags | (hasDeprecatedOverrides ? 4096 /* LazyProvider */ : 0 /* None */),
32399 deps: splitDepsDsl(override.deps),
32400 value: override.value,
32401 index: def.providers.length,
32402 };
32403 def.providers.push(provider);
32404 def.providersByKey[tokenKey(token)] = provider;
32405 }
32406 });
32407 }
32408 }
32409}
32410function prodCheckAndUpdateNode(view, checkIndex, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
32411 const nodeDef = view.def.nodes[checkIndex];
32412 checkAndUpdateNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
32413 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32414 asPureExpressionData(view, checkIndex).value :
32415 undefined;
32416}
32417function prodCheckNoChangesNode(view, checkIndex, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9) {
32418 const nodeDef = view.def.nodes[checkIndex];
32419 checkNoChangesNode(view, nodeDef, argStyle, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
32420 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32421 asPureExpressionData(view, checkIndex).value :
32422 undefined;
32423}
32424function debugCheckAndUpdateView(view) {
32425 return callWithDebugContext(DebugAction.detectChanges, checkAndUpdateView, null, [view]);
32426}
32427function debugCheckNoChangesView(view) {
32428 return callWithDebugContext(DebugAction.checkNoChanges, checkNoChangesView, null, [view]);
32429}
32430function debugDestroyView(view) {
32431 return callWithDebugContext(DebugAction.destroy, destroyView, null, [view]);
32432}
32433var DebugAction;
32434(function (DebugAction) {
32435 DebugAction[DebugAction["create"] = 0] = "create";
32436 DebugAction[DebugAction["detectChanges"] = 1] = "detectChanges";
32437 DebugAction[DebugAction["checkNoChanges"] = 2] = "checkNoChanges";
32438 DebugAction[DebugAction["destroy"] = 3] = "destroy";
32439 DebugAction[DebugAction["handleEvent"] = 4] = "handleEvent";
32440})(DebugAction || (DebugAction = {}));
32441let _currentAction;
32442let _currentView;
32443let _currentNodeIndex;
32444function debugSetCurrentNode(view, nodeIndex) {
32445 _currentView = view;
32446 _currentNodeIndex = nodeIndex;
32447}
32448function debugHandleEvent(view, nodeIndex, eventName, event) {
32449 debugSetCurrentNode(view, nodeIndex);
32450 return callWithDebugContext(DebugAction.handleEvent, view.def.handleEvent, null, [view, nodeIndex, eventName, event]);
32451}
32452function debugUpdateDirectives(view, checkType) {
32453 if (view.state & 128 /* Destroyed */) {
32454 throw viewDestroyedError(DebugAction[_currentAction]);
32455 }
32456 debugSetCurrentNode(view, nextDirectiveWithBinding(view, 0));
32457 return view.def.updateDirectives(debugCheckDirectivesFn, view);
32458 function debugCheckDirectivesFn(view, nodeIndex, argStyle, ...values) {
32459 const nodeDef = view.def.nodes[nodeIndex];
32460 if (checkType === 0 /* CheckAndUpdate */) {
32461 debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
32462 }
32463 else {
32464 debugCheckNoChangesNode(view, nodeDef, argStyle, values);
32465 }
32466 if (nodeDef.flags & 16384 /* TypeDirective */) {
32467 debugSetCurrentNode(view, nextDirectiveWithBinding(view, nodeIndex));
32468 }
32469 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32470 asPureExpressionData(view, nodeDef.nodeIndex).value :
32471 undefined;
32472 }
32473}
32474function debugUpdateRenderer(view, checkType) {
32475 if (view.state & 128 /* Destroyed */) {
32476 throw viewDestroyedError(DebugAction[_currentAction]);
32477 }
32478 debugSetCurrentNode(view, nextRenderNodeWithBinding(view, 0));
32479 return view.def.updateRenderer(debugCheckRenderNodeFn, view);
32480 function debugCheckRenderNodeFn(view, nodeIndex, argStyle, ...values) {
32481 const nodeDef = view.def.nodes[nodeIndex];
32482 if (checkType === 0 /* CheckAndUpdate */) {
32483 debugCheckAndUpdateNode(view, nodeDef, argStyle, values);
32484 }
32485 else {
32486 debugCheckNoChangesNode(view, nodeDef, argStyle, values);
32487 }
32488 if (nodeDef.flags & 3 /* CatRenderNode */) {
32489 debugSetCurrentNode(view, nextRenderNodeWithBinding(view, nodeIndex));
32490 }
32491 return (nodeDef.flags & 224 /* CatPureExpression */) ?
32492 asPureExpressionData(view, nodeDef.nodeIndex).value :
32493 undefined;
32494 }
32495}
32496function debugCheckAndUpdateNode(view, nodeDef, argStyle, givenValues) {
32497 const changed = checkAndUpdateNode(view, nodeDef, argStyle, ...givenValues);
32498 if (changed) {
32499 const values = argStyle === 1 /* Dynamic */ ? givenValues[0] : givenValues;
32500 if (nodeDef.flags & 16384 /* TypeDirective */) {
32501 const bindingValues = {};
32502 for (let i = 0; i < nodeDef.bindings.length; i++) {
32503 const binding = nodeDef.bindings[i];
32504 const value = values[i];
32505 if (binding.flags & 8 /* TypeProperty */) {
32506 bindingValues[normalizeDebugBindingName(binding.nonMinifiedName)] =
32507 normalizeDebugBindingValue(value);
32508 }
32509 }
32510 const elDef = nodeDef.parent;
32511 const el = asElementData(view, elDef.nodeIndex).renderElement;
32512 if (!elDef.element.name) {
32513 // a comment.
32514 view.renderer.setValue(el, escapeCommentText(`bindings=${JSON.stringify(bindingValues, null, 2)}`));
32515 }
32516 else {
32517 // a regular element.
32518 for (let attr in bindingValues) {
32519 const value = bindingValues[attr];
32520 if (value != null) {
32521 view.renderer.setAttribute(el, attr, value);
32522 }
32523 else {
32524 view.renderer.removeAttribute(el, attr);
32525 }
32526 }
32527 }
32528 }
32529 }
32530}
32531function debugCheckNoChangesNode(view, nodeDef, argStyle, values) {
32532 checkNoChangesNode(view, nodeDef, argStyle, ...values);
32533}
32534function nextDirectiveWithBinding(view, nodeIndex) {
32535 for (let i = nodeIndex; i < view.def.nodes.length; i++) {
32536 const nodeDef = view.def.nodes[i];
32537 if (nodeDef.flags & 16384 /* TypeDirective */ && nodeDef.bindings && nodeDef.bindings.length) {
32538 return i;
32539 }
32540 }
32541 return null;
32542}
32543function nextRenderNodeWithBinding(view, nodeIndex) {
32544 for (let i = nodeIndex; i < view.def.nodes.length; i++) {
32545 const nodeDef = view.def.nodes[i];
32546 if ((nodeDef.flags & 3 /* CatRenderNode */) && nodeDef.bindings && nodeDef.bindings.length) {
32547 return i;
32548 }
32549 }
32550 return null;
32551}
32552class DebugContext_ {
32553 constructor(view, nodeIndex) {
32554 this.view = view;
32555 this.nodeIndex = nodeIndex;
32556 if (nodeIndex == null) {
32557 this.nodeIndex = nodeIndex = 0;
32558 }
32559 this.nodeDef = view.def.nodes[nodeIndex];
32560 let elDef = this.nodeDef;
32561 let elView = view;
32562 while (elDef && (elDef.flags & 1 /* TypeElement */) === 0) {
32563 elDef = elDef.parent;
32564 }
32565 if (!elDef) {
32566 while (!elDef && elView) {
32567 elDef = viewParentEl(elView);
32568 elView = elView.parent;
32569 }
32570 }
32571 this.elDef = elDef;
32572 this.elView = elView;
32573 }
32574 get elOrCompView() {
32575 // Has to be done lazily as we use the DebugContext also during creation of elements...
32576 return asElementData(this.elView, this.elDef.nodeIndex).componentView || this.view;
32577 }
32578 get injector() {
32579 return createInjector(this.elView, this.elDef);
32580 }
32581 get component() {
32582 return this.elOrCompView.component;
32583 }
32584 get context() {
32585 return this.elOrCompView.context;
32586 }
32587 get providerTokens() {
32588 const tokens = [];
32589 if (this.elDef) {
32590 for (let i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount; i++) {
32591 const childDef = this.elView.def.nodes[i];
32592 if (childDef.flags & 20224 /* CatProvider */) {
32593 tokens.push(childDef.provider.token);
32594 }
32595 i += childDef.childCount;
32596 }
32597 }
32598 return tokens;
32599 }
32600 get references() {
32601 const references = {};
32602 if (this.elDef) {
32603 collectReferences(this.elView, this.elDef, references);
32604 for (let i = this.elDef.nodeIndex + 1; i <= this.elDef.nodeIndex + this.elDef.childCount; i++) {
32605 const childDef = this.elView.def.nodes[i];
32606 if (childDef.flags & 20224 /* CatProvider */) {
32607 collectReferences(this.elView, childDef, references);
32608 }
32609 i += childDef.childCount;
32610 }
32611 }
32612 return references;
32613 }
32614 get componentRenderElement() {
32615 const elData = findHostElement(this.elOrCompView);
32616 return elData ? elData.renderElement : undefined;
32617 }
32618 get renderNode() {
32619 return this.nodeDef.flags & 2 /* TypeText */ ? renderNode(this.view, this.nodeDef) :
32620 renderNode(this.elView, this.elDef);
32621 }
32622 logError(console, ...values) {
32623 let logViewDef;
32624 let logNodeIndex;
32625 if (this.nodeDef.flags & 2 /* TypeText */) {
32626 logViewDef = this.view.def;
32627 logNodeIndex = this.nodeDef.nodeIndex;
32628 }
32629 else {
32630 logViewDef = this.elView.def;
32631 logNodeIndex = this.elDef.nodeIndex;
32632 }
32633 // Note: we only generate a log function for text and element nodes
32634 // to make the generated code as small as possible.
32635 const renderNodeIndex = getRenderNodeIndex(logViewDef, logNodeIndex);
32636 let currRenderNodeIndex = -1;
32637 let nodeLogger = () => {
32638 currRenderNodeIndex++;
32639 if (currRenderNodeIndex === renderNodeIndex) {
32640 return console.error.bind(console, ...values);
32641 }
32642 else {
32643 return NOOP;
32644 }
32645 };
32646 logViewDef.factory(nodeLogger);
32647 if (currRenderNodeIndex < renderNodeIndex) {
32648 console.error('Illegal state: the ViewDefinitionFactory did not call the logger!');
32649 console.error(...values);
32650 }
32651 }
32652}
32653function getRenderNodeIndex(viewDef, nodeIndex) {
32654 let renderNodeIndex = -1;
32655 for (let i = 0; i <= nodeIndex; i++) {
32656 const nodeDef = viewDef.nodes[i];
32657 if (nodeDef.flags & 3 /* CatRenderNode */) {
32658 renderNodeIndex++;
32659 }
32660 }
32661 return renderNodeIndex;
32662}
32663function findHostElement(view) {
32664 while (view && !isComponentView(view)) {
32665 view = view.parent;
32666 }
32667 if (view.parent) {
32668 return asElementData(view.parent, viewParentEl(view).nodeIndex);
32669 }
32670 return null;
32671}
32672function collectReferences(view, nodeDef, references) {
32673 for (let refName in nodeDef.references) {
32674 references[refName] = getQueryValue(view, nodeDef, nodeDef.references[refName]);
32675 }
32676}
32677function callWithDebugContext(action, fn, self, args) {
32678 const oldAction = _currentAction;
32679 const oldView = _currentView;
32680 const oldNodeIndex = _currentNodeIndex;
32681 try {
32682 _currentAction = action;
32683 const result = fn.apply(self, args);
32684 _currentView = oldView;
32685 _currentNodeIndex = oldNodeIndex;
32686 _currentAction = oldAction;
32687 return result;
32688 }
32689 catch (e) {
32690 if (isViewDebugError(e) || !_currentView) {
32691 throw e;
32692 }
32693 throw viewWrappedDebugError(e, getCurrentDebugContext());
32694 }
32695}
32696function getCurrentDebugContext() {
32697 return _currentView ? new DebugContext_(_currentView, _currentNodeIndex) : null;
32698}
32699class DebugRendererFactory2 {
32700 constructor(delegate) {
32701 this.delegate = delegate;
32702 }
32703 createRenderer(element, renderData) {
32704 return new DebugRenderer2(this.delegate.createRenderer(element, renderData));
32705 }
32706 begin() {
32707 if (this.delegate.begin) {
32708 this.delegate.begin();
32709 }
32710 }
32711 end() {
32712 if (this.delegate.end) {
32713 this.delegate.end();
32714 }
32715 }
32716 whenRenderingDone() {
32717 if (this.delegate.whenRenderingDone) {
32718 return this.delegate.whenRenderingDone();
32719 }
32720 return Promise.resolve(null);
32721 }
32722}
32723class DebugRenderer2 {
32724 constructor(delegate) {
32725 this.delegate = delegate;
32726 /**
32727 * Factory function used to create a `DebugContext` when a node is created.
32728 *
32729 * The `DebugContext` allows to retrieve information about the nodes that are useful in tests.
32730 *
32731 * The factory is configurable so that the `DebugRenderer2` could instantiate either a View Engine
32732 * or a Render context.
32733 */
32734 this.debugContextFactory = getCurrentDebugContext;
32735 this.data = this.delegate.data;
32736 }
32737 createDebugContext(nativeElement) {
32738 return this.debugContextFactory(nativeElement);
32739 }
32740 destroyNode(node) {
32741 const debugNode = getDebugNode(node);
32742 if (debugNode) {
32743 removeDebugNodeFromIndex(debugNode);
32744 if (debugNode instanceof DebugNode__PRE_R3__) {
32745 debugNode.listeners.length = 0;
32746 }
32747 }
32748 if (this.delegate.destroyNode) {
32749 this.delegate.destroyNode(node);
32750 }
32751 }
32752 destroy() {
32753 this.delegate.destroy();
32754 }
32755 createElement(name, namespace) {
32756 const el = this.delegate.createElement(name, namespace);
32757 const debugCtx = this.createDebugContext(el);
32758 if (debugCtx) {
32759 const debugEl = new DebugElement__PRE_R3__(el, null, debugCtx);
32760 debugEl.name = name;
32761 indexDebugNode(debugEl);
32762 }
32763 return el;
32764 }
32765 createComment(value) {
32766 const comment = this.delegate.createComment(escapeCommentText(value));
32767 const debugCtx = this.createDebugContext(comment);
32768 if (debugCtx) {
32769 indexDebugNode(new DebugNode__PRE_R3__(comment, null, debugCtx));
32770 }
32771 return comment;
32772 }
32773 createText(value) {
32774 const text = this.delegate.createText(value);
32775 const debugCtx = this.createDebugContext(text);
32776 if (debugCtx) {
32777 indexDebugNode(new DebugNode__PRE_R3__(text, null, debugCtx));
32778 }
32779 return text;
32780 }
32781 appendChild(parent, newChild) {
32782 const debugEl = getDebugNode(parent);
32783 const debugChildEl = getDebugNode(newChild);
32784 if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
32785 debugEl.addChild(debugChildEl);
32786 }
32787 this.delegate.appendChild(parent, newChild);
32788 }
32789 insertBefore(parent, newChild, refChild, isMove) {
32790 const debugEl = getDebugNode(parent);
32791 const debugChildEl = getDebugNode(newChild);
32792 const debugRefEl = getDebugNode(refChild);
32793 if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
32794 debugEl.insertBefore(debugRefEl, debugChildEl);
32795 }
32796 this.delegate.insertBefore(parent, newChild, refChild, isMove);
32797 }
32798 removeChild(parent, oldChild) {
32799 const debugEl = getDebugNode(parent);
32800 const debugChildEl = getDebugNode(oldChild);
32801 if (debugEl && debugChildEl && debugEl instanceof DebugElement__PRE_R3__) {
32802 debugEl.removeChild(debugChildEl);
32803 }
32804 this.delegate.removeChild(parent, oldChild);
32805 }
32806 selectRootElement(selectorOrNode, preserveContent) {
32807 const el = this.delegate.selectRootElement(selectorOrNode, preserveContent);
32808 const debugCtx = getCurrentDebugContext();
32809 if (debugCtx) {
32810 indexDebugNode(new DebugElement__PRE_R3__(el, null, debugCtx));
32811 }
32812 return el;
32813 }
32814 setAttribute(el, name, value, namespace) {
32815 const debugEl = getDebugNode(el);
32816 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32817 const fullName = namespace ? namespace + ':' + name : name;
32818 debugEl.attributes[fullName] = value;
32819 }
32820 this.delegate.setAttribute(el, name, value, namespace);
32821 }
32822 removeAttribute(el, name, namespace) {
32823 const debugEl = getDebugNode(el);
32824 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32825 const fullName = namespace ? namespace + ':' + name : name;
32826 debugEl.attributes[fullName] = null;
32827 }
32828 this.delegate.removeAttribute(el, name, namespace);
32829 }
32830 addClass(el, name) {
32831 const debugEl = getDebugNode(el);
32832 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32833 debugEl.classes[name] = true;
32834 }
32835 this.delegate.addClass(el, name);
32836 }
32837 removeClass(el, name) {
32838 const debugEl = getDebugNode(el);
32839 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32840 debugEl.classes[name] = false;
32841 }
32842 this.delegate.removeClass(el, name);
32843 }
32844 setStyle(el, style, value, flags) {
32845 const debugEl = getDebugNode(el);
32846 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32847 debugEl.styles[style] = value;
32848 }
32849 this.delegate.setStyle(el, style, value, flags);
32850 }
32851 removeStyle(el, style, flags) {
32852 const debugEl = getDebugNode(el);
32853 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32854 debugEl.styles[style] = null;
32855 }
32856 this.delegate.removeStyle(el, style, flags);
32857 }
32858 setProperty(el, name, value) {
32859 const debugEl = getDebugNode(el);
32860 if (debugEl && debugEl instanceof DebugElement__PRE_R3__) {
32861 debugEl.properties[name] = value;
32862 }
32863 this.delegate.setProperty(el, name, value);
32864 }
32865 listen(target, eventName, callback) {
32866 if (typeof target !== 'string') {
32867 const debugEl = getDebugNode(target);
32868 if (debugEl) {
32869 debugEl.listeners.push(new DebugEventListener(eventName, callback));
32870 }
32871 }
32872 return this.delegate.listen(target, eventName, callback);
32873 }
32874 parentNode(node) {
32875 return this.delegate.parentNode(node);
32876 }
32877 nextSibling(node) {
32878 return this.delegate.nextSibling(node);
32879 }
32880 setValue(node, value) {
32881 return this.delegate.setValue(node, value);
32882 }
32883}
32884
32885/**
32886 * @license
32887 * Copyright Google LLC All Rights Reserved.
32888 *
32889 * Use of this source code is governed by an MIT-style license that can be
32890 * found in the LICENSE file at https://angular.io/license
32891 */
32892function overrideProvider(override) {
32893 initServicesIfNeeded();
32894 return Services.overrideProvider(override);
32895}
32896function overrideComponentView(comp, componentFactory) {
32897 initServicesIfNeeded();
32898 return Services.overrideComponentView(comp, componentFactory);
32899}
32900function clearOverrides() {
32901 initServicesIfNeeded();
32902 return Services.clearOverrides();
32903}
32904// Attention: this function is called as top level function.
32905// Putting any logic in here will destroy closure tree shaking!
32906function createNgModuleFactory(ngModuleType, bootstrapComponents, defFactory) {
32907 return new NgModuleFactory_(ngModuleType, bootstrapComponents, defFactory);
32908}
32909function cloneNgModuleDefinition(def) {
32910 const providers = Array.from(def.providers);
32911 const modules = Array.from(def.modules);
32912 const providersByKey = {};
32913 for (const key in def.providersByKey) {
32914 providersByKey[key] = def.providersByKey[key];
32915 }
32916 return {
32917 factory: def.factory,
32918 scope: def.scope,
32919 providers,
32920 modules,
32921 providersByKey,
32922 };
32923}
32924class NgModuleFactory_ extends NgModuleFactory$1 {
32925 constructor(moduleType, _bootstrapComponents, _ngModuleDefFactory) {
32926 // Attention: this ctor is called as top level function.
32927 // Putting any logic in here will destroy closure tree shaking!
32928 super();
32929 this.moduleType = moduleType;
32930 this._bootstrapComponents = _bootstrapComponents;
32931 this._ngModuleDefFactory = _ngModuleDefFactory;
32932 }
32933 create(parentInjector) {
32934 initServicesIfNeeded();
32935 // Clone the NgModuleDefinition so that any tree shakeable provider definition
32936 // added to this instance of the NgModuleRef doesn't affect the cached copy.
32937 // See https://github.com/angular/angular/issues/25018.
32938 const def = cloneNgModuleDefinition(resolveDefinition(this._ngModuleDefFactory));
32939 return Services.createNgModuleRef(this.moduleType, parentInjector || Injector.NULL, this._bootstrapComponents, def);
32940 }
32941}
32942
32943/**
32944 * @license
32945 * Copyright Google LLC All Rights Reserved.
32946 *
32947 * Use of this source code is governed by an MIT-style license that can be
32948 * found in the LICENSE file at https://angular.io/license
32949 */
32950
32951/**
32952 * @license
32953 * Copyright Google LLC All Rights Reserved.
32954 *
32955 * Use of this source code is governed by an MIT-style license that can be
32956 * found in the LICENSE file at https://angular.io/license
32957 */
32958
32959/**
32960 * @license
32961 * Copyright Google LLC All Rights Reserved.
32962 *
32963 * Use of this source code is governed by an MIT-style license that can be
32964 * found in the LICENSE file at https://angular.io/license
32965 */
32966/**
32967 * Compiles a partial directive declaration object into a full directive definition object.
32968 *
32969 * @codeGenApi
32970 */
32971function ɵɵngDeclareDirective(decl) {
32972 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'directive', type: decl.type });
32973 return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
32974}
32975/**
32976 * Evaluates the class metadata declaration.
32977 *
32978 * @codeGenApi
32979 */
32980function ɵɵngDeclareClassMetadata(decl) {
32981 var _a, _b;
32982 setClassMetadata(decl.type, decl.decorators, (_a = decl.ctorParameters) !== null && _a !== void 0 ? _a : null, (_b = decl.propDecorators) !== null && _b !== void 0 ? _b : null);
32983}
32984/**
32985 * Compiles a partial component declaration object into a full component definition object.
32986 *
32987 * @codeGenApi
32988 */
32989function ɵɵngDeclareComponent(decl) {
32990 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'component', type: decl.type });
32991 return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
32992}
32993/**
32994 * Compiles a partial pipe declaration object into a full pipe definition object.
32995 *
32996 * @codeGenApi
32997 */
32998function ɵɵngDeclareFactory(decl) {
32999 const compiler = getCompilerFacade({
33000 usage: 1 /* PartialDeclaration */,
33001 kind: getFactoryKind(decl.target),
33002 type: decl.type
33003 });
33004 return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
33005}
33006function getFactoryKind(target) {
33007 switch (target) {
33008 case FactoryTarget.Directive:
33009 return 'directive';
33010 case FactoryTarget.Component:
33011 return 'component';
33012 case FactoryTarget.Injectable:
33013 return 'injectable';
33014 case FactoryTarget.Pipe:
33015 return 'pipe';
33016 case FactoryTarget.NgModule:
33017 return 'NgModule';
33018 }
33019}
33020/**
33021 * Compiles a partial injectable declaration object into a full injectable definition object.
33022 *
33023 * @codeGenApi
33024 */
33025function ɵɵngDeclareInjectable(decl) {
33026 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'injectable', type: decl.type });
33027 return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
33028}
33029/**
33030 * Compiles a partial injector declaration object into a full injector definition object.
33031 *
33032 * @codeGenApi
33033 */
33034function ɵɵngDeclareInjector(decl) {
33035 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'NgModule', type: decl.type });
33036 return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
33037}
33038/**
33039 * Compiles a partial NgModule declaration object into a full NgModule definition object.
33040 *
33041 * @codeGenApi
33042 */
33043function ɵɵngDeclareNgModule(decl) {
33044 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'NgModule', type: decl.type });
33045 return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
33046}
33047/**
33048 * Compiles a partial pipe declaration object into a full pipe definition object.
33049 *
33050 * @codeGenApi
33051 */
33052function ɵɵngDeclarePipe(decl) {
33053 const compiler = getCompilerFacade({ usage: 1 /* PartialDeclaration */, kind: 'pipe', type: decl.type });
33054 return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
33055}
33056
33057/**
33058 * @license
33059 * Copyright Google LLC All Rights Reserved.
33060 *
33061 * Use of this source code is governed by an MIT-style license that can be
33062 * found in the LICENSE file at https://angular.io/license
33063 */
33064// clang-format on
33065
33066/**
33067 * @license
33068 * Copyright Google LLC All Rights Reserved.
33069 *
33070 * Use of this source code is governed by an MIT-style license that can be
33071 * found in the LICENSE file at https://angular.io/license
33072 */
33073
33074/**
33075 * @license
33076 * Copyright Google LLC All Rights Reserved.
33077 *
33078 * Use of this source code is governed by an MIT-style license that can be
33079 * found in the LICENSE file at https://angular.io/license
33080 */
33081if (typeof ngDevMode !== 'undefined' && ngDevMode) {
33082 // This helper is to give a reasonable error message to people upgrading to v9 that have not yet
33083 // installed `@angular/localize` in their app.
33084 // tslint:disable-next-line: no-toplevel-property-access
33085 _global.$localize = _global.$localize || function () {
33086 throw new Error('It looks like your application or one of its dependencies is using i18n.\n' +
33087 'Angular 9 introduced a global `$localize()` function that needs to be loaded.\n' +
33088 'Please run `ng add @angular/localize` from the Angular CLI.\n' +
33089 '(For non-CLI projects, add `import \'@angular/localize/init\';` to your `polyfills.ts` file.\n' +
33090 'For server-side rendering applications add the import to your `main.server.ts` file.)');
33091 };
33092}
33093
33094/**
33095 * @license
33096 * Copyright Google LLC All Rights Reserved.
33097 *
33098 * Use of this source code is governed by an MIT-style license that can be
33099 * found in the LICENSE file at https://angular.io/license
33100 */
33101// This file only reexports content of the `src` folder. Keep it that way.
33102
33103/**
33104 * @license
33105 * Copyright Google LLC All Rights Reserved.
33106 *
33107 * Use of this source code is governed by an MIT-style license that can be
33108 * found in the LICENSE file at https://angular.io/license
33109 */
33110
33111/**
33112 * Generated bundle index. Do not edit.
33113 */
33114
33115export { 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 };
33116//# sourceMappingURL=core.mjs.map