PageSourceSearch

https://opticaboavista.com/polyfills.js

js opticaboavista.com collected 2026-10-06 07:18:43 UTC 990,605 bytes, 32,007 lines download raw bytes

1"use strict";
2(self["webpackChunkoptica_boavista"] = self["webpackChunkoptica_boavista"] || []).push([["polyfills"],{
3
4/***/ 7435:
5/*!**************************!*\
6  !*** ./src/polyfills.ts ***!
7  \**************************/
8/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9
10__webpack_require__.r(__webpack_exports__);
11/* harmony import */ var _angular_localize_init__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/localize/init */ 6344);
12/* harmony import */ var zone_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! zone.js */ 4946);
13/* harmony import */ var zone_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(zone_js__WEBPACK_IMPORTED_MODULE_1__);
14/***************************************************************************************************
15 * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
16 */
17
18/**
19 * This file includes polyfills needed by Angular and is loaded before the app.
20 * You can add your own extra polyfills to this file.
21 *
22 * This file is divided into 2 sections:
23 *   1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
24 *   2. Application imports. Files imported after ZoneJS that should be loaded before your main
25 *      file.
26 *
27 * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
28 * automatically update themselves. This includes recent versions of Safari, Chrome (including
29 * Opera), Edge on the desktop, and iOS and Chrome on mobile.
30 *
31 * Learn more in https://angular.io/guide/browser-support
32 */
33/***************************************************************************************************
34 * BROWSER POLYFILLS
35 */
36/**
37 * By default, zone.js will patch all possible macroTask and DomEvents
38 * user can disable parts of macroTask/DomEvents patch by setting following flags
39 * because those flags need to be set before `zone.js` being loaded, and webpack
40 * will put import in the top of bundle, so user need to create a separate file
41 * in this directory (for example: zone-flags.ts), and put the following flags
42 * into that file, and then add the following code before importing zone.js.
43 * import './zone-flags';
44 *
45 * The flags allowed in zone-flags.ts are listed here.
46 *
47 * The following flags will work for all browsers.
48 *
49 * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
50 * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
51 * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
52 *
53 *  in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
54 *  with the following flag, it will bypass `zone.js` patch for IE/Edge
55 *
56 *  (window as any).__Zone_enable_cross_context_check = true;
57 *
58 */
59/***************************************************************************************************
60 * Zone JS is required by default for Angular itself.
61 */
62 // Included with Angular CLI.
63/***************************************************************************************************
64 * APPLICATION IMPORTS
65 */
66
67
68/***/ }),
69
70/***/ 4946:
71/*!***********************************************!*\
72  !*** ./node_modules/zone.js/fesm2015/zone.js ***!
73  \***********************************************/
74/***/ (() => {
75
76
77/**
78 * @license Angular v14.2.0-next.0
79 * (c) 2010-2022 Google LLC. https://angular.io/
80 * License: MIT
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 */
90
91(function (global) {
92  const performance = global['performance'];
93
94  function mark(name) {
95    performance && performance['mark'] && performance['mark'](name);
96  }
97
98  function performanceMeasure(name, label) {
99    performance && performance['measure'] && performance['measure'](name, label);
100  }
101
102  mark('Zone'); // Initialize before it's accessed below.
103  // __Zone_symbol_prefix global can be used to override the default zone
104  // symbol prefix with a custom one if needed.
105
106  const symbolPrefix = global['__Zone_symbol_prefix'] || '__zone_symbol__';
107
108  function __symbol__(name) {
109    return symbolPrefix + name;
110  }
111
112  const checkDuplicate = global[__symbol__('forceDuplicateZoneCheck')] === true;
113
114  if (global['Zone']) {
115    // if global['Zone'] already exists (maybe zone.js was already loaded or
116    // some other lib also registered a global object named Zone), we may 
vendor: 21,308 bytes, lines 116-742
116need
117    // to throw an error, but sometimes user may not want this error.
118    // For example,
119    // we have two web pages, page1 includes zone.js, page2 doesn't.
120    // and the 1st time user load page1 and page2, everything work fine,
121    // but when user load page2 again, error occurs because global['Zone'] already exists.
122    // so we add a flag to let user choose whether to throw this error or not.
123    // By default, if existing Zone is from zone.js, we will not throw the error.
124    if (checkDuplicate || typeof global['Zone'].__symbol__ !== 'function') {
125      throw new Error('Zone already loaded.');
126    } else {
127      return global['Zone'];
128    }
129  }
130
131  class Zone {
132    constructor(parent, zoneSpec) {
133      this._parent = parent;
134      this._name = zoneSpec ? zoneSpec.name || 'unnamed' : '<root>';
135      this._properties = zoneSpec && zoneSpec.properties || {};
136      this._zoneDelegate = new _ZoneDelegate(this, this._parent && this._parent._zoneDelegate, zoneSpec);
137    }
138
139    static assertZonePatched() {
140      if (global['Promise'] !== patches['ZoneAwarePromise']) {
141        throw new Error('Zone.js has detected that ZoneAwarePromise `(window|global).Promise` ' + 'has been overwritten.\n' + 'Most likely cause is that a Promise polyfill has been loaded ' + 'after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. ' + 'If you must load one, do so before loading zone.js.)');
142      }
143    }
144
145    static get root() {
146      let zone = Zone.current;
147
148      while (zone.parent) {
149        zone = zone.parent;
150      }
151
152      return zone;
153    }
154
155    static get current() {
156      return _currentZoneFrame.zone;
157    }
158
159    static get currentTask() {
160      return _currentTask;
161    } // tslint:disable-next-line:require-internal-with-underscore
162
163
164    static __load_patch(name, fn, ignoreDuplicate = false) {
165      if (patches.hasOwnProperty(name)) {
166        // `checkDuplicate` option is defined from global variable
167        // so it works for all modules.
168        // `ignoreDuplicate` can work for the specified module
169        if (!ignoreDuplicate && checkDuplicate) {
170          throw Error('Already loaded patch: ' + name);
171        }
172      } else if (!global['__Zone_disable_' + name]) {
173        const perfName = 'Zone:' + name;
174        mark(perfName);
175        patches[name] = fn(global, Zone, _api);
176        performanceMeasure(perfName, perfName);
177      }
178    }
179
180    get parent() {
181      return this._parent;
182    }
183
184    get name() {
185      return this._name;
186    }
187
188    get(key) {
189      const zone = this.getZoneWith(key);
190      if (zone) return zone._properties[key];
191    }
192
193    getZoneWith(key) {
194      let current = this;
195
196      while (current) {
197        if (current._properties.hasOwnProperty(key)) {
198          return current;
199        }
200
201        current = current._parent;
202      }
203
204      return null;
205    }
206
207    fork(zoneSpec) {
208      if (!zoneSpec) throw new Error('ZoneSpec required!');
209      return this._zoneDelegate.fork(this, zoneSpec);
210    }
211
212    wrap(callback, source) {
213      if (typeof callback !== 'function') {
214        throw new Error('Expecting function got: ' + callback);
215      }
216
217      const _callback = this._zoneDelegate.intercept(this, callback, source);
218
219      const zone = this;
220      return function () {
221        return zone.runGuarded(_callback, this, arguments, source);
222      };
223    }
224
225    run(callback, applyThis, applyArgs, source) {
226      _currentZoneFrame = {
227        parent: _currentZoneFrame,
228        zone: this
229      };
230
231      try {
232        return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);
233      } finally {
234        _currentZoneFrame = _currentZoneFrame.parent;
235      }
236    }
237
238    runGuarded(callback, applyThis = null, applyArgs, source) {
239      _currentZoneFrame = {
240        parent: _currentZoneFrame,
241        zone: this
242      };
243
244      try {
245        try {
246          return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);
247        } catch (error) {
248          if (this._zoneDelegate.handleError(this, error)) {
249            throw error;
250          }
251        }
252      } finally {
253        _currentZoneFrame = _currentZoneFrame.parent;
254      }
255    }
256
257    runTask(task, applyThis, applyArgs) {
258      if (task.zone != this) {
259        throw new Error('A task can only be run in the zone of creation! (Creation: ' + (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');
260      } // https://github.com/angular/zone.js/issues/778, sometimes eventTask
261      // will run in notScheduled(canceled) state, we should not try to
262      // run such kind of task but just return
263
264
265      if (task.state === notScheduled && (task.type === eventTask || task.type === macroTask)) {
266        return;
267      }
268
269      const reEntryGuard = task.state != running;
270      reEntryGuard && task._transitionTo(running, scheduled);
271      task.runCount++;
272      const previousTask = _currentTask;
273      _currentTask = task;
274      _currentZoneFrame = {
275        parent: _currentZoneFrame,
276        zone: this
277      };
278
279      try {
280        if (task.type == macroTask && task.data && !task.data.isPeriodic) {
281          task.cancelFn = undefined;
282        }
283
284        try {
285          return this._zoneDelegate.invokeTask(this, task, applyThis, applyArgs);
286        } catch (error) {
287          if (this._zoneDelegate.handleError(this, error)) {
288            throw error;
289          }
290        }
291      } finally {
292        // if the task's state is notScheduled or unknown, then it has already been cancelled
293        // we should not reset the state to scheduled
294        if (task.state !== notScheduled && task.state !== unknown) {
295          if (task.type == eventTask || task.data && task.data.isPeriodic) {
296            reEntryGuard && task._transitionTo(scheduled, running);
297          } else {
298            task.runCount = 0;
299
300            this._updateTaskCount(task, -1);
301
302            reEntryGuard && task._transitionTo(notScheduled, running, notScheduled);
303          }
304        }
305
306        _currentZoneFrame = _currentZoneFrame.parent;
307        _currentTask = previousTask;
308      }
309    }
310
311    scheduleTask(task) {
312      if (task.zone && task.zone !== this) {
313        // check if the task was rescheduled, the newZone
314        // should not be the children of the original zone
315        let newZone = this;
316
317        while (newZone) {
318          if (newZone === task.zone) {
319            throw Error(`can not reschedule task to ${this.name} which is descendants of the original zone ${task.zone.name}`);
320          }
321
322          newZone = newZone.parent;
323        }
324      }
325
326      task._transitionTo(scheduling, notScheduled);
327
328      const zoneDelegates = [];
329      task._zoneDelegates = zoneDelegates;
330      task._zone = this;
331
332      try {
333        task = this._zoneDelegate.scheduleTask(this, task);
334      } catch (err) {
335        // should set task's state to unknown when scheduleTask throw error
336        // because the err may from reschedule, so the fromState maybe notScheduled
337        task._transitionTo(unknown, scheduling, notScheduled); // TODO: @JiaLiPassion, should we check the result from handleError?
338
339
340        this._zoneDelegate.handleError(this, err);
341
342        throw err;
343      }
344
345      if (task._zoneDelegates === zoneDelegates) {
346        // we have to check because internally the delegate can reschedule the task.
347        this._updateTaskCount(task, 1);
348      }
349
350      if (task.state == scheduling) {
351        task._transitionTo(scheduled, scheduling);
352      }
353
354      return task;
355    }
356
357    scheduleMicroTask(source, callback, data, customSchedule) {
358      return this.scheduleTask(new ZoneTask(microTask, source, callback, data, customSchedule, undefined));
359    }
360
361    scheduleMacroTask(source, callback, data, customSchedule, customCancel) {
362      return this.scheduleTask(new ZoneTask(macroTask, source, callback, data, customSchedule, customCancel));
363    }
364
365    scheduleEventTask(source, callback, data, customSchedule, customCancel) {
366      return this.scheduleTask(new ZoneTask(eventTask, source, callback, data, customSchedule, customCancel));
367    }
368
369    cancelTask(task) {
370      if (task.zone != this) throw new Error('A task can only be cancelled in the zone of creation! (Creation: ' + (task.zone || NO_ZONE).name + '; Execution: ' + this.name + ')');
371
372      task._transitionTo(canceling, scheduled, running);
373
374      try {
375        this._zoneDelegate.cancelTask(this, task);
376      } catch (err) {
377        // if error occurs when cancelTask, transit the state to unknown
378        task._transitionTo(unknown, canceling);
379
380        this._zoneDelegate.handleError(this, err);
381
382        throw err;
383      }
384
385      this._updateTaskCount(task, -1);
386
387      task._transitionTo(notScheduled, canceling);
388
389      task.runCount = 0;
390      return task;
391    }
392
393    _updateTaskCount(task, count) {
394      const zoneDelegates = task._zoneDelegates;
395
396      if (count == -1) {
397        task._zoneDelegates = null;
398      }
399
400      for (let i = 0; i < zoneDelegates.length; i++) {
401        zoneDelegates[i]._updateTaskCount(task.type, count);
402      }
403    }
404
405  } // tslint:disable-next-line:require-internal-with-underscore
406
407
408  Zone.__symbol__ = __symbol__;
409  const DELEGATE_ZS = {
410    name: '',
411    onHasTask: (delegate, _, target, hasTaskState) => delegate.hasTask(target, hasTaskState),
412    onScheduleTask: (delegate, _, target, task) => delegate.scheduleTask(target, task),
413    onInvokeTask: (delegate, _, target, task, applyThis, applyArgs) => delegate.invokeTask(target, task, applyThis, applyArgs),
414    onCancelTask: (delegate, _, target, task) => delegate.cancelTask(target, task)
415  };
416
417  class _ZoneDelegate {
418    constructor(zone, parentDelegate, zoneSpec) {
419      this._taskCounts = {
420        'microTask': 0,
421        'macroTask': 0,
422        'eventTask': 0
423      };
424      this.zone = zone;
425      this._parentDelegate = parentDelegate;
426      this._forkZS = zoneSpec && (zoneSpec && zoneSpec.onFork ? zoneSpec : parentDelegate._forkZS);
427      this._forkDlgt = zoneSpec && (zoneSpec.onFork ? parentDelegate : parentDelegate._forkDlgt);
428      this._forkCurrZone = zoneSpec && (zoneSpec.onFork ? this.zone : parentDelegate._forkCurrZone);
429      this._interceptZS = zoneSpec && (zoneSpec.onIntercept ? zoneSpec : parentDelegate._interceptZS);
430      this._interceptDlgt = zoneSpec && (zoneSpec.onIntercept ? parentDelegate : parentDelegate._interceptDlgt);
431      this._interceptCurrZone = zoneSpec && (zoneSpec.onIntercept ? this.zone : parentDelegate._interceptCurrZone);
432      this._invokeZS = zoneSpec && (zoneSpec.onInvoke ? zoneSpec : parentDelegate._invokeZS);
433      this._invokeDlgt = zoneSpec && (zoneSpec.onInvoke ? parentDelegate : parentDelegate._invokeDlgt);
434      this._invokeCurrZone = zoneSpec && (zoneSpec.onInvoke ? this.zone : parentDelegate._invokeCurrZone);
435      this._handleErrorZS = zoneSpec && (zoneSpec.onHandleError ? zoneSpec : parentDelegate._handleErrorZS);
436      this._handleErrorDlgt = zoneSpec && (zoneSpec.onHandleError ? parentDelegate : parentDelegate._handleErrorDlgt);
437      this._handleErrorCurrZone = zoneSpec && (zoneSpec.onHandleError ? this.zone : parentDelegate._handleErrorCurrZone);
438      this._scheduleTaskZS = zoneSpec && (zoneSpec.onScheduleTask ? zoneSpec : parentDelegate._scheduleTaskZS);
439      this._scheduleTaskDlgt = zoneSpec && (zoneSpec.onScheduleTask ? parentDelegate : parentDelegate._scheduleTaskDlgt);
440      this._scheduleTaskCurrZone = zoneSpec && (zoneSpec.onScheduleTask ? this.zone : parentDelegate._scheduleTaskCurrZone);
441      this._invokeTaskZS = zoneSpec && (zoneSpec.onInvokeTask ? zoneSpec : parentDelegate._invokeTaskZS);
442      this._invokeTaskDlgt = zoneSpec && (zoneSpec.onInvokeTask ? parentDelegate : parentDelegate._invokeTaskDlgt);
443      this._invokeTaskCurrZone = zoneSpec && (zoneSpec.onInvokeTask ? this.zone : parentDelegate._invokeTaskCurrZone);
444      this._cancelTaskZS = zoneSpec && (zoneSpec.onCancelTask ? zoneSpec : parentDelegate._cancelTaskZS);
445      this._cancelTaskDlgt = zoneSpec && (zoneSpec.onCancelTask ? parentDelegate : parentDelegate._cancelTaskDlgt);
446      this._cancelTaskCurrZone = zoneSpec && (zoneSpec.onCancelTask ? this.zone : parentDelegate._cancelTaskCurrZone);
447      this._hasTaskZS = null;
448      this._hasTaskDlgt = null;
449      this._hasTaskDlgtOwner = null;
450      this._hasTaskCurrZone = null;
451      const zoneSpecHasTask = zoneSpec && zoneSpec.onHasTask;
452      const parentHasTask = parentDelegate && parentDelegate._hasTaskZS;
453
454      if (zoneSpecHasTask || parentHasTask) {
455        // If we need to report hasTask, than this ZS needs to do ref counting on tasks. In such
456        // a case all task related interceptors must go through this ZD. We can't short circuit it.
457        this._hasTaskZS = zoneSpecHasTask ? zoneSpec : DELEGATE_ZS;
458        this._hasTaskDlgt = parentDelegate;
459        this._hasTaskDlgtOwner = this;
460        this._hasTaskCurrZone = zone;
461
462        if (!zoneSpec.onScheduleTask) {
463          this._scheduleTaskZS = DELEGATE_ZS;
464          this._scheduleTaskDlgt = parentDelegate;
465          this._scheduleTaskCurrZone = this.zone;
466        }
467
468        if (!zoneSpec.onInvokeTask) {
469          this._invokeTaskZS = DELEGATE_ZS;
470          this._invokeTaskDlgt = parentDelegate;
471          this._invokeTaskCurrZone = this.zone;
472        }
473
474        if (!zoneSpec.onCancelTask) {
475          this._cancelTaskZS = DELEGATE_ZS;
476          this._cancelTaskDlgt = parentDelegate;
477          this._cancelTaskCurrZone = this.zone;
478        }
479      }
480    }
481
482    fork(targetZone, zoneSpec) {
483      return this._forkZS ? this._forkZS.onFork(this._forkDlgt, this.zone, targetZone, zoneSpec) : new Zone(targetZone, zoneSpec);
484    }
485
486    intercept(targetZone, callback, source) {
487      return this._interceptZS ? this._interceptZS.onIntercept(this._interceptDlgt, this._interceptCurrZone, targetZone, callback, source) : callback;
488    }
489
490    invoke(targetZone, callback, applyThis, applyArgs, source) {
491      return this._invokeZS ? this._invokeZS.onInvoke(this._invokeDlgt, this._invokeCurrZone, targetZone, callback, applyThis, applyArgs, source) : callback.apply(applyThis, applyArgs);
492    }
493
494    handleError(targetZone, error) {
495      return this._handleErrorZS ? this._handleErrorZS.onHandleError(this._handleErrorDlgt, this._handleErrorCurrZone, targetZone, error) : true;
496    }
497
498    scheduleTask(targetZone, task) {
499      let returnTask = task;
500
501      if (this._scheduleTaskZS) {
502        if (this._hasTaskZS) {
503          returnTask._zoneDelegates.push(this._hasTaskDlgtOwner);
504        } // clang-format off
505
506
507        returnTask = this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt, this._scheduleTaskCurrZone, targetZone, task); // clang-format on
508
509        if (!returnTask) returnTask = task;
510      } else {
511        if (task.scheduleFn) {
512          task.scheduleFn(task);
513        } else if (task.type == microTask) {
514          scheduleMicroTask(task);
515        } else {
516          throw new Error('Task is missing scheduleFn.');
517        }
518      }
519
520      return returnTask;
521    }
522
523    invokeTask(targetZone, task, applyThis, applyArgs) {
524      return this._invokeTaskZS ? this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt, this._invokeTaskCurrZone, targetZone, task, applyThis, applyArgs) : task.callback.apply(applyThis, applyArgs);
525    }
526
527    cancelTask(targetZone, task) {
528      let value;
529
530      if (this._cancelTaskZS) {
531        value = this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt, this._cancelTaskCurrZone, targetZone, task);
532      } else {
533        if (!task.cancelFn) {
534          throw Error('Task is not cancelable');
535        }
536
537        value = task.cancelFn(task);
538      }
539
540      return value;
541    }
542
543    hasTask(targetZone, isEmpty) {
544      // hasTask should not throw error so other ZoneDelegate
545      // can still trigger hasTask callback
546      try {
547        this._hasTaskZS && this._hasTaskZS.onHasTask(this._hasTaskDlgt, this._hasTaskCurrZone, targetZone, isEmpty);
548      } catch (err) {
549        this.handleError(targetZone, err);
550      }
551    } // tslint:disable-next-line:require-internal-with-underscore
552
553
554    _updateTaskCount(type, count) {
555      const counts = this._taskCounts;
556      const prev = counts[type];
557      const next = counts[type] = prev + count;
558
559      if (next < 0) {
560        throw new Error('More tasks executed then were scheduled.');
561      }
562
563      if (prev == 0 || next == 0) {
564        const isEmpty = {
565          microTask: counts['microTask'] > 0,
566          macroTask: counts['macroTask'] > 0,
567          eventTask: counts['eventTask'] > 0,
568          change: type
569        };
570        this.hasTask(this.zone, isEmpty);
571      }
572    }
573
574  }
575
576  class ZoneTask {
577    constructor(type, source, callback, options, scheduleFn, cancelFn) {
578      // tslint:disable-next-line:require-internal-with-underscore
579      this._zone = null;
580      this.runCount = 0; // tslint:disable-next-line:require-internal-with-underscore
581
582      this._zoneDelegates = null; // tslint:disable-next-line:require-internal-with-underscore
583
584      this._state = 'notScheduled';
585      this.type = type;
586      this.source = source;
587      this.data = options;
588      this.scheduleFn = scheduleFn;
589      this.cancelFn = cancelFn;
590
591      if (!callback) {
592        throw new Error('callback is not defined');
593      }
594
595      this.callback = callback;
596      const self = this; // TODO: @JiaLiPassion options should have interface
597
598      if (type === eventTask && options && options.useG) {
599        this.invoke = ZoneTask.invokeTask;
600      } else {
601        this.invoke = function () {
602          return ZoneTask.invokeTask.call(global, self, this, arguments);
603        };
604      }
605    }
606
607    static invokeTask(task, target, args) {
608      if (!task) {
609        task = this;
610      }
611
612      _numberOfNestedTaskFrames++;
613
614      try {
615        task.runCount++;
616        return task.zone.runTask(task, target, args);
617      } finally {
618        if (_numberOfNestedTaskFrames == 1) {
619          drainMicroTaskQueue();
620        }
621
622        _numberOfNestedTaskFrames--;
623      }
624    }
625
626    get zone() {
627      return this._zone;
628    }
629
630    get state() {
631      return this._state;
632    }
633
634    cancelScheduleRequest() {
635      this._transitionTo(notScheduled, scheduling);
636    } // tslint:disable-next-line:require-internal-with-underscore
637
638
639    _transitionTo(toState, fromState1, fromState2) {
640      if (this._state === fromState1 || this._state === fromState2) {
641        this._state = toState;
642
643        if (toState == notScheduled) {
644          this._zoneDelegates = null;
645        }
646      } else {
647        throw new Error(`${this.type} '${this.source}': can not transition to '${toState}', expecting state '${fromState1}'${fromState2 ? ' or \'' + fromState2 + '\'' : ''}, was '${this._state}'.`);
648      }
649    }
650
651    toString() {
652      if (this.data && typeof this.data.handleId !== 'undefined') {
653        return this.data.handleId.toString();
654      } else {
655        return Object.prototype.toString.call(this);
656      }
657    } // add toJSON method to prevent cyclic error when
658    // call JSON.stringify(zoneTask)
659
660
661    toJSON() {
662      return {
663        type: this.type,
664        state: this.state,
665        source: this.source,
666        zone: this.zone.name,
667        runCount: this.runCount
668      };
669    }
670
671  } //////////////////////////////////////////////////////
672  //////////////////////////////////////////////////////
673  ///  MICROTASK QUEUE
674  //////////////////////////////////////////////////////
675  //////////////////////////////////////////////////////
676
677
678  const symbolSetTimeout = __symbol__('setTimeout');
679
680  const symbolPromise = __symbol__('Promise');
681
682  const symbolThen = __symbol__('then');
683
684  let _microTaskQueue = [];
685  let _isDrainingMicrotaskQueue = false;
686  let nativeMicroTaskQueuePromise;
687
688  function nativeScheduleMicroTask(func) {
689    if (!nativeMicroTaskQueuePromise) {
690      if (global[symbolPromise]) {
691        nativeMicroTaskQueuePromise = global[symbolPromise].resolve(0);
692      }
693    }
694
695    if (nativeMicroTaskQueuePromise) {
696      let nativeThen = nativeMicroTaskQueuePromise[symbolThen];
697
698      if (!nativeThen) {
699        // native Promise is not patchable, we need to use `then` directly
700        // issue 1078
701        nativeThen = nativeMicroTaskQueuePromise['then'];
702      }
703
704      nativeThen.call(nativeMicroTaskQueuePromise, func);
705    } else {
706      global[symbolSetTimeout](func, 0);
707    }
708  }
709
710  function scheduleMicroTask(task) {
711    // if we are not running in any task, and there has not been anything scheduled
712    // we must bootstrap the initial task creation by manually scheduling the drain
713    if (_numberOfNestedTaskFrames === 0 && _microTaskQueue.length === 0) {
714      // We are not running in Task, so we need to kickstart the microtask queue.
715      nativeScheduleMicroTask(drainMicroTaskQueue);
716    }
717
718    task && _microTaskQueue.push(task);
719  }
720
721  function drainMicroTaskQueue() {
722    if (!_isDrainingMicrotaskQueue) {
723      _isDrainingMicrotaskQueue = true;
724
725      while (_microTaskQueue.length) {
726        const queue = _microTaskQueue;
727        _microTaskQueue = [];
728
729        for (let i = 0; i < queue.length; i++) {
730          const task = queue[i];
731
732          try {
733            task.zone.runTask(task, null, null);
734          } catch (error) {
735            _api.onUnhandledError(error);
736          }
737        }
738      }
739
740      _api.microtaskDrainDone();
741
742      _isDrainingMicrotaskQueue = false;
743    }
744  } //////////////////////////////////////////////////////
745  //////////////////////////////////////////////////////
746  ///  BOOTSTRAP
747  //////////////////////////////////////////////////////
748  //////////////////////////////////////////////////////
749
750
751  const NO_ZONE = {
752    name: 'NO ZONE'
753  };
754  const notScheduled = 'notScheduled',
755        scheduling = 'scheduling',
756        scheduled = 'scheduled',
757        running = 'running',
758        canceling = 'canceling',
759        unknown = 'unknown';
760  const microTask = 'microTask',
761        macroTask = 'macroTask',
762        eventTask = 'eventTask';
763  const patches = {};
764  const _api = {
765    symbol: __symbol__,
766    currentZoneFrame: () => _currentZoneFrame,
767    onUnhandledError: noop,
768    microtaskDrainDone: noop,
769    scheduleMicroTask: scheduleMicroTask,
770    showUncaughtError: () => !Zone[__symbol__('ignoreConsoleErrorUncaughtError')],
771    patchEventTarget: () => [],
772    patchOnProperties: noop,
773    patchMethod: () => noop,
774    bindArguments: () => [],
775    patchThen: () => noop,
776    patchMacroTask: () => noop,
777    patchEventPrototype: () => noop,
778    isIEOrEdge: () => false,
779    getGlobalObjects: () => undefined,
780    ObjectDefineProperty: () => noop,
781    ObjectGetOwnPropertyDescriptor: () => undefined,
782    ObjectCreate: () => undefined,
783    ArraySlice: () => [],
784    patchClass: () => noop,
785    wrapWithCurrentZone: () => noop,
786    filterProperties: () => [],
787    attachOriginToPatched: () => noop,
788    _redefineProperty: () => noop,
789    patchCallbacks: () => noop,
790    nativeScheduleMicroTask: nativeScheduleMicroTask
791  };
792  let _currentZoneFrame = {
793    parent: null,
794    zone: new Zone(null, null)
795  };
796  let _currentTask = null;
797  let _numberOfNestedTaskFrames = 0;
798
799  function noop() {}
800
801  performanceMeasure('Zone', 'Zone');
802  return global['Zone'] = Zone;
803})(typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global);
804/**
805 * @license
806 * Copyright Google LLC All Rights Reserved.
807 *
808 * Use of this source code is governed by an MIT-style license that can be
809 * found in the LICENSE file at https://angular.io/license
810 */
811
812/**
813 * Suppress closure compiler errors about unknown 'Zone' variable
814 * @fileoverview
815 * @suppress {undefinedVars,globalThis,missingRequire}
816 */
817/// <reference types="node"/>
818// issue #989, to reduce bundle size, use short name
819
820/** Object.getOwnPropertyDescriptor */
821
822
823const ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
824/** Object.defineProperty */
825
826const ObjectDefineProperty = Object.defineProperty;
827/** Object.getPrototypeOf */
828
829const ObjectGetPrototypeOf = Object.getPrototypeOf;
830/** Object.create */
831
832const ObjectCreate = Object.create;
833/** Array.prototype.slice */
834
835const ArraySlice = Array.prototype.slice;
836/** addEventListener string const */
837
838const ADD_EVENT_LISTENER_STR = 'addEventListener';
839/** removeEventListener string const */
840
841const REMOVE_EVENT_LISTENER_STR = 'removeEventListener';
842/** zoneSymbol addEventListener */
843
844const ZONE_SYMBOL_ADD_EVENT_LISTENER = Zone.__symbol__(ADD_EVENT_LISTENER_STR);
845/** zoneSymbol removeEventListener */
846
847
848const ZONE_SYMBOL_REMOVE_EVENT_LISTENER = Zone.__symbol__(REMOVE_EVENT_LISTENER_STR);
849/** true string const */
850
851
852const TRUE_STR = 'true';
853/** false string const */
854
855const FALSE_STR = 'false';
856/** Zone symbol prefix string const. */
857
858const ZONE_SYMBOL_PREFIX = Zone.__symbol__('');
859
860function wrapWithCurrentZone(callback, source) {
861  return Zone.current.wrap(callback, source);
862}
863
864function scheduleMacroTaskWithCurrentZone(source, callback, data, customSchedule, customCancel) {
865  return Zone.current.scheduleMacroTask(source, callback, data, customSchedule, customCancel);
866}
867
868const zoneSymbol = Zone.__symbol__;
869const isWindowExists = typeof window !== 'undefined';
870const internalWindow = isWindowExists ? window : undefined;
871
872const _global = isWindowExists && internalWindow || typeof self === 'object' && self || global;
873
874const REMOVE_ATTRIBUTE = 'removeAttribute';
875
876function bindArguments(args, source) {
877  for (let i = args.length - 1; i >= 0; i--) {
878    if (typeof args[i] === 'function') {
879      args[i] = wrapWithCurrentZone(args[i], source + '_' + i);
880    }
881  }
882
883  return args;
884}
885
886function patchPrototype(prototype, fnNames) {
887  const source = prototype.constructor['name'];
888
889  for (let i = 0; i < fnNames.length; i++) {
890    const name = fnNames[i];
891    const delegate = prototype[name];
892
893    if (delegate) {
894      const prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, name);
895
896      if (!isPropertyWritable(prototypeDesc)) {
897        continue;
898      }
899
900      prototype[name] = (delegate => {
901        const patched = function () {
902          return delegate.apply(this, bindArguments(arguments, source + '.' + name));
903        };
904
905        attachOriginToPatched(patched, delegate);
906        return patched;
907      })(delegate);
908    }
909  }
910}
911
912function isPropertyWritable(propertyDesc) {
913  if (!propertyDesc) {
914    return true;
915  }
916
917  if (propertyDesc.writable === false) {
918    return false;
919  }
920
921  return !(typeof propertyDesc.get === 'function' && typeof propertyDesc.set === 'undefined');
922}
923
924const isWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope; // Make sure to access `process` through `_global` so that WebPack does not accidentally browserify
925// this code.
926
927const isNode = !('nw' in _global) && typeof _global.process !== 'undefined' && {}.toString.call(_global.process) === '[object process]';
928const isBrowser = !isNode && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']); // we are in electron of nw, so we are both browser and nodejs
929// Make sure to access `process` through `_global` so that WebPack does not accidentally browserify
930// this code.
931
932const isMix = typeof _global.process !== 'undefined' && {}.toString.call(_global.process) === '[object process]' && !isWebWorker && !!(isWindowExists && internalWindow['HTMLElement']);
933const zoneSymbolEventNames$1 = {};
934
935const wrapFn = function (event) {
936  // https://github.com/angular/zone.js/issues/911, in IE, sometimes
937  // event will be undefined, so we need to use window.event
938  event = event || _global.event;
939
940  if (!event) {
941    return;
942  }
943
944  let eventNameSymbol = zoneSymbolEventNames$1[event.type];
945
946  if (!eventNameSymbol) {
947    eventNameSymbol = zoneSymbolEventNames$1[event.type] = zoneSymbol('ON_PROPERTY' + event.type);
948  }
949
950  const target = this || event.target || _global;
951  const listener = target[eventNameSymbol];
952  let result;
953
954  if (isBrowser && target === internalWindow && event.type === 'error') {
955    // window.onerror have different signature
956    // https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror#window.onerror
957    // and onerror callback will prevent default when callback return true
958    const errorEvent = event;
959    result = listener && listener.call(this, errorEvent.message, errorEvent.filename, errorEvent.lineno, errorEvent.colno, errorEvent.error);
960
961    if (result === true) {
962      event.preventDefault();
963    }
964  } else {
965    result = listener && listener.apply(this, arguments);
966
967    if (result != undefined && !result) {
968      event.preventDefault();
969    }
970  }
971
972  return result;
973};
974
975function patchProperty(obj, prop, prototype) {
976  let desc = ObjectGetOwnPropertyDescriptor(obj, prop);
977
978  if (!desc && prototype) {
979    // when patch window object, use prototype to check prop exist or not
vendor: 55,207 bytes, lines 980-2716
980    const prototypeDesc = ObjectGetOwnPropertyDescriptor(prototype, prop);
981
982    if (prototypeDesc) {
983      desc = {
984        enumerable: true,
985        configurable: true
986      };
987    }
988  } // if the descriptor not exists or is not configurable
989  // just return
990
991
992  if (!desc || !desc.configurable) {
993    return;
994  }
995
996  const onPropPatchedSymbol = zoneSymbol('on' + prop + 'patched');
997
998  if (obj.hasOwnProperty(onPropPatchedSymbol) && obj[onPropPatchedSymbol]) {
999    return;
1000  } // A property descriptor cannot have getter/setter and be writable
1001  // deleting the writable and value properties avoids this error:
1002  //
1003  // TypeError: property descriptors must not specify a value or be writable when a
1004  // getter or setter has been specified
1005
1006
1007  delete desc.writable;
1008  delete desc.value;
1009  const originalDescGet = desc.get;
1010  const originalDescSet = desc.set; // slice(2) cuz 'onclick' -> 'click', etc
1011
1012  const eventName = prop.slice(2);
1013  let eventNameSymbol = zoneSymbolEventNames$1[eventName];
1014
1015  if (!eventNameSymbol) {
1016    eventNameSymbol = zoneSymbolEventNames$1[eventName] = zoneSymbol('ON_PROPERTY' + eventName);
1017  }
1018
1019  desc.set = function (newValue) {
1020    // in some of windows's onproperty callback, this is undefined
1021    // so we need to check it
1022    let target = this;
1023
1024    if (!target && obj === _global) {
1025      target = _global;
1026    }
1027
1028    if (!target) {
1029      return;
1030    }
1031
1032    const previousValue = target[eventNameSymbol];
1033
1034    if (typeof previousValue === 'function') {
1035      target.removeEventListener(eventName, wrapFn);
1036    } // issue #978, when onload handler was added before loading zone.js
1037    // we should remove it with originalDescSet
1038
1039
1040    originalDescSet && originalDescSet.call(target, null);
1041    target[eventNameSymbol] = newValue;
1042
1043    if (typeof newValue === 'function') {
1044      target.addEventListener(eventName, wrapFn, false);
1045    }
1046  }; // The getter would return undefined for unassigned properties but the default value of an
1047  // unassigned property is null
1048
1049
1050  desc.get = function () {
1051    // in some of windows's onproperty callback, this is undefined
1052    // so we need to check it
1053    let target = this;
1054
1055    if (!target && obj === _global) {
1056      target = _global;
1057    }
1058
1059    if (!target) {
1060      return null;
1061    }
1062
1063    const listener = target[eventNameSymbol];
1064
1065    if (listener) {
1066      return listener;
1067    } else if (originalDescGet) {
1068      // result will be null when use inline event attribute,
1069      // such as <button onclick="func();">OK</button>
1070      // because the onclick function is internal raw uncompiled handler
1071      // the onclick will be evaluated when first time event was triggered or
1072      // the property is accessed, https://github.com/angular/zone.js/issues/525
1073      // so we should use original native get to retrieve the handler
1074      let value = originalDescGet.call(this);
1075
1076      if (value) {
1077        desc.set.call(this, value);
1078
1079        if (typeof target[REMOVE_ATTRIBUTE] === 'function') {
1080          target.removeAttribute(prop);
1081        }
1082
1083        return value;
1084      }
1085    }
1086
1087    return null;
1088  };
1089
1090  ObjectDefineProperty(obj, prop, desc);
1091  obj[onPropPatchedSymbol] = true;
1092}
1093
1094function patchOnProperties(obj, properties, prototype) {
1095  if (properties) {
1096    for (let i = 0; i < properties.length; i++) {
1097      patchProperty(obj, 'on' + properties[i], prototype);
1098    }
1099  } else {
1100    const onProperties = [];
1101
1102    for (const prop in obj) {
1103      if (prop.slice(0, 2) == 'on') {
1104        onProperties.push(prop);
1105      }
1106    }
1107
1108    for (let j = 0; j < onProperties.length; j++) {
1109      patchProperty(obj, onProperties[j], prototype);
1110    }
1111  }
1112}
1113
1114const originalInstanceKey = zoneSymbol('originalInstance'); // wrap some native API on `window`
1115
1116function patchClass(className) {
1117  const OriginalClass = _global[className];
1118  if (!OriginalClass) return; // keep original class in global
1119
1120  _global[zoneSymbol(className)] = OriginalClass;
1121
1122  _global[className] = function () {
1123    const a = bindArguments(arguments, className);
1124
1125    switch (a.length) {
1126      case 0:
1127        this[originalInstanceKey] = new OriginalClass();
1128        break;
1129
1130      case 1:
1131        this[originalInstanceKey] = new OriginalClass(a[0]);
1132        break;
1133
1134      case 2:
1135        this[originalInstanceKey] = new OriginalClass(a[0], a[1]);
1136        break;
1137
1138      case 3:
1139        this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2]);
1140        break;
1141
1142      case 4:
1143        this[originalInstanceKey] = new OriginalClass(a[0], a[1], a[2], a[3]);
1144        break;
1145
1146      default:
1147        throw new Error('Arg list too long.');
1148    }
1149  }; // attach original delegate to patched function
1150
1151
1152  attachOriginToPatched(_global[className], OriginalClass);
1153  const instance = new OriginalClass(function () {});
1154  let prop;
1155
1156  for (prop in instance) {
1157    // https://bugs.webkit.org/show_bug.cgi?id=44721
1158    if (className === 'XMLHttpRequest' && prop === 'responseBlob') continue;
1159
1160    (function (prop) {
1161      if (typeof instance[prop] === 'function') {
1162        _global[className].prototype[prop] = function () {
1163          return this[originalInstanceKey][prop].apply(this[originalInstanceKey], arguments);
1164        };
1165      } else {
1166        ObjectDefineProperty(_global[className].prototype, prop, {
1167          set: function (fn) {
1168            if (typeof fn === 'function') {
1169              this[originalInstanceKey][prop] = wrapWithCurrentZone(fn, className + '.' + prop); // keep callback in wrapped function so we can
1170              // use it in Function.prototype.toString to return
1171              // the native one.
1172
1173              attachOriginToPatched(this[originalInstanceKey][prop], fn);
1174            } else {
1175              this[originalInstanceKey][prop] = fn;
1176            }
1177          },
1178          get: function () {
1179            return this[originalInstanceKey][prop];
1180          }
1181        });
1182      }
1183    })(prop);
1184  }
1185
1186  for (prop in OriginalClass) {
1187    if (prop !== 'prototype' && OriginalClass.hasOwnProperty(prop)) {
1188      _global[className][prop] = OriginalClass[prop];
1189    }
1190  }
1191}
1192
1193function patchMethod(target, name, patchFn) {
1194  let proto = target;
1195
1196  while (proto && !proto.hasOwnProperty(name)) {
1197    proto = ObjectGetPrototypeOf(proto);
1198  }
1199
1200  if (!proto && target[name]) {
1201    // somehow we did not find it, but we can see it. This happens on IE for Window properties.
1202    proto = target;
1203  }
1204
1205  const delegateName = zoneSymbol(name);
1206  let delegate = null;
1207
1208  if (proto && (!(delegate = proto[delegateName]) || !proto.hasOwnProperty(delegateName))) {
1209    delegate = proto[delegateName] = proto[name]; // check whether proto[name] is writable
1210    // some property is readonly in safari, such as HtmlCanvasElement.prototype.toBlob
1211
1212    const desc = proto && ObjectGetOwnPropertyDescriptor(proto, name);
1213
1214    if (isPropertyWritable(desc)) {
1215      const patchDelegate = patchFn(delegate, delegateName, name);
1216
1217      proto[name] = function () {
1218        return patchDelegate(this, arguments);
1219      };
1220
1221      attachOriginToPatched(proto[name], delegate);
1222    }
1223  }
1224
1225  return delegate;
1226} // TODO: @JiaLiPassion, support cancel task later if necessary
1227
1228
1229function patchMacroTask(obj, funcName, metaCreator) {
1230  let setNative = null;
1231
1232  function scheduleTask(task) {
1233    const data = task.data;
1234
1235    data.args[data.cbIdx] = function () {
1236      task.invoke.apply(this, arguments);
1237    };
1238
1239    setNative.apply(data.target, data.args);
1240    return task;
1241  }
1242
1243  setNative = patchMethod(obj, funcName, delegate => function (self, args) {
1244    const meta = metaCreator(self, args);
1245
1246    if (meta.cbIdx >= 0 && typeof args[meta.cbIdx] === 'function') {
1247      return scheduleMacroTaskWithCurrentZone(meta.name, args[meta.cbIdx], meta, scheduleTask);
1248    } else {
1249      // cause an error by calling it directly.
1250      return delegate.apply(self, args);
1251    }
1252  });
1253}
1254
1255function attachOriginToPatched(patched, original) {
1256  patched[zoneSymbol('OriginalDelegate')] = original;
1257}
1258
1259let isDetectedIEOrEdge = false;
1260let ieOrEdge = false;
1261
1262function isIE() {
1263  try {
1264    const ua = internalWindow.navigator.userAgent;
1265
1266    if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1) {
1267      return true;
1268    }
1269  } catch (error) {}
1270
1271  return false;
1272}
1273
1274function isIEOrEdge() {
1275  if (isDetectedIEOrEdge) {
1276    return ieOrEdge;
1277  }
1278
1279  isDetectedIEOrEdge = true;
1280
1281  try {
1282    const ua = internalWindow.navigator.userAgent;
1283
1284    if (ua.indexOf('MSIE ') !== -1 || ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1) {
1285      ieOrEdge = true;
1286    }
1287  } catch (error) {}
1288
1289  return ieOrEdge;
1290}
1291/**
1292 * @license
1293 * Copyright Google LLC All Rights Reserved.
1294 *
1295 * Use of this source code is governed by an MIT-style license that can be
1296 * found in the LICENSE file at https://angular.io/license
1297 */
1298
1299
1300Zone.__load_patch('ZoneAwarePromise', (global, Zone, api) => {
1301  const ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
1302  const ObjectDefineProperty = Object.defineProperty;
1303
1304  function readableObjectToString(obj) {
1305    if (obj && obj.toString === Object.prototype.toString) {
1306      const className = obj.constructor && obj.constructor.name;
1307      return (className ? className : '') + ': ' + JSON.stringify(obj);
1308    }
1309
1310    return obj ? obj.toString() : Object.prototype.toString.call(obj);
1311  }
1312
1313  const __symbol__ = api.symbol;
1314  const _uncaughtPromiseErrors = [];
1315  const isDisableWrappingUncaughtPromiseRejection = global[__symbol__('DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION')] === true;
1316
1317  const symbolPromise = __symbol__('Promise');
1318
1319  const symbolThen = __symbol__('then');
1320
1321  const creationTrace = '__creationTrace__';
1322
1323  api.onUnhandledError = e => {
1324    if (api.showUncaughtError()) {
1325      const rejection = e && e.rejection;
1326
1327      if (rejection) {
1328        console.error('Unhandled Promise rejection:', rejection instanceof Error ? rejection.message : rejection, '; Zone:', e.zone.name, '; Task:', e.task && e.task.source, '; Value:', rejection, rejection instanceof Error ? rejection.stack : undefined);
1329      } else {
1330        console.error(e);
1331      }
1332    }
1333  };
1334
1335  api.microtaskDrainDone = () => {
1336    while (_uncaughtPromiseErrors.length) {
1337      const uncaughtPromiseError = _uncaughtPromiseErrors.shift();
1338
1339      try {
1340        uncaughtPromiseError.zone.runGuarded(() => {
1341          if (uncaughtPromiseError.throwOriginal) {
1342            throw uncaughtPromiseError.rejection;
1343          }
1344
1345          throw uncaughtPromiseError;
1346        });
1347      } catch (error) {
1348        handleUnhandledRejection(error);
1349      }
1350    }
1351  };
1352
1353  const UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__('unhandledPromiseRejectionHandler');
1354
1355  function handleUnhandledRejection(e) {
1356    api.onUnhandledError(e);
1357
1358    try {
1359      const handler = Zone[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL];
1360
1361      if (typeof handler === 'function') {
1362        handler.call(this, e);
1363      }
1364    } catch (err) {}
1365  }
1366
1367  function isThenable(value) {
1368    return value && value.then;
1369  }
1370
1371  function forwardResolution(value) {
1372    return value;
1373  }
1374
1375  function forwardRejection(rejection) {
1376    return ZoneAwarePromise.reject(rejection);
1377  }
1378
1379  const symbolState = __symbol__('state');
1380
1381  const symbolValue = __symbol__('value');
1382
1383  const symbolFinally = __symbol__('finally');
1384
1385  const symbolParentPromiseValue = __symbol__('parentPromiseValue');
1386
1387  const symbolParentPromiseState = __symbol__('parentPromiseState');
1388
1389  const source = 'Promise.then';
1390  const UNRESOLVED = null;
1391  const RESOLVED = true;
1392  const REJECTED = false;
1393  const REJECTED_NO_CATCH = 0;
1394
1395  function makeResolver(promise, state) {
1396    return v => {
1397      try {
1398        resolvePromise(promise, state, v);
1399      } catch (err) {
1400        resolvePromise(promise, false, err);
1401      } // Do not return value or you will break the Promise spec.
1402
1403    };
1404  }
1405
1406  const once = function () {
1407    let wasCalled = false;
1408    return function wrapper(wrappedFunction) {
1409      return function () {
1410        if (wasCalled) {
1411          return;
1412        }
1413
1414        wasCalled = true;
1415        wrappedFunction.apply(null, arguments);
1416      };
1417    };
1418  };
1419
1420  const TYPE_ERROR = 'Promise resolved with itself';
1421
1422  const CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace'); // Promise Resolution
1423
1424
1425  function resolvePromise(promise, state, value) {
1426    const onceWrapper = once();
1427
1428    if (promise === value) {
1429      throw new TypeError(TYPE_ERROR);
1430    }
1431
1432    if (promise[symbolState] === UNRESOLVED) {
1433      // should only get value.then once based on promise spec.
1434      let then = null;
1435
1436      try {
1437        if (typeof value === 'object' || typeof value === 'function') {
1438          then = value && value.then;
1439        }
1440      } catch (err) {
1441        onceWrapper(() => {
1442          resolvePromise(promise, false, err);
1443        })();
1444        return promise;
1445      } // if (value instanceof ZoneAwarePromise) {
1446
1447
1448      if (state !== REJECTED && value instanceof ZoneAwarePromise && value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) && value[symbolState] !== UNRESOLVED) {
1449        clearRejectedNoCatch(value);
1450        resolvePromise(promise, value[symbolState], value[symbolValue]);
1451      } else if (state !== REJECTED && typeof then === 'function') {
1452        try {
1453          then.call(value, onceWrapper(makeResolver(promise, state)), onceWrapper(makeResolver(promise, false)));
1454        } catch (err) {
1455          onceWrapper(() => {
1456            resolvePromise(promise, false, err);
1457          })();
1458        }
1459      } else {
1460        promise[symbolState] = state;
1461        const queue = promise[symbolValue];
1462        promise[symbolValue] = value;
1463
1464        if (promise[symbolFinally] === symbolFinally) {
1465          // the promise is generated by Promise.prototype.finally
1466          if (state === RESOLVED) {
1467            // the state is resolved, should ignore the value
1468            // and use parent promise value
1469            promise[symbolState] = promise[symbolParentPromiseState];
1470            promise[symbolValue] = promise[symbolParentPromiseValue];
1471          }
1472        } // record task information in value when error occurs, so we can
1473        // do some additional work such as render longStackTrace
1474
1475
1476        if (state === REJECTED && value instanceof Error) {
1477          // check if longStackTraceZone is here
1478          const trace = Zone.currentTask && Zone.currentTask.data && Zone.currentTask.data[creationTrace];
1479
1480          if (trace) {
1481            // only keep the long stack trace into error when in longStackTraceZone
1482            ObjectDefineProperty(value, CURRENT_TASK_TRACE_SYMBOL, {
1483              configurable: true,
1484              enumerable: false,
1485              writable: true,
1486              value: trace
1487            });
1488          }
1489        }
1490
1491        for (let i = 0; i < queue.length;) {
1492          scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);
1493        }
1494
1495        if (queue.length == 0 && state == REJECTED) {
1496          promise[symbolState] = REJECTED_NO_CATCH;
1497          let uncaughtPromiseError = value;
1498
1499          try {
1500            // Here we throws a new Error to print more readable error log
1501            // and if the value is not an error, zone.js builds an `Error`
1502            // Object here to attach the stack information.
1503            throw new Error('Uncaught (in promise): ' + readableObjectToString(value) + (value && value.stack ? '\n' + value.stack : ''));
1504          } catch (err) {
1505            uncaughtPromiseError = err;
1506          }
1507
1508          if (isDisableWrappingUncaughtPromiseRejection) {
1509            // If disable wrapping uncaught promise reject
1510            // use the value instead of wrapping it.
1511            uncaughtPromiseError.throwOriginal = true;
1512          }
1513
1514          uncaughtPromiseError.rejection = value;
1515          uncaughtPromiseError.promise = promise;
1516          uncaughtPromiseError.zone = Zone.current;
1517          uncaughtPromiseError.task = Zone.currentTask;
1518
1519          _uncaughtPromiseErrors.push(uncaughtPromiseError);
1520
1521          api.scheduleMicroTask(); // to make sure that it is running
1522        }
1523      }
1524    } // Resolving an already resolved promise is a noop.
1525
1526
1527    return promise;
1528  }
1529
1530  const REJECTION_HANDLED_HANDLER = __symbol__('rejectionHandledHandler');
1531
1532  function clearRejectedNoCatch(promise) {
1533    if (promise[symbolState] === REJECTED_NO_CATCH) {
1534      // if the promise is rejected no catch status
1535      // and queue.length > 0, means there is a error handler
1536      // here to handle the rejected promise, we should trigger
1537      // windows.rejectionhandled eventHandler or nodejs rejectionHandled
1538      // eventHandler
1539      try {
1540        const handler = Zone[REJECTION_HANDLED_HANDLER];
1541
1542        if (handler && typeof handler === 'function') {
1543          handler.call(this, {
1544            rejection: promise[symbolValue],
1545            promise: promise
1546          });
1547        }
1548      } catch (err) {}
1549
1550      promise[symbolState] = REJECTED;
1551
1552      for (let i = 0; i < _uncaughtPromiseErrors.length; i++) {
1553        if (promise === _uncaughtPromiseErrors[i].promise) {
1554          _uncaughtPromiseErrors.splice(i, 1);
1555        }
1556      }
1557    }
1558  }
1559
1560  function scheduleResolveOrReject(promise, zone, chainPromise, onFulfilled, onRejected) {
1561    clearRejectedNoCatch(promise);
1562    const promiseState = promise[symbolState];
1563    const delegate = promiseState ? typeof onFulfilled === 'function' ? onFulfilled : forwardResolution : typeof onRejected === 'function' ? onRejected : forwardRejection;
1564    zone.scheduleMicroTask(source, () => {
1565      try {
1566        const parentPromiseValue = promise[symbolValue];
1567        const isFinallyPromise = !!chainPromise && symbolFinally === chainPromise[symbolFinally];
1568
1569        if (isFinallyPromise) {
1570          // if the promise is generated from finally call, keep parent promise's state and value
1571          chainPromise[symbolParentPromiseValue] = parentPromiseValue;
1572          chainPromise[symbolParentPromiseState] = promiseState;
1573        } // should not pass value to finally callback
1574
1575
1576        const value = zone.run(delegate, undefined, isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution ? [] : [parentPromiseValue]);
1577        resolvePromise(chainPromise, true, value);
1578      } catch (error) {
1579        // if error occurs, should always return this error
1580        resolvePromise(chainPromise, false, error);
1581      }
1582    }, chainPromise);
1583  }
1584
1585  const ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }';
1586
1587  const noop = function () {};
1588
1589  const AggregateError = global.AggregateError;
1590
1591  class ZoneAwarePromise {
1592    static toString() {
1593      return ZONE_AWARE_PROMISE_TO_STRING;
1594    }
1595
1596    static resolve(value) {
1597      return resolvePromise(new this(null), RESOLVED, value);
1598    }
1599
1600    static reject(error) {
1601      return resolvePromise(new this(null), REJECTED, error);
1602    }
1603
1604    static any(values) {
1605      if (!values || typeof values[Symbol.iterator] !== 'function') {
1606        return Promise.reject(new AggregateError([], 'All promises were rejected'));
1607      }
1608
1609      const promises = [];
1610      let count = 0;
1611
1612      try {
1613        for (let v of values) {
1614          count++;
1615          promises.push(ZoneAwarePromise.resolve(v));
1616        }
1617      } catch (err) {
1618        return Promise.reject(new AggregateError([], 'All promises were rejected'));
1619      }
1620
1621      if (count === 0) {
1622        return Promise.reject(new AggregateError([], 'All promises were rejected'));
1623      }
1624
1625      let finished = false;
1626      const errors = [];
1627      return new ZoneAwarePromise((resolve, reject) => {
1628        for (let i = 0; i < promises.length; i++) {
1629          promises[i].then(v => {
1630            if (finished) {
1631              return;
1632            }
1633
1634            finished = true;
1635            resolve(v);
1636          }, err => {
1637            errors.push(err);
1638            count--;
1639
1640            if (count === 0) {
1641              finished = true;
1642              reject(new AggregateError(errors, 'All promises were rejected'));
1643            }
1644          });
1645        }
1646      });
1647    }
1648
1649    static race(values) {
1650      let resolve;
1651      let reject;
1652      let promise = new this((res, rej) => {
1653        resolve = res;
1654        reject = rej;
1655      });
1656
1657      function onResolve(value) {
1658        resolve(value);
1659      }
1660
1661      function onReject(error) {
1662        reject(error);
1663      }
1664
1665      for (let value of values) {
1666        if (!isThenable(value)) {
1667          value = this.resolve(value);
1668        }
1669
1670        value.then(onResolve, onReject);
1671      }
1672
1673      return promise;
1674    }
1675
1676    static all(values) {
1677      return ZoneAwarePromise.allWithCallback(values);
1678    }
1679
1680    static allSettled(values) {
1681      const P = this && this.prototype instanceof ZoneAwarePromise ? this : ZoneAwarePromise;
1682      return P.allWithCallback(values, {
1683        thenCallback: value => ({
1684          status: 'fulfilled',
1685          value
1686        }),
1687        errorCallback: err => ({
1688          status: 'rejected',
1689          reason: err
1690        })
1691      });
1692    }
1693
1694    static allWithCallback(values, callback) {
1695      let resolve;
1696      let reject;
1697      let promise = new this((res, rej) => {
1698        resolve = res;
1699        reject = rej;
1700      }); // Start at 2 to prevent prematurely resolving if .then is called immediately.
1701
1702      let unresolvedCount = 2;
1703      let valueIndex = 0;
1704      const resolvedValues = [];
1705
1706      for (let value of values) {
1707        if (!isThenable(value)) {
1708          value = this.resolve(value);
1709        }
1710
1711        const curValueIndex = valueIndex;
1712
1713        try {
1714          value.then(value => {
1715            resolvedValues[curValueIndex] = callback ? callback.thenCallback(value) : value;
1716            unresolvedCount--;
1717
1718            if (unresolvedCount === 0) {
1719              resolve(resolvedValues);
1720            }
1721          }, err => {
1722            if (!callback) {
1723              reject(err);
1724            } else {
1725              resolvedValues[curValueIndex] = callback.errorCallback(err);
1726              unresolvedCount--;
1727
1728              if (unresolvedCount === 0) {
1729                resolve(resolvedValues);
1730              }
1731            }
1732          });
1733        } catch (thenErr) {
1734          reject(thenErr);
1735        }
1736
1737        unresolvedCount++;
1738        valueIndex++;
1739      } // Make the unresolvedCount zero-based again.
1740
1741
1742      unresolvedCount -= 2;
1743
1744      if (unresolvedCount === 0) {
1745        resolve(resolvedValues);
1746      }
1747
1748      return promise;
1749    }
1750
1751    constructor(executor) {
1752      const promise = this;
1753
1754      if (!(promise instanceof ZoneAwarePromise)) {
1755        throw new Error('Must be an instanceof Promise.');
1756      }
1757
1758      promise[symbolState] = UNRESOLVED;
1759      promise[symbolValue] = []; // queue;
1760
1761      try {
1762        const onceWrapper = once();
1763        executor && executor(onceWrapper(makeResolver(promise, RESOLVED)), onceWrapper(makeResolver(promise, REJECTED)));
1764      } catch (error) {
1765        resolvePromise(promise, false, error);
1766      }
1767    }
1768
1769    get [Symbol.toStringTag]() {
1770      return 'Promise';
1771    }
1772
1773    get [Symbol.species]() {
1774      return ZoneAwarePromise;
1775    }
1776
1777    then(onFulfilled, onRejected) {
1778      var _a; // We must read `Symbol.species` safely because `this` may be anything. For instance, `this`
1779      // may be an object without a prototype (created through `Object.create(null)`); thus
1780      // `this.constructor` will be undefined. One of the use cases is SystemJS creating
1781      // prototype-less objects (modules) via `Object.create(null)`. The SystemJS creates an empty
1782      // object and copies promise properties into that object (within the `getOrCreateLoad`
1783      // function). The zone.js then checks if the resolved value has the `then` method and invokes
1784      // it with the `value` context. Otherwise, this will throw an error: `TypeError: Cannot read
1785      // properties of undefined (reading 'Symbol(Symbol.species)')`.
1786
1787
1788      let C = (_a = this.constructor) === null || _a === void 0 ? void 0 : _a[Symbol.species];
1789
1790      if (!C || typeof C !== 'function') {
1791        C = this.constructor || ZoneAwarePromise;
1792      }
1793
1794      const chainPromise = new C(noop);
1795      const zone = Zone.current;
1796
1797      if (this[symbolState] == UNRESOLVED) {
1798        this[symbolValue].push(zone, chainPromise, onFulfilled, onRejected);
1799      } else {
1800        scheduleResolveOrReject(this, zone, chainPromise, onFulfilled, onRejected);
1801      }
1802
1803      return chainPromise;
1804    }
1805
1806    catch(onRejected) {
1807      return this.then(null, onRejected);
1808    }
1809
1810    finally(onFinally) {
1811      var _a; // See comment on the call to `then` about why thee `Symbol.species` is safely accessed.
1812
1813
1814      let C = (_a = this.constructor) === null || _a === void 0 ? void 0 : _a[Symbol.species];
1815
1816      if (!C || typeof C !== 'function') {
1817        C = ZoneAwarePromise;
1818      }
1819
1820      const chainPromise = new C(noop);
1821      chainPromise[symbolFinally] = symbolFinally;
1822      const zone = Zone.current;
1823
1824      if (this[symbolState] == UNRESOLVED) {
1825        this[symbolValue].push(zone, chainPromise, onFinally, onFinally);
1826      } else {
1827        scheduleResolveOrReject(this, zone, chainPromise, onFinally, onFinally);
1828      }
1829
1830      return chainPromise;
1831    }
1832
1833  } // Protect against aggressive optimizers dropping seemingly unused properties.
1834  // E.g. Closure Compiler in advanced mode.
1835
1836
1837  ZoneAwarePromise['resolve'] = ZoneAwarePromise.resolve;
1838  ZoneAwarePromise['reject'] = ZoneAwarePromise.reject;
1839  ZoneAwarePromise['race'] = ZoneAwarePromise.race;
1840  ZoneAwarePromise['all'] = ZoneAwarePromise.all;
1841  const NativePromise = global[symbolPromise] = global['Promise'];
1842  global['Promise'] = ZoneAwarePromise;
1843
1844  const symbolThenPatched = __symbol__('thenPatched');
1845
1846  function patchThen(Ctor) {
1847    const proto = Ctor.prototype;
1848    const prop = ObjectGetOwnPropertyDescriptor(proto, 'then');
1849
1850    if (prop && (prop.writable === false || !prop.configurable)) {
1851      // check Ctor.prototype.then propertyDescriptor is writable or not
1852      // in meteor env, writable is false, we should ignore such case
1853      return;
1854    }
1855
1856    const originalThen = proto.then; // Keep a reference to the original method.
1857
1858    proto[symbolThen] = originalThen;
1859
1860    Ctor.prototype.then = function (onResolve, onReject) {
1861      const wrapped = new ZoneAwarePromise((resolve, reject) => {
1862        originalThen.call(this, resolve, reject);
1863      });
1864      return wrapped.then(onResolve, onReject);
1865    };
1866
1867    Ctor[symbolThenPatched] = true;
1868  }
1869
1870  api.patchThen = patchThen;
1871
1872  function zoneify(fn) {
1873    return function (self, args) {
1874      let resultPromise = fn.apply(self, args);
1875
1876      if (resultPromise instanceof ZoneAwarePromise) {
1877        return resultPromise;
1878      }
1879
1880      let ctor = resultPromise.constructor;
1881
1882      if (!ctor[symbolThenPatched]) {
1883        patchThen(ctor);
1884      }
1885
1886      return resultPromise;
1887    };
1888  }
1889
1890  if (NativePromise) {
1891    patchThen(NativePromise);
1892    patchMethod(global, 'fetch', delegate => zoneify(delegate));
1893  } // This is not part of public API, but it is useful for tests, so we expose it.
1894
1895
1896  Promise[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors;
1897  return ZoneAwarePromise;
1898});
1899/**
1900 * @license
1901 * Copyright Google LLC All Rights Reserved.
1902 *
1903 * Use of this source code is governed by an MIT-style license that can be
1904 * found in the LICENSE file at https://angular.io/license
1905 */
1906// override Function.prototype.toString to make zone.js patched function
1907// look like native function
1908
1909
1910Zone.__load_patch('toString', global => {
1911  // patch Func.prototype.toString to let them look like native
1912  const originalFunctionToString = Function.prototype.toString;
1913  const ORIGINAL_DELEGATE_SYMBOL = zoneSymbol('OriginalDelegate');
1914  const PROMISE_SYMBOL = zoneSymbol('Promise');
1915  const ERROR_SYMBOL = zoneSymbol('Error');
1916
1917  const newFunctionToString = function toString() {
1918    if (typeof this === 'function') {
1919      const originalDelegate = this[ORIGINAL_DELEGATE_SYMBOL];
1920
1921      if (originalDelegate) {
1922        if (typeof originalDelegate === 'function') {
1923          return originalFunctionToString.call(originalDelegate);
1924        } else {
1925          return Object.prototype.toString.call(originalDelegate);
1926        }
1927      }
1928
1929      if (this === Promise) {
1930        const nativePromise = global[PROMISE_SYMBOL];
1931
1932        if (nativePromise) {
1933          return originalFunctionToString.call(nativePromise);
1934        }
1935      }
1936
1937      if (this === Error) {
1938        const nativeError = global[ERROR_SYMBOL];
1939
1940        if (nativeError) {
1941          return originalFunctionToString.call(nativeError);
1942        }
1943      }
1944    }
1945
1946    return originalFunctionToString.call(this);
1947  };
1948
1949  newFunctionToString[ORIGINAL_DELEGATE_SYMBOL] = originalFunctionToString;
1950  Function.prototype.toString = newFunctionToString; // patch Object.prototype.toString to let them look like native
1951
1952  const originalObjectToString = Object.prototype.toString;
1953  const PROMISE_OBJECT_TO_STRING = '[object Promise]';
1954
1955  Object.prototype.toString = function () {
1956    if (typeof Promise === 'function' && this instanceof Promise) {
1957      return PROMISE_OBJECT_TO_STRING;
1958    }
1959
1960    return originalObjectToString.call(this);
1961  };
1962});
1963/**
1964 * @license
1965 * Copyright Google LLC All Rights Reserved.
1966 *
1967 * Use of this source code is governed by an MIT-style license that can be
1968 * found in the LICENSE file at https://angular.io/license
1969 */
1970
1971
1972let passiveSupported = false;
1973
1974if (typeof window !== 'undefined') {
1975  try {
1976    const options = Object.defineProperty({}, 'passive', {
1977      get: function () {
1978        passiveSupported = true;
1979      }
1980    }); // Note: We pass the `options` object as the event handler too. This is not compatible with the
1981    // signature of `addEventListener` or `removeEventListener` but enables us to remove the handler
1982    // without an actual handler.
1983
1984    window.addEventListener('test', options, options);
1985    window.removeEventListener('test', options, options);
1986  } catch (err) {
1987    passiveSupported = false;
1988  }
1989} // an identifier to tell ZoneTask do not create a new invoke closure
1990
1991
1992const OPTIMIZED_ZONE_EVENT_TASK_DATA = {
1993  useG: true
1994};
1995const zoneSymbolEventNames = {};
1996const globalSources = {};
1997const EVENT_NAME_SYMBOL_REGX = new RegExp('^' + ZONE_SYMBOL_PREFIX + '(\\w+)(true|false)$');
1998const IMMEDIATE_PROPAGATION_SYMBOL = zoneSymbol('propagationStopped');
1999
2000function prepareEventNames(eventName, eventNameToString) {
2001  const falseEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + FALSE_STR;
2002  const trueEventName = (eventNameToString ? eventNameToString(eventName) : eventName) + TRUE_STR;
2003  const symbol = ZONE_SYMBOL_PREFIX + falseEventName;
2004  const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;
2005  zoneSymbolEventNames[eventName] = {};
2006  zoneSymbolEventNames[eventName][FALSE_STR] = symbol;
2007  zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture;
2008}
2009
2010function patchEventTarget(_global, api, apis, patchOptions) {
2011  const ADD_EVENT_LISTENER = patchOptions && patchOptions.add || ADD_EVENT_LISTENER_STR;
2012  const REMOVE_EVENT_LISTENER = patchOptions && patchOptions.rm || REMOVE_EVENT_LISTENER_STR;
2013  const LISTENERS_EVENT_LISTENER = patchOptions && patchOptions.listeners || 'eventListeners';
2014  const REMOVE_ALL_LISTENERS_EVENT_LISTENER = patchOptions && patchOptions.rmAll || 'removeAllListeners';
2015  const zoneSymbolAddEventListener = zoneSymbol(ADD_EVENT_LISTENER);
2016  const ADD_EVENT_LISTENER_SOURCE = '.' + ADD_EVENT_LISTENER + ':';
2017  const PREPEND_EVENT_LISTENER = 'prependListener';
2018  const PREPEND_EVENT_LISTENER_SOURCE = '.' + PREPEND_EVENT_LISTENER + ':';
2019
2020  const invokeTask = function (task, target, event) {
2021    // for better performance, check isRemoved which is set
2022    // by removeEventListener
2023    if (task.isRemoved) {
2024      return;
2025    }
2026
2027    const delegate = task.callback;
2028
2029    if (typeof delegate === 'object' && delegate.handleEvent) {
2030      // create the bind version of handleEvent when invoke
2031      task.callback = event => delegate.handleEvent(event);
2032
2033      task.originalDelegate = delegate;
2034    } // invoke static task.invoke
2035    // need to try/catch error here, otherwise, the error in one event listener
2036    // will break the executions of the other event listeners. Also error will
2037    // not remove the event listener when `once` options is true.
2038
2039
2040    let error;
2041
2042    try {
2043      task.invoke(task, target, [event]);
2044    } catch (err) {
2045      error = err;
2046    }
2047
2048    const options = task.options;
2049
2050    if (options && typeof options === 'object' && options.once) {
2051      // if options.once is true, after invoke once remove listener here
2052      // only browser need to do this, nodejs eventEmitter will cal removeListener
2053      // inside EventEmitter.once
2054      const delegate = task.originalDelegate ? task.originalDelegate : task.callback;
2055      target[REMOVE_EVENT_LISTENER].call(target, event.type, delegate, options);
2056    }
2057
2058    return error;
2059  };
2060
2061  function globalCallback(context, event, isCapture) {
2062    // https://github.com/angular/zone.js/issues/911, in IE, sometimes
2063    // event will be undefined, so we need to use window.event
2064    event = event || _global.event;
2065
2066    if (!event) {
2067      return;
2068    } // event.target is needed for Samsung TV and SourceBuffer
2069    // || global is needed https://github.com/angular/zone.js/issues/190
2070
2071
2072    const target = context || event.target || _global;
2073    const tasks = target[zoneSymbolEventNames[event.type][isCapture ? TRUE_STR : FALSE_STR]];
2074
2075    if (tasks) {
2076      const errors = []; // invoke all tasks which attached to current target with given event.type and capture = false
2077      // for performance concern, if task.length === 1, just invoke
2078
2079      if (tasks.length === 1) {
2080        const err = invokeTask(tasks[0], target, event);
2081        err && errors.push(err);
2082      } else {
2083        // https://github.com/angular/zone.js/issues/836
2084        // copy the tasks array before invoke, to avoid
2085        // the callback will remove itself or other listener
2086        const copyTasks = tasks.slice();
2087
2088        for (let i = 0; i < copyTasks.length; i++) {
2089          if (event && event[IMMEDIATE_PROPAGATION_SYMBOL] === true) {
2090            break;
2091          }
2092
2093          const err = invokeTask(copyTasks[i], target, event);
2094          err && errors.push(err);
2095        }
2096      } // Since there is only one error, we don't need to schedule microTask
2097      // to throw the error.
2098
2099
2100      if (errors.length === 1) {
2101        throw errors[0];
2102      } else {
2103        for (let i = 0; i < errors.length; i++) {
2104          const err = errors[i];
2105          api.nativeScheduleMicroTask(() => {
2106            throw err;
2107          });
2108        }
2109      }
2110    }
2111  } // global shared zoneAwareCallback to handle all event callback with capture = false
2112
2113
2114  const globalZoneAwareCallback = function (event) {
2115    return globalCallback(this, event, false);
2116  }; // global shared zoneAwareCallback to handle all event callback with capture = true
2117
2118
2119  const globalZoneAwareCaptureCallback = function (event) {
2120    return globalCallback(this, event, true);
2121  };
2122
2123  function patchEventTargetMethods(obj, patchOptions) {
2124    if (!obj) {
2125      return false;
2126    }
2127
2128    let useGlobalCallback = true;
2129
2130    if (patchOptions && patchOptions.useG !== undefined) {
2131      useGlobalCallback = patchOptions.useG;
2132    }
2133
2134    const validateHandler = patchOptions && patchOptions.vh;
2135    let checkDuplicate = true;
2136
2137    if (patchOptions && patchOptions.chkDup !== undefined) {
2138      checkDuplicate = patchOptions.chkDup;
2139    }
2140
2141    let returnTarget = false;
2142
2143    if (patchOptions && patchOptions.rt !== undefined) {
2144      returnTarget = patchOptions.rt;
2145    }
2146
2147    let proto = obj;
2148
2149    while (proto && !proto.hasOwnProperty(ADD_EVENT_LISTENER)) {
2150      proto = ObjectGetPrototypeOf(proto);
2151    }
2152
2153    if (!proto && obj[ADD_EVENT_LISTENER]) {
2154      // somehow we did not find it, but we can see it. This happens on IE for Window properties.
2155      proto = obj;
2156    }
2157
2158    if (!proto) {
2159      return false;
2160    }
2161
2162    if (proto[zoneSymbolAddEventListener]) {
2163      return false;
2164    }
2165
2166    const eventNameToString = patchOptions && patchOptions.eventNameToString; // a shared global taskData to pass data for scheduleEventTask
2167    // so we do not need to create a new object just for pass some data
2168
2169    const taskData = {};
2170    const nativeAddEventListener = proto[zoneSymbolAddEventListener] = proto[ADD_EVENT_LISTENER];
2171    const nativeRemoveEventListener = proto[zoneSymbol(REMOVE_EVENT_LISTENER)] = proto[REMOVE_EVENT_LISTENER];
2172    const nativeListeners = proto[zoneSymbol(LISTENERS_EVENT_LISTENER)] = proto[LISTENERS_EVENT_LISTENER];
2173    const nativeRemoveAllListeners = proto[zoneSymbol(REMOVE_ALL_LISTENERS_EVENT_LISTENER)] = proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER];
2174    let nativePrependEventListener;
2175
2176    if (patchOptions && patchOptions.prepend) {
2177      nativePrependEventListener = proto[zoneSymbol(patchOptions.prepend)] = proto[patchOptions.prepend];
2178    }
2179    /**
2180     * This util function will build an option object with passive option
2181     * to handle all possible input from the user.
2182     */
2183
2184
2185    function buildEventListenerOptions(options, passive) {
2186      if (!passiveSupported && typeof options === 'object' && options) {
2187        // doesn't support passive but user want to pass an object as options.
2188        // this will not work on some old browser, so we just pass a boolean
2189        // as useCapture parameter
2190        return !!options.capture;
2191      }
2192
2193      if (!passiveSupported || !passive) {
2194        return options;
2195      }
2196
2197      if (typeof options === 'boolean') {
2198        return {
2199          capture: options,
2200          passive: true
2201        };
2202      }
2203
2204      if (!options) {
2205        return {
2206          passive: true
2207        };
2208      }
2209
2210      if (typeof options === 'object' && options.passive !== false) {
2211        return Object.assign(Object.assign({}, options), {
2212          passive: true
2213        });
2214      }
2215
2216      return options;
2217    }
2218
2219    const customScheduleGlobal = function (task) {
2220      // if there is already a task for the eventName + capture,
2221      // just return, because we use the shared globalZoneAwareCallback here.
2222      if (taskData.isExisting) {
2223        return;
2224      }
2225
2226      return nativeAddEventListener.call(taskData.target, taskData.eventName, taskData.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, taskData.options);
2227    };
2228
2229    const customCancelGlobal = function (task) {
2230      // if task is not marked as isRemoved, this call is directly
2231      // from Zone.prototype.cancelTask, we should remove the task
2232      // from tasksList of target first
2233      if (!task.isRemoved) {
2234        const symbolEventNames = zoneSymbolEventNames[task.eventName];
2235        let symbolEventName;
2236
2237        if (symbolEventNames) {
2238          symbolEventName = symbolEventNames[task.capture ? TRUE_STR : FALSE_STR];
2239        }
2240
2241        const existingTasks = symbolEventName && task.target[symbolEventName];
2242
2243        if (existingTasks) {
2244          for (let i = 0; i < existingTasks.length; i++) {
2245            const existingTask = existingTasks[i];
2246
2247            if (existingTask === task) {
2248              existingTasks.splice(i, 1); // set isRemoved to data for faster invokeTask check
2249
2250              task.isRemoved = true;
2251
2252              if (existingTasks.length === 0) {
2253                // all tasks for the eventName + capture have gone,
2254                // remove globalZoneAwareCallback and remove the task cache from target
2255                task.allRemoved = true;
2256                task.target[symbolEventName] = null;
2257              }
2258
2259              break;
2260            }
2261          }
2262        }
2263      } // if all tasks for the eventName + capture have gone,
2264      // we will really remove the global event callback,
2265      // if not, return
2266
2267
2268      if (!task.allRemoved) {
2269        return;
2270      }
2271
2272      return nativeRemoveEventListener.call(task.target, task.eventName, task.capture ? globalZoneAwareCaptureCallback : globalZoneAwareCallback, task.options);
2273    };
2274
2275    const customScheduleNonGlobal = function (task) {
2276      return nativeAddEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options);
2277    };
2278
2279    const customSchedulePrepend = function (task) {
2280      return nativePrependEventListener.call(taskData.target, taskData.eventName, task.invoke, taskData.options);
2281    };
2282
2283    const customCancelNonGlobal = function (task) {
2284      return nativeRemoveEventListener.call(task.target, task.eventName, task.invoke, task.options);
2285    };
2286
2287    const customSchedule = useGlobalCallback ? customScheduleGlobal : customScheduleNonGlobal;
2288    const customCancel = useGlobalCallback ? customCancelGlobal : customCancelNonGlobal;
2289
2290    const compareTaskCallbackVsDelegate = function (task, delegate) {
2291      const typeOfDelegate = typeof delegate;
2292      return typeOfDelegate === 'function' && task.callback === delegate || typeOfDelegate === 'object' && task.originalDelegate === delegate;
2293    };
2294
2295    const compare = patchOptions && patchOptions.diff ? patchOptions.diff : compareTaskCallbackVsDelegate;
2296    const unpatchedEvents = Zone[zoneSymbol('UNPATCHED_EVENTS')];
2297
2298    const passiveEvents = _global[zoneSymbol('PASSIVE_EVENTS')];
2299
2300    const makeAddListener = function (nativeListener, addSource, customScheduleFn, customCancelFn, returnTarget = false, prepend = false) {
2301      return function () {
2302        const target = this || _global;
2303        let eventName = arguments[0];
2304
2305        if (patchOptions && patchOptions.transferEventName) {
2306          eventName = patchOptions.transferEventName(eventName);
2307        }
2308
2309        let delegate = arguments[1];
2310
2311        if (!delegate) {
2312          return nativeListener.apply(this, arguments);
2313        }
2314
2315        if (isNode && eventName === 'uncaughtException') {
2316          // don't patch uncaughtException of nodejs to prevent endless loop
2317          return nativeListener.apply(this, arguments);
2318        } // don't create the bind delegate function for handleEvent
2319        // case here to improve addEventListener performance
2320        // we will create the bind delegate when invoke
2321
2322
2323        let isHandleEvent = false;
2324
2325        if (typeof delegate !== 'function') {
2326          if (!delegate.handleEvent) {
2327            return nativeListener.apply(this, arguments);
2328          }
2329
2330          isHandleEvent = true;
2331        }
2332
2333        if (validateHandler && !validateHandler(nativeListener, delegate, target, arguments)) {
2334          return;
2335        }
2336
2337        const passive = passiveSupported && !!passiveEvents && passiveEvents.indexOf(eventName) !== -1;
2338        const options = buildEventListenerOptions(arguments[2], passive);
2339
2340        if (unpatchedEvents) {
2341          // check unpatched list
2342          for (let i = 0; i < unpatchedEvents.length; i++) {
2343            if (eventName === unpatchedEvents[i]) {
2344              if (passive) {
2345                return nativeListener.call(target, eventName, delegate, options);
2346              } else {
2347                return nativeListener.apply(this, arguments);
2348              }
2349            }
2350          }
2351        }
2352
2353        const capture = !options ? false : typeof options === 'boolean' ? true : options.capture;
2354        const once = options && typeof options === 'object' ? options.once : false;
2355        const zone = Zone.current;
2356        let symbolEventNames = zoneSymbolEventNames[eventName];
2357
2358        if (!symbolEventNames) {
2359          prepareEventNames(eventName, eventNameToString);
2360          symbolEventNames = zoneSymbolEventNames[eventName];
2361        }
2362
2363        const symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR];
2364        let existingTasks = target[symbolEventName];
2365        let isExisting = false;
2366
2367        if (existingTasks) {
2368          // already have task registered
2369          isExisting = true;
2370
2371          if (checkDuplicate) {
2372            for (let i = 0; i < existingTasks.length; i++) {
2373              if (compare(existingTasks[i], delegate)) {
2374                // same callback, same capture, same event name, just return
2375                return;
2376              }
2377            }
2378          }
2379        } else {
2380          existingTasks = target[symbolEventName] = [];
2381        }
2382
2383        let source;
2384        const constructorName = target.constructor['name'];
2385        const targetSource = globalSources[constructorName];
2386
2387        if (targetSource) {
2388          source = targetSource[eventName];
2389        }
2390
2391        if (!source) {
2392          source = constructorName + addSource + (eventNameToString ? eventNameToString(eventName) : eventName);
2393        } // do not create a new object as task.data to pass those things
2394        // just use the global shared one
2395
2396
2397        taskData.options = options;
2398
2399        if (once) {
2400          // if addEventListener with once options, we don't pass it to
2401          // native addEventListener, instead we keep the once setting
2402          // and handle ourselves.
2403          taskData.options.once = false;
2404        }
2405
2406        taskData.target = target;
2407        taskData.capture = capture;
2408        taskData.eventName = eventName;
2409        taskData.isExisting = isExisting;
2410        const data = useGlobalCallback ? OPTIMIZED_ZONE_EVENT_TASK_DATA : undefined; // keep taskData into data to allow onScheduleEventTask to access the task information
2411
2412        if (data) {
2413          data.taskData = taskData;
2414        }
2415
2416        const task = zone.scheduleEventTask(source, delegate, data, customScheduleFn, customCancelFn); // should clear taskData.target to avoid memory leak
2417        // issue, https://github.com/angular/angular/issues/20442
2418
2419        taskData.target = null; // need to clear up taskData because it is a global object
2420
2421        if (data) {
2422          data.taskData = null;
2423        } // have to save those information to task in case
2424        // application may call task.zone.cancelTask() directly
2425
2426
2427        if (once) {
2428          options.once = true;
2429        }
2430
2431        if (!(!passiveSupported && typeof task.options === 'boolean')) {
2432          // if not support passive, and we pass an option object
2433          // to addEventListener, we should save the options to task
2434          task.options = options;
2435        }
2436
2437        task.target = target;
2438        task.capture = capture;
2439        task.eventName = eventName;
2440
2441        if (isHandleEvent) {
2442          // save original delegate for compare to check duplicate
2443          task.originalDelegate = delegate;
2444        }
2445
2446        if (!prepend) {
2447          existingTasks.push(task);
2448        } else {
2449          existingTasks.unshift(task);
2450        }
2451
2452        if (returnTarget) {
2453          return target;
2454        }
2455      };
2456    };
2457
2458    proto[ADD_EVENT_LISTENER] = makeAddListener(nativeAddEventListener, ADD_EVENT_LISTENER_SOURCE, customSchedule, customCancel, returnTarget);
2459
2460    if (nativePrependEventListener) {
2461      proto[PREPEND_EVENT_LISTENER] = makeAddListener(nativePrependEventListener, PREPEND_EVENT_LISTENER_SOURCE, customSchedulePrepend, customCancel, returnTarget, true);
2462    }
2463
2464    proto[REMOVE_EVENT_LISTENER] = function () {
2465      const target = this || _global;
2466      let eventName = arguments[0];
2467
2468      if (patchOptions && patchOptions.transferEventName) {
2469        eventName = patchOptions.transferEventName(eventName);
2470      }
2471
2472      const options = arguments[2];
2473      const capture = !options ? false : typeof options === 'boolean' ? true : options.capture;
2474      const delegate = arguments[1];
2475
2476      if (!delegate) {
2477        return nativeRemoveEventListener.apply(this, arguments);
2478      }
2479
2480      if (validateHandler && !validateHandler(nativeRemoveEventListener, delegate, target, arguments)) {
2481        return;
2482      }
2483
2484      const symbolEventNames = zoneSymbolEventNames[eventName];
2485      let symbolEventName;
2486
2487      if (symbolEventNames) {
2488        symbolEventName = symbolEventNames[capture ? TRUE_STR : FALSE_STR];
2489      }
2490
2491      const existingTasks = symbolEventName && target[symbolEventName];
2492
2493      if (existingTasks) {
2494        for (let i = 0; i < existingTasks.length; i++) {
2495          const existingTask = existingTasks[i];
2496
2497          if (compare(existingTask, delegate)) {
2498            existingTasks.splice(i, 1); // set isRemoved to data for faster invokeTask check
2499
2500            existingTask.isRemoved = true;
2501
2502            if (existingTasks.length === 0) {
2503              // all tasks for the eventName + capture have gone,
2504              // remove globalZoneAwareCallback and remove the task cache from target
2505              existingTask.allRemoved = true;
2506              target[symbolEventName] = null; // in the target, we have an event listener which is added by on_property
2507              // such as target.onclick = function() {}, so we need to clear this internal
2508              // property too if all delegates all removed
2509
2510              if (typeof eventName === 'string') {
2511                const onPropertySymbol = ZONE_SYMBOL_PREFIX + 'ON_PROPERTY' + eventName;
2512                target[onPropertySymbol] = null;
2513              }
2514            }
2515
2516            existingTask.zone.cancelTask(existingTask);
2517
2518            if (returnTarget) {
2519              return target;
2520            }
2521
2522            return;
2523          }
2524        }
2525      } // issue 930, didn't find the event name or callback
2526      // from zone kept existingTasks, the callback maybe
2527      // added outside of zone, we need to call native removeEventListener
2528      // to try to remove it.
2529
2530
2531      return nativeRemoveEventListener.apply(this, arguments);
2532    };
2533
2534    proto[LISTENERS_EVENT_LISTENER] = function () {
2535      const target = this || _global;
2536      let eventName = arguments[0];
2537
2538      if (patchOptions && patchOptions.transferEventName) {
2539        eventName = patchOptions.transferEventName(eventName);
2540      }
2541
2542      const listeners = [];
2543      const tasks = findEventTasks(target, eventNameToString ? eventNameToString(eventName) : eventName);
2544
2545      for (let i = 0; i < tasks.length; i++) {
2546        const task = tasks[i];
2547        let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
2548        listeners.push(delegate);
2549      }
2550
2551      return listeners;
2552    };
2553
2554    proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER] = function () {
2555      const target = this || _global;
2556      let eventName = arguments[0];
2557
2558      if (!eventName) {
2559        const keys = Object.keys(target);
2560
2561        for (let i = 0; i < keys.length; i++) {
2562          const prop = keys[i];
2563          const match = EVENT_NAME_SYMBOL_REGX.exec(prop);
2564          let evtName = match && match[1]; // in nodejs EventEmitter, removeListener event is
2565          // used for monitoring the removeListener call,
2566          // so just keep removeListener eventListener until
2567          // all other eventListeners are removed
2568
2569          if (evtName && evtName !== 'removeListener') {
2570            this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, evtName);
2571          }
2572        } // remove removeListener listener finally
2573
2574
2575        this[REMOVE_ALL_LISTENERS_EVENT_LISTENER].call(this, 'removeListener');
2576      } else {
2577        if (patchOptions && patchOptions.transferEventName) {
2578          eventName = patchOptions.transferEventName(eventName);
2579        }
2580
2581        const symbolEventNames = zoneSymbolEventNames[eventName];
2582
2583        if (symbolEventNames) {
2584          const symbolEventName = symbolEventNames[FALSE_STR];
2585          const symbolCaptureEventName = symbolEventNames[TRUE_STR];
2586          const tasks = target[symbolEventName];
2587          const captureTasks = target[symbolCaptureEventName];
2588
2589          if (tasks) {
2590            const removeTasks = tasks.slice();
2591
2592            for (let i = 0; i < removeTasks.length; i++) {
2593              const task = removeTasks[i];
2594              let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
2595              this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);
2596            }
2597          }
2598
2599          if (captureTasks) {
2600            const removeTasks = captureTasks.slice();
2601
2602            for (let i = 0; i < removeTasks.length; i++) {
2603              const task = removeTasks[i];
2604              let delegate = task.originalDelegate ? task.originalDelegate : task.callback;
2605              this[REMOVE_EVENT_LISTENER].call(this, eventName, delegate, task.options);
2606            }
2607          }
2608        }
2609      }
2610
2611      if (returnTarget) {
2612        return this;
2613      }
2614    }; // for native toString patch
2615
2616
2617    attachOriginToPatched(proto[ADD_EVENT_LISTENER], nativeAddEventListener);
2618    attachOriginToPatched(proto[REMOVE_EVENT_LISTENER], nativeRemoveEventListener);
2619
2620    if (nativeRemoveAllListeners) {
2621      attachOriginToPatched(proto[REMOVE_ALL_LISTENERS_EVENT_LISTENER], nativeRemoveAllListeners);
2622    }
2623
2624    if (nativeListeners) {
2625      attachOriginToPatched(proto[LISTENERS_EVENT_LISTENER], nativeListeners);
2626    }
2627
2628    return true;
2629  }
2630
2631  let results = [];
2632
2633  for (let i = 0; i < apis.length; i++) {
2634    results[i] = patchEventTargetMethods(apis[i], patchOptions);
2635  }
2636
2637  return results;
2638}
2639
2640function findEventTasks(target, eventName) {
2641  if (!eventName) {
2642    const foundTasks = [];
2643
2644    for (let prop in target) {
2645      const match = EVENT_NAME_SYMBOL_REGX.exec(prop);
2646      let evtName = match && match[1];
2647
2648      if (evtName && (!eventName || evtName === eventName)) {
2649        const tasks = target[prop];
2650
2651        if (tasks) {
2652          for (let i = 0; i < tasks.length; i++) {
2653            foundTasks.push(tasks[i]);
2654          }
2655        }
2656      }
2657    }
2658
2659    return foundTasks;
2660  }
2661
2662  let symbolEventName = zoneSymbolEventNames[eventName];
2663
2664  if (!symbolEventName) {
2665    prepareEventNames(eventName);
2666    symbolEventName = zoneSymbolEventNames[eventName];
2667  }
2668
2669  const captureFalseTasks = target[symbolEventName[FALSE_STR]];
2670  const captureTrueTasks = target[symbolEventName[TRUE_STR]];
2671
2672  if (!captureFalseTasks) {
2673    return captureTrueTasks ? captureTrueTasks.slice() : [];
2674  } else {
2675    return captureTrueTasks ? captureFalseTasks.concat(captureTrueTasks) : captureFalseTasks.slice();
2676  }
2677}
2678
2679function patchEventPrototype(global, api) {
2680  const Event = global['Event'];
2681
2682  if (Event && Event.prototype) {
2683    api.patchMethod(Event.prototype, 'stopImmediatePropagation', delegate => function (self, args) {
2684      self[IMMEDIATE_PROPAGATION_SYMBOL] = true; // we need to call the native stopImmediatePropagation
2685      // in case in some hybrid application, some part of
2686      // application will be controlled by zone, some are not
2687
2688      delegate && delegate.apply(self, args);
2689    });
2690  }
2691}
2692/**
2693 * @license
2694 * Copyright Google LLC All Rights Reserved.
2695 *
2696 * Use of this source code is governed by an MIT-style license that can be
2697 * found in the LICENSE file at https://angular.io/license
2698 */
2699
2700
2701function patchCallbacks(api, target, targetName, method, callbacks) {
2702  const symbol = Zone.__symbol__(method);
2703
2704  if (target[symbol]) {
2705    return;
2706  }
2707
2708  const nativeDelegate = target[symbol] = target[method];
2709
2710  target[method] = function (name, opts, options) {
2711    if (opts && opts.prototype) {
2712      callbacks.forEach(function (callback) {
2713        const source = `${targetName}.${method}::` + callback;
2714        const prototype = opts.prototype; // Note: the `patchCallbacks` is used for patching the `document.registerElement` and
2715        // `customElements.define`. We explicitly wrap the patching code into try-catch since
2716        // callbacks may be already patched by other web components frameworks (e.g. LWC
2716), and they
2717        // make those properties non-writable. This means that patching callback will throw an error
2718        // `cannot assign to read-only property`. See this code as an example:
2719        // https://github.com/salesforce/lwc/blob/master/packages/@lwc/engine-core/src/framework/base-bridge-element.ts#L180-L186
2720        // We don't want to stop the application rendering if we couldn't patch some
2721        // callback, e.g. `attributeChangedCallback`.
2722
2723        try {
2724          if (prototype.hasOwnProperty(callback)) {
2725            const descriptor = api.ObjectGetOwnPropertyDescriptor(prototype, callback);
2726
2727            if (descriptor && descriptor.value) {
2728              descriptor.value = api.wrapWithCurrentZone(descriptor.value, source);
2729
2730              api._redefineProperty(opts.prototype, callback, descriptor);
2731            } else if (prototype[callback]) {
2732              prototype[callback] = api.wrapWithCurrentZone(prototype[callback], source);
2733            }
2734          } else if (prototype[callback]) {
2735            prototype[callback] = api.wrapWithCurrentZone(prototype[callback], source);
2736          }
2737        }
vendor: 6,048 bytes, lines 2737-2912
2737 catch (_a) {// Note: we leave the catch block empty since there's no way to handle the error related
2738          // to non-writable property.
2739        }
2740      });
2741    }
2742
2743    return nativeDelegate.call(target, name, opts, options);
2744  };
2745
2746  api.attachOriginToPatched(target[method], nativeDelegate);
2747}
2748/**
2749 * @license
2750 * Copyright Google LLC All Rights Reserved.
2751 *
2752 * Use of this source code is governed by an MIT-style license that can be
2753 * found in the LICENSE file at https://angular.io/license
2754 */
2755
2756
2757function filterProperties(target, onProperties, ignoreProperties) {
2758  if (!ignoreProperties || ignoreProperties.length === 0) {
2759    return onProperties;
2760  }
2761
2762  const tip = ignoreProperties.filter(ip => ip.target === target);
2763
2764  if (!tip || tip.length === 0) {
2765    return onProperties;
2766  }
2767
2768  const targetIgnoreProperties = tip[0].ignoreProperties;
2769  return onProperties.filter(op => targetIgnoreProperties.indexOf(op) === -1);
2770}
2771
2772function patchFilteredProperties(target, onProperties, ignoreProperties, prototype) {
2773  // check whether target is available, sometimes target will be undefined
2774  // because different browser or some 3rd party plugin.
2775  if (!target) {
2776    return;
2777  }
2778
2779  const filteredProperties = filterProperties(target, onProperties, ignoreProperties);
2780  patchOnProperties(target, filteredProperties, prototype);
2781}
2782/**
2783 * Get all event name properties which the event name startsWith `on`
2784 * from the target object itself, inherited properties are not considered.
2785 */
2786
2787
2788function getOnEventNames(target) {
2789  return Object.getOwnPropertyNames(target).filter(name => name.startsWith('on') && name.length > 2).map(name => name.substring(2));
2790}
2791
2792function propertyDescriptorPatch(api, _global) {
2793  if (isNode && !isMix) {
2794    return;
2795  }
2796
2797  if (Zone[api.symbol('patchEvents')]) {
2798    // events are already been patched by legacy patch.
2799    return;
2800  }
2801
2802  const ignoreProperties = _global['__Zone_ignore_on_properties']; // for browsers that we can patch the descriptor:  Chrome & Firefox
2803
2804  let patchTargets = [];
2805
2806  if (isBrowser) {
2807    const internalWindow = window;
2808    patchTargets = patchTargets.concat(['Document', 'SVGElement', 'Element', 'HTMLElement', 'HTMLBodyElement', 'HTMLMediaElement', 'HTMLFrameSetElement', 'HTMLFrameElement', 'HTMLIFrameElement', 'HTMLMarqueeElement', 'Worker']);
2809    const ignoreErrorProperties = isIE() ? [{
2810      target: internalWindow,
2811      ignoreProperties: ['error']
2812    }] : []; // in IE/Edge, onProp not exist in window object, but in WindowPrototype
2813    // so we need to pass WindowPrototype to check onProp exist or not
2814
2815    patchFilteredProperties(internalWindow, getOnEventNames(internalWindow), ignoreProperties ? ignoreProperties.concat(ignoreErrorProperties) : ignoreProperties, ObjectGetPrototypeOf(internalWindow));
2816  }
2817
2818  patchTargets = patchTargets.concat(['XMLHttpRequest', 'XMLHttpRequestEventTarget', 'IDBIndex', 'IDBRequest', 'IDBOpenDBRequest', 'IDBDatabase', 'IDBTransaction', 'IDBCursor', 'WebSocket']);
2819
2820  for (let i = 0; i < patchTargets.length; i++) {
2821    const target = _global[patchTargets[i]];
2822    target && target.prototype && patchFilteredProperties(target.prototype, getOnEventNames(target.prototype), ignoreProperties);
2823  }
2824}
2825/**
2826 * @license
2827 * Copyright Google LLC All Rights Reserved.
2828 *
2829 * Use of this source code is governed by an MIT-style license that can be
2830 * found in the LICENSE file at https://angular.io/license
2831 */
2832
2833
2834Zone.__load_patch('util', (global, Zone, api) => {
2835  // Collect native event names by looking at properties
2836  // on the global namespace, e.g. 'onclick'.
2837  const eventNames = getOnEventNames(global);
2838  api.patchOnProperties = patchOnProperties;
2839  api.patchMethod = patchMethod;
2840  api.bindArguments = bindArguments;
2841  api.patchMacroTask = patchMacroTask; // In earlier version of zone.js (<0.9.0), we use env name `__zone_symbol__BLACK_LISTED_EVENTS` to
2842  // define which events will not be patched by `Zone.js`.
2843  // In newer version (>=0.9.0), we change the env name to `__zone_symbol__UNPATCHED_EVENTS` to keep
2844  // the name consistent with angular repo.
2845  // The  `__zone_symbol__BLACK_LISTED_EVENTS` is deprecated, but it is still be supported for
2846  // backwards compatibility.
2847
2848  const SYMBOL_BLACK_LISTED_EVENTS = Zone.__symbol__('BLACK_LISTED_EVENTS');
2849
2850  const SYMBOL_UNPATCHED_EVENTS = Zone.__symbol__('UNPATCHED_EVENTS');
2851
2852  if (global[SYMBOL_UNPATCHED_EVENTS]) {
2853    global[SYMBOL_BLACK_LISTED_EVENTS] = global[SYMBOL_UNPATCHED_EVENTS];
2854  }
2855
2856  if (global[SYMBOL_BLACK_LISTED_EVENTS]) {
2857    Zone[SYMBOL_BLACK_LISTED_EVENTS] = Zone[SYMBOL_UNPATCHED_EVENTS] = global[SYMBOL_BLACK_LISTED_EVENTS];
2858  }
2859
2860  api.patchEventPrototype = patchEventPrototype;
2861  api.patchEventTarget = patchEventTarget;
2862  api.isIEOrEdge = isIEOrEdge;
2863  api.ObjectDefineProperty = ObjectDefineProperty;
2864  api.ObjectGetOwnPropertyDescriptor = ObjectGetOwnPropertyDescriptor;
2865  api.ObjectCreate = ObjectCreate;
2866  api.ArraySlice = ArraySlice;
2867  api.patchClass = patchClass;
2868  api.wrapWithCurrentZone = wrapWithCurrentZone;
2869  api.filterProperties = filterProperties;
2870  api.attachOriginToPatched = attachOriginToPatched;
2871  api._redefineProperty = Object.defineProperty;
2872  api.patchCallbacks = patchCallbacks;
2873
2874  api.getGlobalObjects = () => ({
2875    globalSources,
2876    zoneSymbolEventNames,
2877    eventNames,
2878    isBrowser,
2879    isMix,
2880    isNode,
2881    TRUE_STR,
2882    FALSE_STR,
2883    ZONE_SYMBOL_PREFIX,
2884    ADD_EVENT_LISTENER_STR,
2885    REMOVE_EVENT_LISTENER_STR
2886  });
2887});
2888/**
2889 * @license
2890 * Copyright Google LLC All Rights Reserved.
2891 *
2892 * Use of this source code is governed by an MIT-style license that can be
2893 * found in the LICENSE file at https://angular.io/license
2894 */
2895
2896
2897const taskSymbol = zoneSymbol('zoneTask');
2898
2899function patchTimer(window, setName, cancelName, nameSuffix) {
2900  let setNative = null;
2901  let clearNative = null;
2902  setName += nameSuffix;
2903  cancelName += nameSuffix;
2904  const tasksByHandleId = {};
2905
2906  function scheduleTask(task) {
2907    const data = task.data;
2908
2909    data.args[0] = function () {
2910      return task.invoke.apply(this, arguments);
2911    };
2912
2913    data.handleId = setNative.apply(window, data.args);
2914    return task;
2915  }
2916
2917  function clearTask(task) {
2918    return clearNative.call(window, task.data.handleId);
2919  }
2920
2921  setNative = patchMethod(window, setName, delegate => function (self, args) {
2922    if (typeof args[0] === 'function') {
2923      const options = {
2924        isPeriodic: nameSuffix === 'Interval',
2925        delay: nameSuffix === 'Timeout' || nameSuffix === 'Interval' ? args[1] || 0 : undefined,
2926        args: args
2927      };
2928      const callback = args[0];
2929
2930      args[0] = function timer() {
2931        try {
2932          return callback.apply(this, arguments);
2933        } finally {
2934          // issue-934, task will be cancelled
2935          // even it is a periodic task such as
2936          // setInterval
2937          // https://github.com/angular/angular/issues/40387
2938          // Cleanup tasksByHandleId should be handled before scheduleTask
2939          // Since some zoneSpec may intercept and doesn't trigger
2940          // scheduleFn(scheduleTask) provided here.
2941          if (!options.isPeriodic) {
2942            if (typeof options.handleId === 'number') {
2943              // in non-nodejs env, we remove timerId
2944              // from local cache
2945              delete tasksByHandleId[options.handleId];
2946            } else if (options.handleId) {
2947              // Node returns complex objects as handleIds
2948              // we remove task reference from timer object
2949              options.handleId[taskSymbol] = null;
2950            }
2951          }
2952        }
2953      };
2954
2955      const task = scheduleMacroTaskWithCurrentZone(setName, args[0], options, scheduleTask, clearTask);
2956
2957      if (!task) {
2958        return task;
2959      } // Node.js must additionally support the ref and unref functions.
2960
2961
2962      const handle = task.data.handleId;
2963
2964      if (typeof handle === 'number') {
2965        // for non nodejs env, we save handleId: task
2966        // mapping in local cache for clearTimeout
2967        tasksByHandleId[handle] = task;
2968      } else if (handle) {
2969        // for nodejs env, we save task
2970        // reference in timerId Object for clearTimeout
2971        handle[taskSymbol] = task;
2972      } // check whether handle is null, because some polyfill or browser
2973      // may return undefined from setTimeout/setInterval/setImmediate/requestAnimationFrame
2974
2975
2976      if (handle && handle.ref && handle.unref && typeof handle.ref === 'function' && typeof handle.unref === 'function') {
2977        task.ref = handle.ref.bind(handle);
2978        task.unref = handle.unref.bind(handle);
2979      }
2980
2981      if (typeof handle === 'number' || handle) {
2982        return handle;
2983      }
2984
2985      return task;
2986    } else {
2987      // cause an error by calling it directly.
2988      return delegate.apply(window, args);
2989    }
2990  });
2991  clearNative = patchMethod(window, cancelName, delegate => function (self, args) {
2992    const id = args[0];
2993    let task;
2994
2995    if (typeof id === 'number') {
2996      // non nodejs env.
2997      task = tasksByHandleId[id];
2998    } else {
2999      // nodejs env.
3000      task = id && id[taskSymbol]; // other environments.
3001
3002      if (!task) {
3003        task = id;
3004      }
3005    }
3006
3007    if (task && typeof task.type === 'string') {
3008      if (task.state !== 'notScheduled' && (task.cancelFn && task.data.isPeriodic || task.runCount === 0)) {
3009        if (typeof id === 'number') {
3010          delete tasksByHandleId[id];
3011        } else if (id) {
3012          id[taskSymbol] = null;
3013        } // Do not cancel already canceled functions
3014
3015
3016        task.zone.cancelTask(task);
3017      }
3018    } else {
3019      // cause an error by calling it directly.
3020      delegate.apply(window, args);
3021    }
3022  });
3023}
3024/**
3025 * @license
3026 * Copyright Google LLC All Rights Reserved.
3027 *
3028 * Use of this source code is governed by an MIT-style license that can be
3029 * found in the LICENSE file at https://angular.io/license
3030 */
3031
3032
3033function patchCustomElements(_global, api) {
3034  const {
3035    isBrowser,
3036    isMix
3037  } = api.getGlobalObjects();
3038
3039  if (!isBrowser && !isMix || !_global['customElements'] || !('customElements' in _global)) {
3040    return;
3041  }
3042
3043  const callbacks = ['connectedCallback', 'disconnectedCallback', 'adoptedCallback', 'attributeChangedCallback'];
3044  api.patchCallbacks(api, _global.customElements, 'customElements', 'define', callbacks);
3045}
3046/**
3047 * @license
3048 * Copyright Google LLC All Rights Reserved.
3049 *
3050 * Use of this source code is governed by an MIT-style license that can be
3051 * found in the LICENSE file at https://angular.io/license
3052 */
3053
3054
3055function eventTargetPatch(_global, api) {
vendor: 14,275 bytes, lines 3056-3431
3056  if (Zone[api.symbol('patchEventTarget')]) {
3057    // EventTarget is already patched.
3058    return;
3059  }
3060
3061  const {
3062    eventNames,
3063    zoneSymbolEventNames,
3064    TRUE_STR,
3065    FALSE_STR,
3066    ZONE_SYMBOL_PREFIX
3067  } = api.getGlobalObjects(); //  predefine all __zone_symbol__ + eventName + true/false string
3068
3069  for (let i = 0; i < eventNames.length; i++) {
3070    const eventName = eventNames[i];
3071    const falseEventName = eventName + FALSE_STR;
3072    const trueEventName = eventName + TRUE_STR;
3073    const symbol = ZONE_SYMBOL_PREFIX + falseEventName;
3074    const symbolCapture = ZONE_SYMBOL_PREFIX + trueEventName;
3075    zoneSymbolEventNames[eventName] = {};
3076    zoneSymbolEventNames[eventName][FALSE_STR] = symbol;
3077    zoneSymbolEventNames[eventName][TRUE_STR] = symbolCapture;
3078  }
3079
3080  const EVENT_TARGET = _global['EventTarget'];
3081
3082  if (!EVENT_TARGET || !EVENT_TARGET.prototype) {
3083    return;
3084  }
3085
3086  api.patchEventTarget(_global, api, [EVENT_TARGET && EVENT_TARGET.prototype]);
3087  return true;
3088}
3089
3090function patchEvent(global, api) {
3091  api.patchEventPrototype(global, api);
3092}
3093/**
3094 * @license
3095 * Copyright Google LLC All Rights Reserved.
3096 *
3097 * Use of this source code is governed by an MIT-style license that can be
3098 * found in the LICENSE file at https://angular.io/license
3099 */
3100
3101
3102Zone.__load_patch('legacy', global => {
3103  const legacyPatch = global[Zone.__symbol__('legacyPatch')];
3104
3105  if (legacyPatch) {
3106    legacyPatch();
3107  }
3108});
3109
3110Zone.__load_patch('queueMicrotask', (global, Zone, api) => {
3111  api.patchMethod(global, 'queueMicrotask', delegate => {
3112    return function (self, args) {
3113      Zone.current.scheduleMicroTask('queueMicrotask', args[0]);
3114    };
3115  });
3116});
3117
3118Zone.__load_patch('timers', global => {
3119  const set = 'set';
3120  const clear = 'clear';
3121  patchTimer(global, set, clear, 'Timeout');
3122  patchTimer(global, set, clear, 'Interval');
3123  patchTimer(global, set, clear, 'Immediate');
3124});
3125
3126Zone.__load_patch('requestAnimationFrame', global => {
3127  patchTimer(global, 'request', 'cancel', 'AnimationFrame');
3128  patchTimer(global, 'mozRequest', 'mozCancel', 'AnimationFrame');
3129  patchTimer(global, 'webkitRequest', 'webkitCancel', 'AnimationFrame');
3130});
3131
3132Zone.__load_patch('blocking', (global, Zone) => {
3133  const blockingMethods = ['alert', 'prompt', 'confirm'];
3134
3135  for (let i = 0; i < blockingMethods.length; i++) {
3136    const name = blockingMethods[i];
3137    patchMethod(global, name, (delegate, symbol, name) => {
3138      return function (s, args) {
3139        return Zone.current.run(delegate, global, args, name);
3140      };
3141    });
3142  }
3143});
3144
3145Zone.__load_patch('EventTarget', (global, Zone, api) => {
3146  patchEvent(global, api);
3147  eventTargetPatch(global, api); // patch XMLHttpRequestEventTarget's addEventListener/removeEventListener
3148
3149  const XMLHttpRequestEventTarget = global['XMLHttpRequestEventTarget'];
3150
3151  if (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) {
3152    api.patchEventTarget(global, api, [XMLHttpRequestEventTarget.prototype]);
3153  }
3154});
3155
3156Zone.__load_patch('MutationObserver', (global, Zone, api) => {
3157  patchClass('MutationObserver');
3158  patchClass('WebKitMutationObserver');
3159});
3160
3161Zone.__load_patch('IntersectionObserver', (global, Zone, api) => {
3162  patchClass('IntersectionObserver');
3163});
3164
3165Zone.__load_patch('FileReader', (global, Zone, api) => {
3166  patchClass('FileReader');
3167});
3168
3169Zone.__load_patch('on_property', (global, Zone, api) => {
3170  propertyDescriptorPatch(api, global);
3171});
3172
3173Zone.__load_patch('customElements', (global, Zone, api) => {
3174  patchCustomElements(global, api);
3175});
3176
3177Zone.__load_patch('XHR', (global, Zone) => {
3178  // Treat XMLHttpRequest as a macrotask.
3179  patchXHR(global);
3180  const XHR_TASK = zoneSymbol('xhrTask');
3181  const XHR_SYNC = zoneSymbol('xhrSync');
3182  const XHR_LISTENER = zoneSymbol('xhrListener');
3183  const XHR_SCHEDULED = zoneSymbol('xhrScheduled');
3184  const XHR_URL = zoneSymbol('xhrURL');
3185  const XHR_ERROR_BEFORE_SCHEDULED = zoneSymbol('xhrErrorBeforeScheduled');
3186
3187  function patchXHR(window) {
3188    const XMLHttpRequest = window['XMLHttpRequest'];
3189
3190    if (!XMLHttpRequest) {
3191      // XMLHttpRequest is not available in service worker
3192      return;
3193    }
3194
3195    const XMLHttpRequestPrototype = XMLHttpRequest.prototype;
3196
3197    function findPendingTask(target) {
3198      return target[XHR_TASK];
3199    }
3200
3201    let oriAddListener = XMLHttpRequestPrototype[ZONE_SYMBOL_ADD_EVENT_LISTENER];
3202    let oriRemoveListener = XMLHttpRequestPrototype[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];
3203
3204    if (!oriAddListener) {
3205      const XMLHttpRequestEventTarget = window['XMLHttpRequestEventTarget'];
3206
3207      if (XMLHttpRequestEventTarget) {
3208        const XMLHttpRequestEventTargetPrototype = XMLHttpRequestEventTarget.prototype;
3209        oriAddListener = XMLHttpRequestEventTargetPrototype[ZONE_SYMBOL_ADD_EVENT_LISTENER];
3210        oriRemoveListener = XMLHttpRequestEventTargetPrototype[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];
3211      }
3212    }
3213
3214    const READY_STATE_CHANGE = 'readystatechange';
3215    const SCHEDULED = 'scheduled';
3216
3217    function scheduleTask(task) {
3218      const data = task.data;
3219      const target = data.target;
3220      target[XHR_SCHEDULED] = false;
3221      target[XHR_ERROR_BEFORE_SCHEDULED] = false; // remove existing event listener
3222
3223      const listener = target[XHR_LISTENER];
3224
3225      if (!oriAddListener) {
3226        oriAddListener = target[ZONE_SYMBOL_ADD_EVENT_LISTENER];
3227        oriRemoveListener = target[ZONE_SYMBOL_REMOVE_EVENT_LISTENER];
3228      }
3229
3230      if (listener) {
3231        oriRemoveListener.call(target, READY_STATE_CHANGE, listener);
3232      }
3233
3234      const newListener = target[XHR_LISTENER] = () => {
3235        if (target.readyState === target.DONE) {
3236          // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
3237          // readyState=4 multiple times, so we need to check task state here
3238          if (!data.aborted && target[XHR_SCHEDULED] && task.state === SCHEDULED) {
3239            // check whether the xhr has registered onload listener
3240            // if that is the case, the task should invoke after all
3241            // onload listeners finish.
3242            // Also if the request failed without response (status = 0), the load event handler
3243            // will not be triggered, in that case, we should also invoke the placeholder callback
3244            // to close the XMLHttpRequest::send macroTask.
3245            // https://github.com/angular/angular/issues/38795
3246            const loadTasks = target[Zone.__symbol__('loadfalse')];
3247
3248            if (target.status !== 0 && loadTasks && loadTasks.length > 0) {
3249              const oriInvoke = task.invoke;
3250
3251              task.invoke = function () {
3252                // need to load the tasks again, because in other
3253                // load listener, they may remove themselves
3254                const loadTasks = target[Zone.__symbol__('loadfalse')];
3255
3256                for (let i = 0; i < loadTasks.length; i++) {
3257                  if (loadTasks[i] === task) {
3258                    loadTasks.splice(i, 1);
3259                  }
3260                }
3261
3262                if (!data.aborted && task.state === SCHEDULED) {
3263                  oriInvoke.call(task);
3264                }
3265              };
3266
3267              loadTasks.push(task);
3268            } else {
3269              task.invoke();
3270            }
3271          } else if (!data.aborted && target[XHR_SCHEDULED] === false) {
3272            // error occurs when xhr.send()
3273            target[XHR_ERROR_BEFORE_SCHEDULED] = true;
3274          }
3275        }
3276      };
3277
3278      oriAddListener.call(target, READY_STATE_CHANGE, newListener);
3279      const storedTask = target[XHR_TASK];
3280
3281      if (!storedTask) {
3282        target[XHR_TASK] = task;
3283      }
3284
3285      sendNative.apply(target, data.args);
3286      target[XHR_SCHEDULED] = true;
3287      return task;
3288    }
3289
3290    function placeholderCallback() {}
3291
3292    function clearTask(task) {
3293      const data = task.data; // Note - ideally, we would call data.target.removeEventListener here, but it's too late
3294      // to prevent it from firing. So instead, we store info for the event listener.
3295
3296      data.aborted = true;
3297      return abortNative.apply(data.target, data.args);
3298    }
3299
3300    const openNative = patchMethod(XMLHttpRequestPrototype, 'open', () => function (self, args) {
3301      self[XHR_SYNC] = args[2] == false;
3302      self[XHR_URL] = args[1];
3303      return openNative.apply(self, args);
3304    });
3305    const XMLHTTPREQUEST_SOURCE = 'XMLHttpRequest.send';
3306    const fetchTaskAborting = zoneSymbol('fetchTaskAborting');
3307    const fetchTaskScheduling = zoneSymbol('fetchTaskScheduling');
3308    const sendNative = patchMethod(XMLHttpRequestPrototype, 'send', () => function (self, args) {
3309      if (Zone.current[fetchTaskScheduling] === true) {
3310        // a fetch is scheduling, so we are using xhr to polyfill fetch
3311        // and because we already schedule macroTask for fetch, we should
3312        // not schedule a macroTask for xhr again
3313        return sendNative.apply(self, args);
3314      }
3315
3316      if (self[XHR_SYNC]) {
3317        // if the XHR is sync there is no task to schedule, just execute the code.
3318        return sendNative.apply(self, args);
3319      } else {
3320        const options = {
3321          target: self,
3322          url: self[XHR_URL],
3323          isPeriodic: false,
3324          args: args,
3325          aborted: false
3326        };
3327        const task = scheduleMacroTaskWithCurrentZone(XMLHTTPREQUEST_SOURCE, placeholderCallback, options, scheduleTask, clearTask);
3328
3329        if (self && self[XHR_ERROR_BEFORE_SCHEDULED] === true && !options.aborted && task.state === SCHEDULED) {
3330          // xhr request throw error when send
3331          // we should invoke task instead of leaving a scheduled
3332          // pending macroTask
3333          task.invoke();
3334        }
3335      }
3336    });
3337    const abortNative = patchMethod(XMLHttpRequestPrototype, 'abort', () => function (self, args) {
3338      const task = findPendingTask(self);
3339
3340      if (task && typeof task.type == 'string') {
3341        // If the XHR has already completed, do nothing.
3342        // If the XHR has already been aborted, do nothing.
3343        // Fix #569, call abort multiple times before done will cause
3344        // macroTask task count be negative number
3345        if (task.cancelFn == null || task.data && task.data.aborted) {
3346          return;
3347        }
3348
3349        task.zone.cancelTask(task);
3350      } else if (Zone.current[fetchTaskAborting] === true) {
3351        // the abort is called from fetch polyfill, we need to call native abort of XHR.
3352        return abortNative.apply(self, args);
3353      } // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no
3354      // task
3355      // to cancel. Do nothing.
3356
3357    });
3358  }
3359});
3360
3361Zone.__load_patch('geolocation', global => {
3362  /// GEO_LOCATION
3363  if (global['navigator'] && global['navigator'].geolocation) {
3364    patchPrototype(global['navigator'].geolocation, ['getCurrentPosition', 'watchPosition']);
3365  }
3366});
3367
3368Zone.__load_patch('PromiseRejectionEvent', (global, Zone) => {
3369  // handle unhandled promise rejection
3370  function findPromiseRejectionHandler(evtName) {
3371    return function (e) {
3372      const eventTasks = findEventTasks(global, evtName);
3373      eventTasks.forEach(eventTask => {
3374        // windows has added unhandledrejection event listener
3375        // trigger the event listener
3376        const PromiseRejectionEvent = global['PromiseRejectionEvent'];
3377
3378        if (PromiseRejectionEvent) {
3379          const evt = new PromiseRejectionEvent(evtName, {
3380            promise: e.promise,
3381            reason: e.rejection
3382          });
3383          eventTask.invoke(evt);
3384        }
3385      });
3386    };
3387  }
3388
3389  if (global['PromiseRejectionEvent']) {
3390    Zone[zoneSymbol('unhandledPromiseRejectionHandler')] = findPromiseRejectionHandler('unhandledrejection');
3391    Zone[zoneSymbol('rejectionHandledHandler')] = findPromiseRejectionHandler('rejectionhandled');
3392  }
3393});
3394
3395/***/ }),
3396
3397/***/ 8781:
3398/*!**************************************************************!*\
3399  !*** ./node_modules/@angular/compiler/fesm2020/compiler.mjs ***!
3400  \**************************************************************/
3401/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
3402
3403__webpack_require__.r(__webpack_exports__);
3404/* harmony export */ __webpack_require__.d(__webpack_exports__, {
3405/* harmony export */   "AST": () => (/* binding */ AST),
3406/* harmony export */   "ASTWithName": () => (/* binding */ ASTWithName),
3407/* harmony export */   "ASTWithSource": () => (/* binding */ ASTWithSource),
3408/* harmony export */   "AbsoluteSourceSpan": () => (/* binding */ AbsoluteSourceSpan),
3409/* harmony export */   "ArrayType": () => (/* binding */ ArrayType),
3410/* harmony export */   "AstMemoryEfficientTransformer": () => (/* binding */ AstMemoryEfficientTransformer),
3411/* harmony export */   "AstTransformer": () => (/* binding */ AstTransformer),
3412/* harmony export */   "Attribute": () => (/* binding */ Attribute),
3413/* harmony export */   "Binary": () => (/* binding */ Binary),
3414/* harmony export */   "BinaryOperator": () => (/* binding */ BinaryOperator),
3415/* harmony export */   "BinaryOperatorExpr": () => (/* binding */ BinaryOperatorExpr),
3416/* harmony export */   "BindingPipe": () => (/* binding */ BindingPipe),
3417/* harmony export */   "BoundElementProperty": () => (/* binding */ BoundElementProperty),
3418/* harmony export */   "BuiltinType": () => (/* binding */ BuiltinType),
3419/* harmony export */   "BuiltinTypeName": () => (/* binding */ BuiltinTypeName),
3420/* harmony export */   "CUSTOM_ELEMENTS_SCHEMA": () => (/* binding */ CUSTOM_ELEMENTS_SCHEMA),
3421/* harmony export */   "Call": () => (/* binding */ Call),
3422/* harmony export */   "Chain": () => (/* binding */ Chain),
3423/* harmony export */   "ChangeDetectionStrategy": () => (/* binding */ ChangeDetectionStrategy),
3424/* harmony export */   "CommaExpr": () => (/* binding */ CommaExpr),
3425/* harmony export */   "Comment": () => (/* binding */ Comment),
3426/* harmony export */   "CompilerConfig": () => (/* binding */ CompilerConfig),
3427/* harmony export */   "Conditional": () => (/* binding */ Conditional),
3428/* harmony export */   "ConditionalExpr": () => (/* binding */ ConditionalExpr),
3429/* harmony export */   "ConstantPool": () => (/* binding */ ConstantPool),
3430/* harmony export */   "CssSelector": () => (/* binding */ CssSelector),
3431/* harmony export */   "DEFAULT_INTERPOLATION_CONFIG": () => (/* binding */ DEFAULT_INTERPOLATION_CONFIG),
3432/* harmony export */   "DYNAMIC_TYPE": () => (/* binding */ DYNAMIC_TYPE),
3433/* harmony export */   "DeclareFunctionStmt": () => (/* binding */ DeclareFunctionStmt),
3434/* harmony export */   "DeclareVarStmt": () => (/* binding */ DeclareVarStmt),
3435/* harmony export */   "DomElementSchemaRegistry": () => (/* binding */ DomElementSchemaRegistry),
3436/* harmony export */   "EOF": () => (/* binding */ EOF),
3437/* harmony export */   "Element": () => (/* binding */ Element),
3438/* harmony export */   "ElementSchemaRegistry": () => (/* binding */ ElementSchemaRegistry),
3439/* harmony export */   "EmitterVisitorContext": () => (/* binding */ EmitterVisitorContext),
3440/* harmony export */   "EmptyExpr": () => (/* binding */ EmptyExpr),
3441/* harmony export */   "Expansion": () => (/* binding */ Expansion),
3442/* harmony export */   "ExpansionCase": () => (/* binding */ ExpansionCase),
3443/* harmony export */   "Expression": () => (/* binding */ Expression),
3444/* harmony export */   "ExpressionBinding": () => (/* binding */ ExpressionBinding),
3445/* harmony export */   "ExpressionStatement": () => (/* binding */ ExpressionStatement),
3446/* harmony export */   "ExpressionType": () => (/* binding */ ExpressionType),
3447/* harmony export */   "ExternalExpr": () => (/* binding */ ExternalExpr),
3448/* harmony export */   "ExternalReference": () => (/* binding */ ExternalReference),
3449/* harmony export */   "FactoryTarget": () => (/* binding */ FactoryTarget$1),
3450/* harmony export */   "FunctionExpr": () => (/* binding */ FunctionExpr),
3451/* harmony export */   "HtmlParser": () => (/* binding */ HtmlParser),
3452/* harmony export */   "HtmlTagDefinition": () => (/* binding */ HtmlTagDefinition),
3453/* harmony export */   "I18NHtmlParser": () => (/* binding */ I18NHtmlParser),
3454/* harmony export */   "IfStmt": () => (/* binding */ IfStmt),
3455/* harmony export */   "ImplicitReceiver": () => (/* binding */ ImplicitReceiver),
3456/* harmony export */   "InstantiateExpr": () => (/* binding */ InstantiateExpr),
3457/* harmony export */   "Interpolation": () => (/* binding */ Interpolation),
3458/* harmony export */   "InterpolationConfig": () => (/* binding */ InterpolationConfig),
3459/* harmony export */   "InvokeFunctionExpr": () => (/* binding */ InvokeFunctionExpr),
3460/* harmony export */   "JSDocComment": () => (/* binding */ JSDocComment),
3461/* harmony export */   "JitEvaluator": () => (/* binding */ JitEvaluator),
3462/* harmony export */   "KeyedRead": () => (/* binding */ KeyedRead),
3463/* harmony export */   "KeyedWrite": () => (/* binding */ KeyedWrite),
3464/* harmony export */   "LeadingComment": () => (/* binding */ LeadingComment),
3465/* harmony export */   "Lexer": () => (/* binding */ Lexer),
3466/* harmony export */   "LiteralArray": () => (/* binding */ LiteralArray),
3467/* harmony export */   "LiteralArrayExpr": () => (/* binding */ LiteralArrayExpr),
3468/* harmony export */   "LiteralExpr": () => (/* binding */ LiteralExpr),
3469/* harmony export */   "LiteralMap": () => (/* binding */ LiteralMap),
3470/* harmony export */   "LiteralMapExpr": () => (/* binding */ LiteralMapExpr),
3471/* harmony export */   "LiteralPrimitive": () => (/* binding */ LiteralPrimitive),
3472/* harmony export */   "LocalizedString": () => (/* binding */ LocalizedString),
3473/* harmony export */   "MapType": () => (/* binding */ MapType),
3474/* harmony export */   "MessageBundle": () => (/* binding */ MessageBundle),
3475/* harmony export */   "NONE_TYPE": () => (/* binding */ NONE_TYPE),
3476/* harmony export */   "NO_ERRORS_SCHEMA": () => (/* binding */ NO_ERRORS_SCHEMA),
3477/* harmony export */   "NodeWithI18n": () => (/* binding */ NodeWithI18n),
3478/* harmony export */   "NonNullAssert": () => (/* binding */ NonNullAssert),
3479/* harmony export */   "NotExpr": () => (/* binding */ NotExpr),
3480/* harmony export */   "ParseError": () => (/* binding */ ParseError),
3481/* harmony export */   "ParseErrorLevel": () => (/* binding */ ParseErrorLevel),
3482/* harmony export */   "ParseLocation": () => (/* binding */ ParseLocation),
3483/* harmony export */   "ParseSourceFile": () => (/* binding */ ParseSourceFile),
3484/* harmony export */   "ParseSourceSpan": () => (/* binding */ ParseSourceSpan),
3485/* harmony export */   "ParseSpan": () => (/* binding */ ParseSpan),
3486/* harmony export */   "ParseTreeResult": () => (/* binding */ ParseTreeResult),
3487/* harmony export */   "ParsedEvent": () => (/* binding */ ParsedEvent),
3488/* harmony export */   "ParsedProperty": () => (/* binding */ ParsedProperty),
3489/* harmony export */   "ParsedPropertyType": () => (/* binding */ ParsedPropertyType),
3490/* harmony export */   "ParsedVariable": () => (/* binding */ ParsedVariable),
3491/* harmony export */   "Parser": () => (/* binding */ Parser$1),
3492/* harmony export */   "ParserError": () => (/* binding */ ParserError),
3493/* harmony export */   "PrefixNot": () => (/* binding */ PrefixNot),
3494/* harmony export */   "PropertyRead": () => (/* binding */ PropertyRead),
3495/* harmony export */   "PropertyWrite": () => (/* binding */ PropertyWrite),
3496/* harmony export */   "R3BoundTarget": () => (/* binding */ R3BoundTarget),
3497/* harmony export */   "R3Identifiers": () => (/* binding */ Identifiers),
3498/* harmony export */   "R3SelectorScopeMode": () => (/* binding */ R3SelectorScopeMode),
3499/* harmony export */   "R3TargetBinder": () => (/* binding */ R3TargetBinder),
3500/* harmony export */   "R3TemplateDependencyKind": () => (/* binding */ R3TemplateDependencyKind),
3501/* harmony export */   "ReadKeyExpr": () => (/* binding */ ReadKeyExpr),
3502/* harmony export */   "ReadPropExpr": () => (/* binding */ ReadPropExpr),
3503/* harmony export */   "ReadVarExpr": () => (/* binding */ ReadVarExpr),
3504/* harmony export */   "RecursiveAstVisitor": () => (/* binding */ RecursiveAstVisitor),
3505/* harmony export */   "RecursiveVisitor": () => (/* binding */ RecursiveVisitor),
3506/* harmony export */   "ResourceLoader": () => (/* binding */ ResourceLoader),
3507/* harmony export */   "ReturnStatement": () => (/* binding */ ReturnStatement),
3508/* harmony export */   "STRING_TYPE": () => (/* binding */ STRING_TYPE),
3509/* harmony export */   "SafeCall": () => (/* binding */ SafeCall),
3510/* harmony export */   "SafeKeyedRead": () => (/* binding */ SafeKeyedRead),
3511/* harmony export */   "SafePropertyRead": () => (/* binding */ SafePropertyRead),
3512/* harmony export */   "SelectorContext": () => (/* binding */ SelectorContext),
3513/* harmony export */   "SelectorListContext": () => (/* binding */ SelectorListContext),
3514/* harmony export */   "SelectorMatcher": () => (/* binding */ SelectorMatcher),
3515/* harmony export */   "Serializer": () => (/* binding */ Serializer),
3516/* harmony export */   "SplitInterpolation": () => (/* binding */ SplitInterpolation),
3517/* harmony export */   "Statement": () => (/* binding */ Statement),
3518/* harmony export */   "StmtModifier": () => (/* binding */ StmtModifier),
3519/* harmony export */   "TagContentType": () => (/* binding */ TagContentType),
3520/* harmony export */   "TaggedTemplateExpr": () => (/* binding */ TaggedTemplateExpr),
3521/* harmony export */   "TemplateBindingParseResult": () => (/* binding */ TemplateBindingParseResult),
3522/* harmony export */   "TemplateLiteral": () => (/* binding */ TemplateLiteral),
3523/* harmony export */   "TemplateLiteralElement": () => (/* binding */ TemplateLiteralElement),
3524/* harmony export */   "Text": () => (/* binding */ Text),
3525/* harmony export */   "ThisReceiver": () => (/* binding */ ThisReceiver),
3526/* harmony export */   "TmplAstBoundAttribute": () => (/* binding */ BoundAttribute),
3527/* harmony export */   "TmplAstBoundEvent": () => (/* binding */ BoundEvent),
3528/* harmony export */   "TmplAstBoundText": () => (/* binding */ BoundText),
3529/* harmony export */   "TmplAstContent": () => (/* binding */ Content),
3530/* harmony export */   "TmplAstElement": () => (/* binding */ Element$1),
3531/* harmony export */   "TmplAstIcu": () => (/* binding */ Icu$1),
3532/* harmony export */   "TmplAstRecursiveVisitor": () => (/* binding */ RecursiveVisitor$1),
3533/* harmony export */   "TmplAstReference": () => (/* binding */ Reference),
3534/* harmony export */   "TmplAstTemplate": () => (/* binding */ Template),
3535/* harmony export */   "TmplAstText": () => (/* binding */ Text$3),
3536/* harmony export */   "TmplAstTextAttribute": () => (/* binding */ TextAttribute),
3537/* harmony export */   "TmplAstVariable": () => (/* binding */ Variable),
3538/* harmony export */   "Token": () => (/* binding */ Token),
3539/* harmony export */   "TokenType": () => (/* binding */ TokenType),
3540/* harmony export */   "TreeError": () => (/* binding */ TreeError),
3541/* harmony export */   "Type": () => (/* binding */ Type),
3542/* harmony export */   "TypeModifier": () => (/* binding */ TypeModifier),
3543/* harmony export */   "TypeofExpr": () => (/* binding */ TypeofExpr),
3544/* harmony export */   "Unary": () => (/* binding */ Unary),
3545/* harmony export */   "UnaryOperator": () => (/* binding */ UnaryOperator),
3546/* harmony export */   "UnaryOperatorExpr": () => (/* binding */ UnaryOperatorExpr),
3547/* harmony export */   "VERSION": () => (/* binding */ VERSION),
3548/* harmony export */   "VariableBinding": () => (/* binding */ VariableBinding),
3549/* harmony export */   "Version": () => (/* binding */ Version),
3550/* harmony export */   "ViewEncapsulation": () => (/* binding */ ViewEncapsulation),
3551/* harmony export */   "WrappedNodeExpr": () => (/* binding */ WrappedNodeExpr),
3552/* harmony export */   "WriteKeyExpr": () => (/* binding */ WriteKeyExpr),
3553/* harmony export */   "WritePropExpr": () => (/* binding */ WritePropExpr),
3554/* harmony export */   "WriteVarExpr": () => (/* binding */ WriteVarExpr),
3555/* harmony export */   "Xliff": () => (/* binding */ Xliff),
3556/* harmony export */   "Xliff2": () => (/* binding */ Xliff2),
3557/* harmony export */   "Xmb": () => (/* binding */ Xmb),
3558/* harmony export */   "XmlParser": () => (/* binding */ XmlParser),
3559/* harmony export */   "Xtb": () => (/* binding */ Xtb),
3560/* harmony export */   "_ParseAST": () => (/* binding */ _ParseAST),
3561/* harmony export */   "compileClassMetadata": () => (/* binding */ compileClassMetadata),
3562/* harmony export */   "compileComponentFromMetadata": () => (/* binding */ compileComponentFromMetadata),
3563/* harmony export */   "compileDeclareClassMetadata": () => (/* binding */ compileDeclareClassMetadata),
3564/* harmony export */   "compileDeclareComponentFromMetadata": () => (/* binding */ compileDeclareComponentFromMetadata),
3565/* harmony export */   "compileDeclareDirectiveFromMetadata": () => (/* binding */ compileDeclareDirectiveFromMetadata),
3566/* harmony export */   "compileDeclareFactoryFunction": () => (/* binding */ compileDeclareFactoryFunction),
3567/* harmony export */   "compileDeclareInjectableFromMetadata": () => (/* binding */ compileDeclareInjectableFromMetadata),
3568/* harmony export */   "compileDeclareInjectorFromMetadata": () => (/* binding */ compileDeclareInjectorFromMetadata),
3569/* harmony export */   "compileDeclareNgModuleFromMetadata": () => (/* binding */ compileDeclareNgModuleFromMetadata),
3570/* harmony export */   "compileDeclarePipeFromMetadata": () => (/* binding */ compileDeclarePipeFromMetadata),
3571/* harmony export */   "compileDirectiveFromMetadata": () => (/* binding */ compileDirectiveFromMetadata),
3572/* harmony export */   "compileFactoryFunction": () => (/* binding */ compileFactoryFunction),
3573/* harmony export */   "compileInjectable": () => (/* binding */ compileInjectable),
3574/* harmony export */   "compileInjector": () => (/* binding */ compileInjector),
3575/* harmony export */   "compileNgModule": () => (/* binding */ compileNgModule),
3576/* harmony export */   "compilePipeFromMetadata": () => (/* binding */ compilePipeFromMetadata),
3577/* harmony export */   "computeMsgId": () => (/* binding */ computeMsgId),
3578/* harmony export */   "core": () => (/* binding */ core),
3579/* harmony export */   "createInjectableType": () => (/* binding */ createInjectableType),
3580/* harmony export */   "createMayBeForwardRefExpression": () => (/* binding */ createMayBeForwardRefExpression),
3581/* harmony export */   "devOnlyGuardedExpression": () => (/* binding */ devOnlyGuardedExpression),
3582/* harmony export */   "emitDistinctChangesOnlyDefaultValue": () => (/* binding */ emitDistinctChangesOnlyDefaultValue),
3583/* harmony export */   "getHtmlTagDefinition": () => (/* binding */ getHtmlTagDefinition),
3584/* harmony export */   "getNsPrefix": () => (/* binding */ getNsPrefix),
3585/* harmony export */   "getSafePropertyAccessString": () => (/* binding */ getSafePropertyAccessString),
3586/* harmony export */   "identifierName": () => (/* binding */ identifierName),
3587/* harmony export */   "isIdentifier": () => (/* binding */ isIdentifier),
3588/* harmony export */   "isNgContainer": () => (/* binding */ isNgContainer),
3589/* harmony export */   "isNgContent": () => (/* binding */ isNgContent),
3590/* harmony export */   "isNgTemplate": () => (/* binding */ isNgTemplate),
3591/* harmony export */   "jsDocComment": () => (/* binding */ jsDocComment),
3592/* harmony export */   "leadingComment": () => (/* binding */ leadingComment),
3593/* harmony export */   "literalMap": () => (/* binding */ literalMap),
3594/* harmony export */   "makeBindingParser": () => (/* binding */ makeBindingParser),
3595/* harmony export */   "mergeNsAndName": () => (/* binding */ mergeNsAndName),
3596/* harmony export */   "outputAst": () => (/* binding */ output_ast),
3597/* harmony export */   "parseHostBindings": () => (/* binding */ parseHostBindings),
3598/* harmony export */   "parseTemplate": () => (/* binding */ parseTemplate),
3599/* harmony export */   "preserveWhitespacesDefault": () => (/* binding */ preserveWhitespacesDefault),
3600/* harmony export */   "publishFacade": () => (/* binding */ publishFacade),
3601/* harmony export */   "r3JitTypeSourceSpan": () => (/* binding */ r3JitTypeSourceSpan),
3602/* harmony export */   "sanitizeIdentifier": () => (/* binding */ sanitizeIdentifier),
3603/* harmony export */   "splitNsName": () => (/* binding */ splitNsName),
3604/* harmony export */   "verifyHostBindings": () => (/* binding */ verifyHostBindings),
3605/* harmony export */   "visitAll": () => (/* binding */ visitAll)
3606/* harmony export */ });
3607/**
3608 * @license Angular v14.2.12
3609 * (c) 2010-2022 Google LLC. https://angular.io/
3610 * License: MIT
3611 */
3612
3613/**
3614 * @license
3615 * Copyright Google LLC All Rights Reserved.
3616 *
3617 * Use of this source code is governed by an MIT-style license that can be
3618 * found in the LICENSE file at https://angular.io/license
3619 */
3620var TagContentType;
3621
3622(function (TagContentType) {
3623  TagContentType[TagContentType["RAW_TEXT"] = 0] = "RAW_TEXT";
3624  TagContentType[TagContentType["ESCAPABLE_RAW_TEXT"] = 1] = "ESCAPABLE_RAW_TEXT";
3625  TagContentType[TagContentType["PARSABLE_DATA"] = 2] = "PARSABLE_DATA";
3626})(TagContentType || (TagContentType = {}));
3627
3628function splitNsName(elementName) {
3629  if (elementName[0] != ':') {
3630    return [null, elementName];
3631  }
3632
3633  const colonIndex = elementName.indexOf(':', 1);
3634
3635  if (colonIndex === -1) {
3636    throw new Error(`Unsupported format "${elementName}" expecting ":namespace:name"`);
3637  }
3638
3639  return [elementName.slice(1, colonIndex), elementName.slice(colonIndex + 1)];
3640} // `<ng-container>` tags work the same regardless the namespace
3641
3642
3643function isNgContainer(tagName) {
3644  return splitNsName(tagName)[1] === 'ng-container';
3645} // `<ng-content>` tags work the same regardless the namespace
3646
3647
3648function isNgContent(tagName) {
3649  return splitNsName(tagName)[1] === 'ng-content';
3650} // `<ng-template>` tags work the same regardless the namespace
3651
3652
3653function isNgTemplate(tagName) {
3654  return splitNsName(tagName)[1] === 'ng-template';
3655}
3656
3657function getNsPrefix(fullName) {
3658  return fullName === null ? null : splitNsName(fullName)[0];
3659}
3660
3661function mergeNsAndName(prefix, localName) {
3662  return prefix ? `:${prefix}:${localName}` : localName;
3663}
3664/**
3665 * @license
3666 * Copyright Google LLC All Rights Reserved.
3667 *
3668 * Use of this source code is governed by an MIT-style license that can be
3669 * found in the LICENSE file at https://angular.io/license
3670 */
3671
3672
3673class HtmlTagDefinition {
3674  constructor({
3675    closedByChildren,
3676    implicitNamespacePrefix,
3677    contentType = TagContentType.PARSABLE_DATA,
3678    closedByParent = false,
3679    isVoid = false,
3680    ignoreFirstLf = false,
3681    preventNamespaceInheritance = false
3682  }
3682 = {}) {
3683    this.closedByChildren = {};
3684    this.closedByParent = false;
3685    this.canSelfClose = false;
3686
3687    if (closedByChildren && closedByChildren.length > 0) {
3688      closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true);
3689    }
3690
3691    this.isVoid = isVoid;
3692    this.closedByParent = closedByParent || isVoid;
3693    this.implicitNamespacePrefix = implicitNamespacePrefix || null;
3694    this.contentType = contentType;
3695    this.ignoreFirstLf = ignoreFirstLf;
3696    this.preventNamespaceInheritance = preventNamespaceInheritance;
3697  }
3698
3699  isClosedByChild(name) {
3700    return this.isVoid || name.toLowerCase() in this.closedByChildren;
3701  }
3702
3703  getContentType(prefix) {
3704    if (typeof this.contentType === 'object') {
3705      const overrideType = prefix === undefined ? undefined : this.contentType[prefix];
3706      return overrideType ?? this.contentType.default;
3707    }
3708
3709    return this.contentType;
3710  }
3711
3712}
3713
3714let _DEFAULT_TAG_DEFINITION; // see https://www.w3.org/TR/html51/syntax.html#optional-tags
3715// This implementation does not fully conform to the HTML5 spec.
3716
3717
3718let TAG_DEFINITIONS;
3719
3720function getHtmlTagDefinition(tagName) {
3721  if (!TAG_DEFINITIONS) {
3722    _DEFAULT_TAG_DEFINITION = new HtmlTagDefinition();
3723    TAG_DEFINITIONS = {
3724      'base': new HtmlTagDefinition({
3725        isVoid: true
3726      }),
3727      'meta': new HtmlTagDefinition({
3728        isVoid: true
3729      }),
3730      'area': new HtmlTagDefinition({
3731        isVoid: true
3732      }),
3733      'embed': new HtmlTagDefinition({
3734        isVoid: true
3735      }),
3736      'link': new HtmlTagDefinition({
3737        isVoid: true
3738      }),
3739      'img': new HtmlTagDefinition({
3740        isVoid: true
3741      }),
3742      'input': new HtmlTagDefinition({
3743        isVoid: true
3744      }),
3745      'param': new HtmlTagDefinition({
3746        isVoid: true
3747      }),
3748      'hr': new HtmlTagDefinition({
3749        isVoid: true
3750      }),
3751      'br': new HtmlTagDefinition({
3752        isVoid: true
3753      }),
3754      'source': new HtmlTagDefinition({
3755        isVoid: true
3756      }),
3757      'track': new HtmlTagDefinition({
3758        isVoid: true
3759      }),
3760      'wbr': new HtmlTagDefinition({
3761        isVoid: true
3762      }),
3763      'p': new HtmlTagDefinition({
3764        closedByChildren: ['address', 'article', 'aside', 'blockquote', 'div', 'dl', 'fieldset', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'],
3765        closedByParent: true
3766      }),
3767      'thead': new HtmlTagDefinition({
3768        closedByChildren: ['tbody', 'tfoot']
3769      }),
3770      'tbody': new HtmlTagDefinition({
3771        closedByChildren: ['tbody', 'tfoot'],
3772        closedByParent: true
3773      }),
3774      'tfoot': new HtmlTagDefinition({
3775        closedByChildren: ['tbody'],
3776        closedByParent: true
3777      }),
3778      'tr': new HtmlTagDefinition({
3779        closedByChildren: ['tr'],
3780        closedByParent: true
3781      }),
3782      'td': new HtmlTagDefinition({
3783        closedByChildren: ['td', 'th'],
3784        closedByParent: true
3785      }),
3786      'th': new HtmlTagDefinition({
3787        closedByChildren: ['td', 'th'],
3788        closedByParent: true
3789      }),
3790      'col': new HtmlTagDefinition({
3791        isVoid: true
3792      }),
3793      'svg': new HtmlTagDefinition({
3794        implicitNamespacePrefix: 'svg'
3795      }),
3796      'foreignObject': new HtmlTagDefinition({
3797        // Usually the implicit namespace here would be redundant since it will be inherited from
3798        // the parent `svg`, but we have to do it for `foreignObject`, because the way the parser
3799        // works is that the parent node of an end tag is its own start tag which means that
3800        // the `preventNamespaceInheritance` on `foreignObject` would have it default to the
3801        // implicit namespace which is `html`, unless specified otherwise.
3802        implicitNamespacePrefix: 'svg',
3803        // We want to prevent children of foreignObject from inheriting its namespace, because
3804        // the point of the element is to allow nodes from other namespaces to be inserted.
3805        preventNamespaceInheritance: true
3806      }),
3807      'math': new HtmlTagDefinition({
3808        implicitNamespacePrefix: 'math'
3809      }),
3810      'li': new HtmlTagDefinition({
3811        closedByChildren: ['li'],
3812        closedByParent: true
3813      }),
3814      'dt': new HtmlTagDefinition({
3815        closedByChildren: ['dt', 'dd']
3816      }),
3817      'dd': new HtmlTagDefinition({
3818        closedByChildren: ['dt', 'dd'],
3819        closedByParent: true
3820      }),
3821      'rb': new HtmlTagDefinition({
3822        closedByChildren: ['rb', 'rt', 'rtc', 'rp'],
3823        closedByParent: true
3824      }),
3825      'rt': new HtmlTagDefinition({
3826        closedByChildren: ['rb', 'rt', 'rtc', 'rp'],
3827        closedByParent: true
3828      }),
3829      'rtc': new HtmlTagDefinition({
3830        closedByChildren: ['rb', 'rtc', 'rp'],
3831        closedByParent: true
3832      }),
3833      'rp': new HtmlTagDefinition({
3834        closedByChildren: ['rb', 'rt', 'rtc', 'rp'],
3835        closedByParent: true
3836      }),
3837      'optgroup': new HtmlTagDefinition({
3838        closedByChildren: ['optgroup'],
3839        closedByParent: true
3840      }),
3841      'option': new HtmlTagDefinition({
3842        closedByChildren: ['option', 'optgroup'],
3843        closedByParent: true
3844      }),
3845      'pre': new HtmlTagDefinition({
3846        ignoreFirstLf: true
3847      }),
3848      'listing': new HtmlTagDefinition({
3849        ignoreFirstLf: true
3850      }),
3851      'style': new HtmlTagDefinition({
3852        contentType: TagContentType.RAW_TEXT
3853      }),
3854      'script': new HtmlTagDefinition({
3855        contentType: TagContentType.RAW_TEXT
3856      }),
3857      'title': new HtmlTagDefinition({
3858        // The browser supports two separate `title` tags which have to use
3859        // a different content type: `HTMLTitleElement` and `SVGTitleElement`
3860        contentType: {
3861          default: TagContentType.ESCAPABLE_RAW_TEXT,
3862          svg: TagContentType.PARSABLE_DATA
3863        }
3864      }),
3865      'textarea': new HtmlTagDefinition({
3866        contentType: TagContentType.ESCAPABLE_RAW_TEXT,
3867        ignoreFirstLf: true
3868      })
3869    };
3870  } // We have to make both a case-sensitive and a case-insensitive lookup, because
3871  // HTML tag names are case insensitive, whereas some SVG tags are case sensitive.
3872
3873
3874  return TAG_DEFINITIONS[tagName] ?? TAG_DEFINITIONS[tagName.toLowerCase()] ?? _DEFAULT_TAG_DEFINITION;
3875}
3876/**
3877 * @license
3878 * Copyright Google LLC All Rights Reserved.
3879 *
3880 * Use of this source code is governed by an MIT-style license that can be
3881 * found in the LICENSE file at https://angular.io/license
3882 */
3883
3884
3885const _SELECTOR_REGEXP = new RegExp('(\\:not\\()|' + // 1: ":not("
3886'(([\\.\\#]?)[-\\w]+)|' + // 2: "tag"; 3: "."/"#";
3887// "-" should appear first in the regexp below as FF31 parses "[.-\w]" as a range
3888// 4: attribute; 5: attribute_string; 6: attribute_value
3889'(?:\\[([-.\\w*\\\\$]+)(?:=([\"\']?)([^\\]\"\']*)\\5)?\\])|' + // "[name]", "[name=value]",
3890// "[name="value"]",
3891// "[name='value']"
3892'(\\))|' + // 7: ")"
3893'(\\s*,\\s*)', // 8: ","
3894'g');
3895/**
3896 * A css selector contains an element name,
3897 * css classes and attribute/value pairs with the purpose
3898 * of selecting subsets out of them.
3899 */
3900
3901
3902class CssSelector {
3903  constructor() {
3904    this.element = null;
3905    this.classNames = [];
3906    /**
3907     * The selectors are encoded in pairs where:
3908     * - even locations are attribute names
3909     * - odd locations are attribute values.
3910     *
3911     * Example:
3912     * Selector: `[key1=value1][key2]` would parse to:
3913     * ```
3914     * ['key1', 'value1', 'key2', '']
3915     * ```
3916     */
3917
3918    this.attrs = [];
3919    this.notSelectors = [];
3920  }
3921
3922  static parse(selector) {
3923    const results = [];
3924
3925    const _addResult = (res, cssSel) => {
3926      if (cssSel.notSelectors.length > 0 && !cssSel.element && cssSel.classNames.length == 0 && cssSel.attrs.length == 0) {
3927        cssSel.element = '*';
3928      }
3929
3930      res.push(cssSel);
3931    };
3932
3933    let cssSelector = new CssSelector();
3934    let match;
3935    let current = cssSelector;
3936    let inNot = false;
3937    _SELECTOR_REGEXP.lastIndex = 0;
3938
3939    while (match = _SELECTOR_REGEXP.exec(selector)) {
3940      if (match[1
3941      /* SelectorRegexp.NOT */
3942      ]) {
3943        if (inNot) {
3944          throw new Error('Nesting :not in a selector is not allowed');
3945        }
3946
3947        inNot = true;
3948        current = new CssSelector();
3949        cssSelector.notSelectors.push(current);
3950      }
3951
3952      const tag = match[2
3953      /* SelectorRegexp.TAG */
3954      ];
3955
3956      if (tag) {
3957        const prefix = match[3
3958        /* SelectorRegexp.PREFIX */
3959        ];
3960
3961        if (prefix === '#') {
3962          // #hash
3963          current.addAttribute('id', tag.slice(1));
3964        } else if (prefix === '.') {
3965          // Class
3966          current.addClassName(tag.slice(1));
3967        } else {
3968          // Element
3969          current.setElement(tag);
3970        }
3971      }
3972
3973      const attribute = match[4
3974      /* SelectorRegexp.ATTRIBUTE */
3975      ];
3976
3977      if (attribute) {
3978        current.addAttribute(current.unescapeAttribute(attribute), match[6
3979        /* SelectorRegexp.ATTRIBUTE_VALUE */
3980        ]);
3981      }
3982
3983      if (match[7
3984      /* SelectorRegexp.NOT_END */
3985      ]) {
3986        inNot = false;
3987        current = cssSelector;
3988      }
3989
3990      if (match[8
3991      /* SelectorRegexp.SEPARATOR */
3992      ]) {
3993        if (inNot) {
3994          throw new Error('Multiple selectors in :not are not supported');
3995        }
3996
3997        _addResult(results, cssSelector);
3998
3999        cssSelector = current = new CssSelector();
4000      }
4001    }
4002
4003    _addResult(results, cssSelector);
4004
4005    return results;
4006  }
4007  /**
4008   * Unescape `\$` sequences from the CSS attribute selector.
4009   *
4010   * This is needed because `$` can have a special meaning in CSS selectors,
4011   * but we might want to match an attribute that contains `$`.
4012   * [MDN web link for more
4013   * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
4014   * @param attr the attribute to unescape.
4015   * @returns the unescaped string.
4016   */
4017
4018
4019  unescapeAttribute(attr) {
4020    let result = '';
4021    let escaping = false;
4022
4023    for (let i = 0; i < attr.length; i++) {
4024      const char = attr.charAt(i);
4025
4026      if (char === '\\') {
4027        escaping = true;
4028        continue;
4029      }
4030
4031      if (char === '$' && !escaping) {
4032        throw new Error(`Error in attribute selector "${attr}". ` + `Unescaped "$" is not supported. Please escape with "\\$".`);
4033      }
4034
4035      escaping = false;
4036      result += char;
4037    }
4038
4039    return result;
4040  }
4041  /**
4042   * Escape `$` sequences from the CSS attribute selector.
4043   *
4044   * This is needed because `$` can have a special meaning in CSS selectors,
4045   * with this method we are escaping `$` with `\$'.
4046   * [MDN web link for more
4047   * info](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors).
4048   * @param attr the attribute to escape.
4049   * @returns the escaped string.
4050   */
4051
4052
4053  escapeAttribute(attr) {
4054    return attr.replace(/\\/g, '\\\\').replace(/\$/g, '\\$');
4055  }
4056
4057  isElementSelector() {
4058    return this.hasElementSelector() && this.classNames.length == 0 && this.attrs.length == 0 && this.notSelectors.length === 0;
4059  }
4060
4061  hasElementSelector() {
4062    return !!this.element;
4063  }
4064
4065  setElement(element = null) {
4066    this.element = element;
4067  }
4068  /** Gets a template string for an element that matches the selector. */
4069
4070
4071  getMatchingElementTemplate() {
4072    const tagName = this.element || 'div';
4073    const classAttr = this.classNames.length > 0 ? ` class="${this.classNames.join(' ')}"` : '';
4074    let attrs = '';
4075
4076    for (let i = 0; i < this.attrs.length; i += 2) {
4077      const attrName = this.attrs[i];
4078      const attrValue = this.attrs[i + 1] !== '' ? `="${this.attrs[i + 1]}"` : '';
4079      attrs += ` ${attrName}${attrValue}`;
4080    }
4081
4082    return getHtmlTagDefinition(tagName).isVoid ? `<${tagName}${classAttr}${attrs}/>` : `<${tagName}${classAttr}${attrs}></${tagName}>`;
4083  }
4084
4085  getAttrs() {
4086    const result = [];
4087
4088    if (this.classNames.length > 0) {
4089      result.push('class', this.classNames.join(' '));
4090    }
4091
4092    return result.concat(this.attrs);
4093  }
4094
4095  addAttribute(name, value = '') {
4096    this.attrs.push(name, value && value.toLowerCase() || '');
4097  }
4098
4099  addClassName(name) {
4100    this.classNames.push(name.toLowerCase());
4101  }
4102
4103  toString() {
4104    let res = this.element || '';
4105
4106    if (this.classNames) {
4107      this.classNames.forEach(klass => res += `.${klass}`);
4108    }
4109
4110    if (this.attrs) {
4111      for (let i = 0; i < this.attrs.length; i += 2) {
4112        const name = this.escapeAttribute(this.attrs[i]);
4113        const value = this.attrs[i + 1];
4114        res += `[${name}${value ? '=' + value : ''}]`;
4115      }
4116    }
4117
4118    this.notSelectors.forEach(notSelector => res += `:not(${notSelector})`);
4119    return res;
4120  }
4121
4122}
4123/**
4124 * Reads a list of CssSelectors and allows to calculate which ones
4125 * are contained in a given CssSelector.
4126 */
4127
4128
4129class SelectorMatcher {
4130  constructor() {
4131    this._elementMap = new Map();
4132    this._elementPartialMap = new Map();
4133    this._classMap = new Map();
4134    this._classPartialMap = new Map();
4135    this._attrValueMap = new Map();
4136    this._attrValuePartialMap = new Map();
4137    this._listContexts = [];
4138  }
4139
4140  static createNotMatcher(notSelectors) {
4141    const notMatcher = new SelectorMatcher();
4142    notMatcher.addSelectables(notSelectors, null);
4143    return notMatcher;
4144  }
4145
4146  addSelectables(cssSelectors, callbackCtxt) {
4147    let listContext = null;
4148
4149    if (cssSelectors.length > 1) {
4150      listContext = new SelectorListContext(cssSelectors);
4151
4152      this._listContexts.push(listContext);
4153    }
4154
4155    for (let i = 0; i < cssSelectors.length; i++) {
4156      this._addSelectable(cssSelectors[i], callbackCtxt, listContext);
4157    }
4158  }
4159  /**
4160   * Add an object that can be found later on by calling `match`.
4161   * @param cssSelector A css selector
4162   * @param callbackCtxt An opaque object that will be given to the callback of the `match` function
4163   */
4164
4165
4166  _addSelectable(cssSelector, callbackCtxt, listContext) {
4167    let matcher = this;
4168    const element = cssSelector.element;
4169    const classNames = cssSelector.classNames;
4170    const attrs = cssSelector.attrs;
4171    const selectable = new SelectorContext(cssSelector, callbackCtxt, listContext);
4172
4173    if (element) {
4174      const isTerminal = attrs.length === 0 && classNames.length === 0;
4175
4176      if (isTerminal) {
4177        this._addTerminal(matcher._elementMap, element, selectable);
4178      } else {
4179        matcher = this._addPartial(matcher._elementPartialMap, element);
4180      }
4181    }
4182
4183    if (classNames) {
4184      for (let i = 0; i < classNames.length; i++) {
4185        const isTerminal = attrs.length === 0 && i === classNames.length - 1;
4186        const className = classNames[i];
4187
4188        if (isTerminal) {
4189          this._addTerminal(matcher._classMap, className, selectable);
4190        } else {
4191          matcher = this._addPartial(matcher._classPartialMap, className);
4192        }
4193      }
4194    }
4195
4196    if (attrs) {
4197      for (let i = 0; i < attrs.length; i += 2) {
4198        const isTerminal = i === attrs.length - 2;
4199        const name = attrs[i];
4200        const value = attrs[i + 1];
4201
4202        if (isTerminal) {
4203          const terminalMap = matcher._attrValueMap;
4204          let terminalValuesMap = terminalMap.get(name);
4205
4206          if (!terminalValuesMap) {
4207            terminalValuesMap = new Map();
4208            terminalMap.set(name, terminalValuesMap);
4209          }
4210
4211          this._addTerminal(terminalValuesMap, value, selectable);
4212        } else {
4213          const partialMap = matcher._attrValuePartialMap;
4214          let partialValuesMap = partialMap.get(name);
4215
4216          if (!partialValuesMap) {
4217            partialValuesMap = new Map();
4218            partialMap.set(name, partialValuesMap);
4219          }
4220
4221          matcher = this._addPartial(partialValuesMap, value);
4222        }
4223      }
4224    }
4225  }
4226
4227  _addTerminal(map, name, selectable) {
4228    let terminalList = map.get(name);
4229
4230    if (!terminalList) {
4231      terminalList = [];
4232      map.set(name, terminalList);
4233    }
4234
4235    terminalList.push(selectable);
4236  }
4237
4238  _addPartial(map, name) {
4239    let matcher = map.get(name);
4240
4241    if (!matcher) {
4242      matcher = new SelectorMatcher();
4243      map.set(name, matcher);
4244    }
4245
4246    return matcher;
4247  }
4248  /**
4249   * Find the objects that have been added via `addSelectable`
4250   * whose css selector is contained in the given css selector.
4251   * @param cssSelector A css selector
4252   * @param matchedCallback This callback will be called with the object handed into `addSelectable`
4253   * @return boolean true if a match was found
4254   */
4255
4256
4257  match(cssSelector, matchedCallback) {
4258    let result = false;
4259    const element = cssSelector.element;
4260    const classNames = cssSelector.classNames;
4261    const attrs = cssSelector.attrs;
4262
4263    for (let i = 0; i < this._listContexts.length; i++) {
4264      this._listContexts[i].alreadyMatched = false;
4265    }
4266
4267    result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
4268    result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) || result;
4269
4270    if (classNames) {
4271      for (let i = 0; i < classNames.length; i++) {
4272        const className = classNames[i];
4273        result = this._matchTerminal(this._classMap, className, cssSelector, matchedCallback) || result;
4274        result = this._matchPartial(this._classPartialMap, className, cssSelector, matchedCallback) || result;
4275      }
4276    }
4277
4278    if (attrs) {
4279      for (let i = 0; i < attrs.length; i += 2) {
4280        const name = attrs[i];
4281        const value = attrs[i + 1];
4282
4283        const terminalValuesMap = this._attrValueMap.get(name);
4284
4285        if (value) {
4286          result = this._matchTerminal(terminalValuesMap, '', cssSelector, matchedCallback) || result;
4287        }
4288
4289        result = this._matchTerminal(terminalValuesMap, value, cssSelector, matchedCallback) || result;
4290
4291        const partialValuesMap = this._attrValuePartialMap.get(name);
4292
4293        if (value) {
4294          result = this._matchPartial(partialValuesMap, '', cssSelector, matchedCallback) || result;
4295        }
4296
4297        result = this._matchPartial(partialValuesMap, value, cssSelector, matchedCallback) || result;
4298      }
4299    }
4300
4301    return result;
4302  }
4303  /** @internal */
4304
4305
4306  _matchTerminal(map, name, cssSelector, matchedCallback) {
4307    if (!map || typeof name !== 'string') {
4308      return false;
4309    }
4310
4311    let selectables = map.get(name) || [];
4312    const starSelectables = map.get('*');
4313
4314    if (starSelectables) {
4315      selectables = selectables.concat(starSelectables);
4316    }
4317
4318    if (selectables.length === 0) {
4319      return false;
4320    }
4321
4322    let selectable;
4323    let result = false;
4324
4325    for (let i = 0; i < selectables.length; i++) {
4326      selectable = selectables[i];
4327      result = selectable.finalize(cssSelector, matchedCallback) || result;
4328    }
4329
4330    return result;
4331  }
4332  /** @internal */
4333
4334
4335  _matchPartial(map, name, cssSelector, matchedCallback) {
4336    if (!map || typeof name !== 'string') {
4337      return false;
4338    }
4339
4340    const nestedSelector = map.get(name);
4341
4342    if (!nestedSelector) {
4343      return false;
4344    } // TODO(perf): get rid of recursion and measure again
4345    // TODO(perf): don't pass the whole selector into the recursion,
4346    // but only the not processed parts
4347
4348
4349    return nestedSelector.match(cssSelector, matchedCallback);
4350  }
4351
4352}
4353
4354class SelectorListContext {
4355  constructor(selectors) {
4356    this.selectors = selectors;
4357    this.alreadyMatched = false;
4358  }
4359
4360} // Store context to pass back selector and context when a selector is matched
4361
4362
4363class SelectorContext {
4364  constructor(selector, cbContext, listContext) {
4365    this.selector = selector;
4366    this.cbContext = cbContext;
4367    this.listContext = listContext;
4368    this.notSelectors = selector.notSelectors;
4369  }
4370
4371  finalize(cssSelector, callback) {
4372    let result = true;
4373
4374    if (this.notSelectors.length > 0 && (!this.listContext || !this.listContext.alreadyMatched)) {
4375      const notMatcher = SelectorMatcher.createNotMatcher(this.notSelectors);
4376      result = !notMatcher.match(cssSelector, null);
4377    }
4378
4379    if (result && callback && (!this.listContext || !this.listContext.alreadyMatched)) {
4380      if (this.listContext) {
4381        this.listContext.alreadyMatched = true;
4382      }
4383
4384      callback(this.selector, this.cbContext);
4385    }
4386
4387    return result;
4388  }
4389
4390}
4391/**
4392 * @license
4393 * Copyright Google LLC All Rights Reserved.
4394 *
4395 * Use of this source code is governed by an MIT-style license that can be
4396 * found in the LICENSE file at https://angular.io/license
4397 */
4398// Stores the default value of `emitDistinctChangesOnly` when the `emitDistinctChangesOnly` is not
4399// explicitly set.
4400
4401
4402const emitDistinctChangesOnlyDefaultValue = true;
4403var ViewEncapsulation;
4404
4405(function (ViewEncapsulation) {
4406  ViewEncapsulation[ViewEncapsulation["Emulated"] = 0] = "Emulated"; // Historically the 1 value was for `Native` encapsulation which has been removed as of v11.
4407
4408  ViewEncapsulation[ViewEncapsulation["None"] = 2] = "None";
4409  ViewEncapsulation[ViewEncapsulation["ShadowDom"] = 3] = "ShadowDom";
4410})(ViewEncapsulation || (ViewEncapsulation = {}));
4411
4412var ChangeDetectionStrategy;
4413
4414(function (ChangeDetectionStrategy) {
4415  ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
4416  ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
4417})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
4418
4419const CUSTOM_ELEMENTS_SCHEMA = {
4420  name: 'custom-elements'
4421};
4422const NO_ERRORS_SCHEMA = {
4423  name: 'no-errors-schema'
4424};
4425const Type$1 = Function;
4426var SecurityContext;
4427
4428(function (SecurityContext) {
4429  SecurityContext[SecurityContext["NONE"] = 0] = "NONE";
4430  SecurityContext[SecurityContext["HTML"] = 1] = "HTML";
4431  SecurityContext[SecurityContext["STYLE"] = 2] = "STYLE";
4432  SecurityContext[SecurityContext["SCRIPT"] = 3] = "SCRIPT";
4433  SecurityContext[SecurityContext["URL"] = 4] = "URL";
4434  SecurityContext[SecurityContext["RESOURCE_URL"] = 5] = "RESOURCE_URL";
4435})(SecurityContext || (SecurityContext = {}));
4436
4437var MissingTranslationStrategy;
4438
4439(function (MissingTranslationStrategy) {
4440  MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
4441  MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
4442  MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
4443})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
4444
4445function parserSelectorToSimpleSelector(selector) {
4446  const classes = selector.classNames && selector.classNames.length ? [8
4447  /* SelectorFlags.CLASS */
4448  , ...selector.classNames] : [];
4449  const elementName = selector.element && selector.element !== '*' ? selector.element : '';
4450  return [elementName, ...selector.attrs, ...classes];
4451}
4452
4453function parserSelectorToNegativeSelector(selector) {
4454  const classes = selector.classNames && selector.classNames.length ? [8
4455  /* SelectorFlags.CLASS */
4456  , ...selector.classNames] : [];
4457
4458  if (selector.element) {
4459    return [1
4460    /* SelectorFlags.NOT */
4461    | 4
4462    /* SelectorFlags.ELEMENT */
4463    , selector.element, ...selector.attrs, ...classes];
4464  } else if (selector.attrs.length) {
4465    return [1
4466    /* SelectorFlags.NOT */
4467    | 2
4468    /* SelectorFlags.ATTRIBUTE */
4469    , ...selector.attrs, ...classes];
4470  } else {
4471    return selector.classNames && selector.classNames.length ? [1
4472    /* SelectorFlags.NOT */
4473    | 8
4474    /* SelectorFlags.CLASS */
4475    , ...selector.classNames] : [];
4476  }
4477}
4478
4479function parserSelectorToR3Selector(selector) {
4480  const positive = parserSelectorToSimpleSelector(selector);
4481  const negative = selector.notSelectors && selector.notSelectors.length ? selector.notSelectors.map(notSelector => parserSelectorToNegativeSelector(notSelector)) : [];
4482  return positive.concat(...negative);
4483}
4484
4485function parseSelectorToR3Selector(selector) {
4486  return selector ? CssSelector.parse(selector).map(parserSelectorToR3Selector) : [];
4487}
4488
4489var core = /*#__PURE__*/Object.freeze({
4490  __proto__: null,
4491  emitDistinctChangesOnlyDefaultValue: emitDistinctChangesOnlyDefaultValue,
4492
4493  get ViewEncapsulation() {
4494    return ViewEncapsulation;
4495  },
4496
4497  get ChangeDetectionStrategy() {
4498    return ChangeDetectionStrategy;
4499  },
4500
4501  CUSTOM_ELEMENTS_SCHEMA: CUSTOM_ELEMENTS_SCHEMA,
4502  NO_ERRORS_SCHEMA: NO_ERRORS_SCHEMA,
4503  Type: Type$1,
4504
4505  get SecurityContext() {
4506    return SecurityContext;
4507  },
4508
4509  get MissingTranslationStrategy() {
4510    return MissingTranslationStrategy;
4511  },
4512
4513  parseSelectorToR3Selector: parseSelectorToR3Selector
4514});
4515/**
4516 * @license
4517 * Copyright Google LLC All Rights Reserved.
4518 *
4519 * Use of this source code is governed by an MIT-style license that can be
4520 * found in the LICENSE file at https://angular.io/license
4521 */
4522
4523const DASH_CASE_REGEXP = /-+([a-z0-9])/g;
4524
4525function dashCaseToCamelCase(input) {
4526  return input.replace(DASH_CASE_REGEXP, (...m) => m[1].toUpperCase());
4527}
4528
4529function splitAtColon(input, defaultValues) {
4530  return _splitAt(input, ':', defaultValues);
4531}
4532
4533function splitAtPeriod(input, defaultValues) {
4534  return _splitAt(input, '.', defaultValues);
4535}
4536
4537function _splitAt(input, character, defaultValues) {
4538  const characterIndex = input.indexOf(character);
4539  if (characterIndex == -1) return defaultValues;
4540  return [input.slice(0, characterIndex).trim(), input.slice(characterIndex + 1).trim()];
4541}
4542
4543function noUndefined(val) {
4544  return val === undefined ? null : val;
4545}
4546
4547function error(msg) {
4548  throw new Error(`Internal Error: ${msg}`);
4549} // Escape characters that have a special meaning in Regular Expressions
4550
4551
4552function escapeRegExp(s) {
4553  return s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
4554}
4555
4556function utf8Encode(str) {
4557  let encoded = [];
4558
4559  for (let index = 0; index < str.length; index++) {
4560    let codePoint = str.charCodeAt(index); // decode surrogate
4561    // see https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
4562
4563    if (codePoint >= 0xd800 && codePoint <= 0xdbff && str.length > index + 1) {
4564      const low = str.charCodeAt(index + 1);
4565
4566      if (low >= 0xdc00 && low <= 0xdfff) {
4567        index++;
4568        codePoint = (codePoint - 0xd800 << 10) + low - 0xdc00 + 0x10000;
4569      }
4570    }
4571
4572    if (codePoint <= 0x7f) {
4573      encoded.push(codePoint);
4574    } else if (codePoint <= 0x7ff) {
4575      encoded.push(codePoint >> 6 & 0x1F | 0xc0, codePoint & 0x3f | 0x80);
4576    } else if (codePoint <= 0xffff) {
4577      encoded.push(codePoint >> 12 | 0xe0, codePoint >> 6 & 0x3f | 0x80, codePoint & 0x3f | 0x80);
4578    } else if (codePoint <= 0x1fffff) {
4579      encoded.push(codePoint >> 18 & 0x07 | 0xf0, codePoint >> 12 & 0x3f | 0x80, codePoint >> 6 & 0x3f | 0x80, codePoint & 0x3f | 0x80);
4580    }
4581  }
4582
4583  return encoded;
4584}
4585
4586function stringify(token) {
4587  if (typeof token === 'string') {
4588    return token;
4589  }
4590
4591  if (Array.isArray(token)) {
4592    return '[' + token.map(stringify).join(', ') + ']';
4593  }
4594
4595  if (token == null) {
4596    return '' + token;
4597  }
4598
4599  if (token.overriddenName) {
4600    return `${token.overriddenName}`;
4601  }
4602
4603  if (token.name) {
4604    return `${token.name}`;
4605  }
4606
4607  if (!token.toString) {
4608    return 'object';
4609  } // WARNING: do not try to `JSON.stringify(token)` here
4610  // see https://github.com/angular/angular/issues/23440
4611
4612
4613  const res = token.toString();
4614
4615  if (res == null) {
4616    return '' + res;
4617  }
4618
4619  const newLineIndex = res.indexOf('\n');
4620  return newLineIndex === -1 ? res : res.substring(0, newLineIndex);
4621}
4622
4623class Version {
4624  constructor(full) {
4625    this.full = full;
4626    const splits = full.split('.');
4627    this.major = splits[0];
4628    this.minor = splits[1];
4629    this.patch = splits.slice(2).join('.');
4630  }
4631
4632} // Check `global` first, because in Node tests both `global` and `window` may be defined and our
4633// `_global` variable should point to the NodeJS `global` in that case. Note: Typeof/Instanceof
4634// checks are considered side-effects in Terser. We explicitly mark this as side-effect free:
4635// https://github.com/terser/terser/issues/250.
4636
4637
4638const _global = /* @__PURE__ */(() => typeof global !== 'undefined' && global || typeof window !== 'undefined' && window || typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope && self)();
4639
4640function newArray(size, value) {
4641  const list = [];
4642
4643  for (let i = 0; i < size; i++) {
4644    list.push(value);
4645  }
4646
4647  return list;
4648}
4649/**
4650 * Partitions a given array into 2 arrays, based on a boolean value returned by the condition
4651 * function.
4652 *
4653 * @param arr Input array that should be partitioned
4654 * @param conditionFn Condition function that is called for each item in a given array and returns a
4655 * boolean value.
4656 */
4657
4658
4659function partitionArray(arr, conditionFn) {
4660  const truthy = [];
4661  const falsy = [];
4662
4663  for (const item of arr) {
4664    (conditionFn(item) ? truthy : falsy).push(item);
4665  }
4666
4667  return [truthy, falsy];
4668}
4669/**
4670 * @license
4671 * Copyright Google LLC All Rights Reserved.
4672 *
4673 * Use of this source code is governed by an MIT-style license that can be
4674 * found in the LICENSE file at https://angular.io/license
4675 */
4676
4677/**
4678 * Represents a big integer using a buffer of its individual digits, with the least significant
4679 * digit stored at the beginning of the array (little endian).
4680 *
4681 * For performance reasons, each instance is mutable. The addition operation can be done in-place
4682 * to reduce memory pressure of allocation for the digits array.
4683 */
4684
4685
4686class BigInteger {
4687  /**
4688   * Creates a big integer using its individual digits in little endian storage.
4689   */
4690  constructor(digits) {
4691    this.digits = digits;
4692  }
4693
4694  static zero() {
4695    return new BigInteger([0]);
4696  }
4697
4698  static one() {
4699    return new BigInteger([1]);
4700  }
4701  /**
4702   * Creates a clone of this instance.
4703   */
4704
4705
4706  clone() {
4707    return new BigInteger(this.digits.slice());
4708  }
4709  /**
4710   * Returns a new big integer with the sum of `this` and `other` as its value. This does not mutate
4711   * `this` but instead returns a new instance, unlike `addToSelf`.
4712   */
4713
4714
4715  add(other) {
4716    const result = this.clone();
4717    result.addToSelf(other);
4718    return result;
4719  }
4720  /**
4721   * Adds `other` to the instance itself, thereby mutating its value.
4722   */
4723
4724
4725  addToSelf(other) {
4726    const maxNrOfDigits = Math.max(this.digits.length, other.digits.length);
4727    let carry = 0;
4728
4729    for (let i = 0; i < maxNrOfDigits; i++) {
4730      let digitSum = carry;
4731
4732      if (i < this.digits.length) {
4733        digitSum += this.digits[i];
4734      }
4735
4736      if (i < other.digits.length) {
4737        digitSum += other.digits[i];
4738      }
4739
4740      if (digitSum >= 10) {
4741        this.digits[i] = digitSum - 10;
4742        carry = 1;
4743      } else {
4744        this.digits[i] = digitSum;
4745        carry = 0;
4746      }
4747    } // Apply a remaining carry if needed.
4748
4749
4750    if (carry > 0) {
4751      this.digits[maxNrOfDigits] = 1;
4752    }
4753  }
4754  /**
4755   * Builds the decimal string representation of the big integer. As this is stored in
4756   * little endian, the digits are concatenated in reverse order.
4757   */
4758
4759
4760  toString() {
4761    let res = '';
4762
4763    for (let i = this.digits.length - 1; i >= 0; i--) {
4764      res += this.digits[i];
4765    }
4766
4767    return res;
4768  }
4769
4770}
4771/**
4772 * Represents a big integer which is optimized for multiplication operations, as its power-of-twos
4773 * are memoized. See `multiplyBy()` for details on the multiplication algorithm.
4774 */
4775
4776
4777class BigIntForMultiplication {
4778  constructor(value) {
4779    this.powerOfTwos = [value];
4780  }
4781  /**
4782   * Returns the big integer itself.
4783   */
4784
4785
4786  getValue() {
4787    return this.powerOfTwos[0];
4788  }
4789  /**
4790   * Computes the value for `num * b`, where `num` is a JS number and `b` is a big integer. The
4791   * value for `b` is represented by a storage model that is optimized for this computation.
4792   *
4793   * This operation is implemented in N(log2(num)) by continuous halving of the number, where the
4794   * least-significant bit (LSB) is tested in each iteration. If the bit is set, the bit's index is
4795   * used as exponent into the power-of-two multiplication of `b`.
4796   *
4797   * As an example, consider the multiplication num=42, b=1337. In binary 42 is 0b00101010 and the
4798   * algorithm unrolls into the following iterations:
4799   *
4800   *  Iteration | num        | LSB  | b * 2^iter | Add? | product
4801   * -----------|------------|------|------------|------|--------
4802   *  0         | 0b00101010 | 0    | 1337       | No   | 0
4803   *  1         | 0b00010101 | 1    | 2674       | Yes  | 2674
4804   *  2         | 0b00001010 | 0    | 5348       | No   | 2674
4805   *  3         | 0b00000101 | 1    | 10696      | Yes  | 13370
4806   *  4         | 0b00000010 | 0    | 21392      | No   | 13370
4807   *  5         | 0b00000001 | 1    | 42784      | Yes  | 56154
4808   *  6         | 0b00000000 | 0    | 85568      | No   | 56154
4809   *
4810   * The computed product of 56154 is indeed the correct result.
4811   *
4812   * The `BigIntForMultiplication` representation for a big integer provides memoized access to the
4813   * power-of-two values to reduce the workload in computing those values.
4814   */
4815
4816
4817  multiplyBy(num) {
4818    const product = BigInteger.zero();
4819    this.multiplyByAndAddTo(num, product);
4820    return product;
4821  }
4822  /**
4823   * See `multiplyBy()` for details. This function allows for the computed product to be added
4824   * directly to the provided result big integer.
4825   */
4826
4827
4828  multiplyByAndAddTo(num, result) {
4829    for (let exponent = 0; num !== 0; num = num >>> 1, exponent++) {
4830      if (num & 1) {
4831        const value = this.getMultipliedByPowerOfTwo(exponent);
4832        result.addToSelf(value);
4833      }
4834    }
4835  }
4836  /**
4837   * Computes and memoizes the big integer value for `this.number * 2^exponent`.
4838   */
4839
4840
4841  getMultipliedByPowerOfTwo(exponent) {
4842    // Compute the powers up until the requested exponent, where each value is computed from its
4843    // predecessor. This is simple as `this.number * 2^(exponent - 1)` only has to be doubled (i.e.
4844    // added to itself) to reach `this.number * 2^exponent`.
4845    for (let i = this.powerOfTwos.length; i <= exponent; i++) {
4846      const previousPower = this.powerOfTwos[i - 1];
4847      this.powerOfTwos[i] = previousPower.add(previousPower);
4848    }
4849
4850    return this.powerOfTwos[exponent];
4851  }
4852
4853}
4854/**
4855 * Represents an exponentiation operation for the provided base, of which exponents are computed and
4856 * memoized. The results are represented by a `BigIntForMultiplication` which is tailored for
4857 * multiplication operations by memoizing the power-of-twos. This effectively results in a matrix
4858 * representation that is lazily computed upon request.
4859 */
4860
4861
4862class BigIntExponentiation {
4863  constructor(base) {
4864    this.base = base;
4865    this.exponents = [new BigIntForMultiplication(BigInteger.one())];
4866  }
4867  /**
4868   * Compute the value for `this.base^exponent`, resulting in a big integer that is optimized for
4869   * further multiplication operations.
4870   */
4871
4872
4873  toThePowerOf(exponent) {
4874    // Compute the results up until the requested exponent, where every value is computed from its
4875    // predecessor. This is because `this.base^(exponent - 1)` only has to be multiplied by `base`
4876    // to reach `this.base^exponent`.
4877    for (let i = this.exponents.length; i <= exponent; i++) {
4878      const value = this.exponents[i - 1].multiplyBy(this.base);
4879      this.exponents[i] = new BigIntForMultiplication(value);
4880    }
4881
4882    return this.exponents[exponent];
4883  }
4884
4885}
4886/**
4887 * @license
4888 * Copyright Google LLC All Rights Reserved.
4889 *
4890 * Use of this source code is governed by an MIT-style license that can be
4891 * found in the LICENSE file at https://angular.io/license
4892 */
4893
4894/**
4895 * Return the message id or compute it using the XLIFF1 digest.
4896 */
4897
4898
4899function digest$1(message) {
4900  return message.id || computeDigest(message);
4901}
4902/**
4903 * Compute the message id using the XLIFF1 digest.
4904 */
4905
4906
4907function computeDigest(message) {
4908  return sha1(serializeNodes(message.nodes).join('') + `[${message.meaning}]`);
4909}
4910/**
4911 * Return the message id or compute it using the XLIFF2/XMB/$localize digest.
4912 */
4913
4914
4915function decimalDigest(message) {
4916  return message.id || computeDecimalDigest(message);
4917}
4918/**
4919 * Compute the message id using the XLIFF2/XMB/$localize digest.
4920 */
4921
4922
4923function computeDecimalDigest(message) {
4924  const visitor = new _SerializerIgnoreIcuExpVisitor();
4925  const parts = message.nodes.map(a => a.visit(visitor, null));
4926  return computeMsgId(parts.join(''), message.meaning);
4927}
4928/**
4929 * Serialize the i18n ast to something xml-like in order to generate an UID.
4930 *
4931 * The visitor is also used in the i18n parser tests
4932 *
4933 * @internal
4934 */
4935
4936
4937class _SerializerVisitor {
4938  visitText(text, context) {
4939    return text.value;
4940  }
4941
4942  visitContainer(container, context) {
4943    return `[${container.children.map(child => child.visit(this)).join(', ')}]`;
4944  }
4945
4946  visitIcu(icu, context) {
4947    const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
4948    return `{${icu.expression}, ${icu.type}, ${strCases.join(', ')}}`;
4949  }
4950
4951  visitTagPlaceholder(ph, context) {
4952    return ph.isVoid ? `<ph tag name="${ph.startName}"/>` : `<ph tag name="${ph.startName}">${ph.children.map(child => child.visit(this)).join(', ')}</ph name="${ph.closeName}">`;
4953  }
4954
4955  visitPlaceholder(ph, context) {
4956    return ph.value ? `<ph name="${ph.name}">${ph.value}</ph>` : `<ph name="${ph.name}"/>`;
4957  }
4958
4959  visitIcuPlaceholder(ph, context) {
4960    return `<ph icu name="${ph.name}">${ph.value.visit(this)}</ph>`;
4961  }
4962
4963}
4964
4965const serializerVisitor$1 = new _SerializerVisitor();
4966
4967function serializeNodes(nodes) {
4968  return nodes.map(a => a.visit(serializerVisitor$1, null));
4969}
4970/**
4971 * Serialize the i18n ast to something xml-like in order to generate an UID.
4972 *
4973 * Ignore the ICU expressions so that message IDs stays identical if only the expression changes.
4974 *
4975 * @internal
4976 */
4977
4978
4979class _SerializerIgnoreIcuExpVisitor extends _SerializerVisitor {
4980  visitIcu(icu, context) {
4981    let strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); // Do not take the expression into account
4982
4983    return `{${icu.type}, ${strCases.join(', ')}}`;
4984  }
4985
4986}
4987/**
4988 * Compute the SHA1 of the given string
4989 *
4990 * see https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
4991 *
4992 * WARNING: this function has not been designed not tested with security in mind.
4993 *          DO NOT USE IT IN A SECURITY SENSITIVE CONTEXT.
4994 */
4995
4996
4997function sha1(str) {
4998  const utf8 = utf8Encode(str);
4999  const words32 = bytesToWords32(utf8, Endian.Big);
5000  const len = utf8.length * 8;
5001  const w = newArray(80);
5002  let a = 0x67452301,
5003      b = 0xefcdab89,
5004      c = 0x98badcfe,
5005      d = 0x10325476,
5006      e = 0xc3d2e1f0;
5007  words32[len >> 5] |= 0x80 << 24 - len % 32;
5008  words32[(len + 64 >> 9 << 4) + 15] = len;
5009
5010  for (let i = 0; i < words32.length; i += 16) {
5011    const h0 = a,
5012          h1 = b,
5013          h2 = c,
5014          h3 = d,
5015          h4 = e;
5016
5017    for (let j = 0; j < 80; j++) {
5018      if (j < 16) {
5019        w[j] = words32[i + j];
5020      } else {
5021        w[j] = rol32(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
5022      }
5023
5024      const fkVal = fk(j, b, c, d);
5025      const f = fkVal[0];
5026      const k = fkVal[1];
5027      const temp = [rol32(a, 5), f, e, k, w[j]].reduce(add32);
5028      e = d;
5029      d = c;
5030      c = rol32(b, 30);
5031      b = a;
5032      a = temp;
5033    }
5034
5035    a = add32(a, h0);
5036    b = add32(b, h1);
5037    c = add32(c, h2);
5038    d = add32(d, h3);
5039    e = add32(e, h4);
5040  }
5041
5042  return bytesToHexString(words32ToByteString([a, b, c, d, e]));
5043}
5044
5045function fk(index, b, c, d) {
5046  if (index < 20) {
5047    return [b & c | ~b & d, 0x5a827999];
5048  }
5049
5050  if (index < 40) {
5051    return [b ^ c ^ d, 0x6ed9eba1];
5052  }
5053
5054  if (index < 60) {
5055    return [b & c | b & d | c & d, 0x8f1bbcdc];
5056  }
5057
5058  return [b ^ c ^ d, 0xca62c1d6];
5059}
5060/**
5061 * Compute the fingerprint of the given string
5062 *
5063 * The output is 64 bit number encoded as a decimal string
5064 *
5065 * based on:
5066 * https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/GoogleJsMessageIdGenerator.java
5067 */
5068
5069
5070function fingerprint(str) {
5071  const utf8 = utf8Encode(str);
5072  let hi = hash32(utf8, 0);
5073  let lo = hash32(utf8, 102072);
5074
5075  if (hi == 0 && (lo == 0 || lo == 1)) {
5076    hi = hi ^ 0x130f9bef;
5077    lo = lo ^ -0x6b5f56d8;
5078  }
5079
5080  return [hi, lo];
5081}
5082
5083function computeMsgId(msg, meaning = '') {
5084  let msgFingerprint = fingerprint(msg);
5085
5086  if (meaning) {
5087    const meaningFingerprint = fingerprint(meaning);
5088    msgFingerprint = add64(rol64(msgFingerprint, 1), meaningFingerprint);
5089  }
5090
5091  const hi = msgFingerprint[0];
5092  const lo = msgFingerprint[1];
5093  return wordsToDecimalString(hi & 0x7fffffff, lo);
5094}
5095
5096function hash32(bytes, c) {
5097  let a = 0x9e3779b9,
5098      b = 0x9e3779b9;
5099  let i;
5100  const len = bytes.length;
5101
5102  for (i = 0; i + 12 <= len; i += 12) {
5103    a = add32(a, wordAt(bytes, i, Endian.Little));
5104    b = add32(b, wordAt(bytes, i + 4, Endian.Little));
5105    c = add32(c, wordAt(bytes, i + 8, Endian.Little));
5106    const res = mix(a, b, c);
5107    a = res[0], b = res[1], c = res[2];
5108  }
5109
5110  a = add32(a, wordAt(bytes, i, Endian.Little));
5111  b = add32(b, wordAt(bytes, i + 4, Endian.Little)); // the first byte of c is reserved for the length
5112
5113  c = add32(c, len);
5114  c = add32(c, wordAt(bytes, i + 8, Endian.Little) << 8);
5115  return mix(a, b, c)[2];
5116} // clang-format off
5117
5118
5119function mix(a, b, c) {
5120  a = sub32(a, b);
5121  a = sub32(a, c);
5122  a ^= c >>> 13;
5123  b = sub32(b, c);
5124  b = sub32(b, a);
5125  b ^= a << 8;
5126  c = sub32(c, a);
5127  c = sub32(c, b);
5128  c ^= b >>> 13;
5129  a = sub32(a, b);
5130  a = sub32(a, c);
5131  a ^= c >>> 12;
5132  b = sub32(b, c);
5133  b = sub32(b, a);
5134  b ^= a << 16;
5135  c = sub32(c, a);
5136  c = sub32(c, b);
5137  c ^= b >>> 5;
5138  a = sub32(a, b);
5139  a = sub32(a, c);
5140  a ^= c >>> 3;
5141  b = sub32(b, c);
5142  b = sub32(b, a);
5143  b ^= a << 10;
5144  c = sub32(c, a);
5145  c = sub32(c, b);
5146  c ^= b >>> 15;
5147  return [a, b, c];
5148} // clang-format on
5149// Utils
5150
5151
5152var Endian;
5153
5154(function (Endian) {
5155  Endian[Endian["Little"] = 0] = "Little";
5156  Endian[Endian["Big"] = 1] = "Big";
5157})(Endian || (Endian = {}));
5158
5159function add32(a, b) {
5160  return add32to64(a, b)[1];
5161}
5162
5163function add32to64(a, b) {
5164  const low = (a & 0xffff) + (b & 0xffff);
5165  const high = (a >>> 16) + (b >>> 16) + (low >>> 16);
5166  return [high >>> 16, high << 16 | low & 0xffff];
5167}
5168
5169function add64(a, b) {
5170  const ah = a[0],
5171        al = a[1];
5172  const bh = b[0],
5173        bl = b[1];
5174  const result = add32to64(al, bl);
5175  const carry = result[0];
5176  const l = result[1];
5177  const h = add32(add32(ah, bh), carry);
5178  return [h, l];
5179}
5180
5181function sub32(a, b) {
5182  const low = (a & 0xffff) - (b & 0xffff);
5183  const high = (a >> 16) - (b >> 16) + (low >> 16);
5184  return high << 16 | low & 0xffff;
5185} // Rotate a 32b number left `count` position
5186
5187
5188function rol32(a, count) {
5189  return a << count | a >>> 32 - count;
5190} // Rotate a 64b number left `count` position
5191
5192
5193function rol64(num, count) {
5194  const hi = num[0],
5195        lo = num[1];
5196  const h = hi << count | lo >>> 32 - count;
5197  const l = lo << count | hi >>> 32 - count;
5198  return [h, l];
5199}
5200
5201function bytesToWords32(bytes, endian) {
5202  const size = bytes.length + 3 >>> 2;
5203  const words32 = [];
5204
5205  for (let i = 0; i < size; i++) {
5206    words32[i] = wordAt(bytes, i * 4, endian);
5207  }
5208
5209  return words32;
5210}
5211
5212function byteAt(bytes, index) {
5213  return index >= bytes.length ? 0 : bytes[index];
5214}
5215
5216function wordAt(bytes, index, endian) {
5217  let word = 0;
5218
5219  if (endian === Endian.Big) {
5220    for (let i = 0; i < 4; i++) {
5221      word += byteAt(bytes, index + i) << 24 - 8 * i;
5222    }
5223  } else {
5224    for (let i = 0; i < 4; i++) {
5225      word += byteAt(bytes, index + i) << 8 * i;
5226    }
5227  }
5228
5229  return word;
5230}
5231
5232function words32ToByteString(words32) {
5233  return words32.reduce((bytes, word) => bytes.concat(word32ToByteString(word)), []);
5234}
5235
5236function word32ToByteString(word) {
5237  let bytes = [];
5238
5239  for (let i = 0; i < 4; i++) {
5240    bytes.push(word >>> 8 * (3 - i) & 0xff);
5241  }
5242
5243  return bytes;
5244}
5245
5246function bytesToHexString(bytes) {
5247  let hex = '';
5248
5249  for (let i = 0; i < bytes.length; i++) {
5250    const b = byteAt(bytes, i);
5251    hex += (b >>> 4).toString(16) + (b & 0x0f).toString(16);
5252  }
5253
5254  return hex.toLowerCase();
5255}
5256/**
5257 * Create a shared exponentiation pool for base-256 computations. This shared pool provides memoized
5258 * power-of-256 results with memoized power-of-two computations for efficient multiplication.
5259 *
5260 * For our purposes, this can be safely stored as a global without memory concerns. The reason is
5261 * that we encode two words, so only need the 0th (for the low word) and 4th (for the high word)
5262 * exponent.
5263 */
5264
5265
5266const base256 = new BigIntExponentiation(256);
5267/**
5268 * Represents two 32-bit words as a single decimal number. This requires a big integer storage
5269 * model as JS numbers are not accurate enough to represent the 64-bit number.
5270 *
5271 * Based on https://www.danvk.org/hex2dec.html
5272 */
5273
5274function wordsToDecimalString(hi, lo) {
5275  // Encode the four bytes in lo in the lower digits of the decimal number.
5276  // Note: the multiplication results in lo itself but represented by a big integer using its
5277  // decimal digits.
5278  const decimal = base256.toThePowerOf(0).multiplyBy(lo); // Encode the four bytes in hi above the four lo bytes. lo is a maximum of (2^8)^4, which is why
5279  // this multiplication factor is applied.
5280
5281  base256.toThePowerOf(4).multiplyByAndAddTo(hi, decimal);
5282  return decimal.toString();
5283}
5284/**
5285 * @license
5286 * Copyright Google LLC All Rights Reserved.
5287 *
5288 * Use of this source code is governed by an MIT-style license that can be
5289 * found in the LICENSE file at https://angular.io/license
5290 */
5291//// Types
5292
5293
5294var TypeModifier;
5295
5296(function (TypeModifier) {
5297  TypeModifier[TypeModifier["None"] = 0] = "None";
5298  TypeModifier[TypeModifier["Const"] = 1] = "Const";
5299})(TypeModifier || (TypeModifier = {}));
5300
5301class Type {
5302  constructor(modifiers = TypeModifier.None) {
5303    this.modifiers = modifiers;
5304  }
5305
5306  hasModifier(modifier) {
5307    return (this.modifiers & modifier) !== 0;
5308  }
5309
5310}
5311
5312var BuiltinTypeName;
5313
5314(function (BuiltinTypeName) {
5315  BuiltinTypeName[BuiltinTypeName["Dynamic"] = 0] = "Dynamic";
5316  BuiltinTypeName[BuiltinTypeName["Bool"] = 1] = "Bool";
5317  BuiltinTypeName[BuiltinTypeName["String"] = 2] = "String";
5318  BuiltinTypeName[BuiltinTypeName["Int"] = 3] = "Int";
5319  BuiltinTypeName[BuiltinTypeName["Number"] = 4] = "Number";
5320  BuiltinTypeName[BuiltinTypeName["Function"] = 5] = "Function";
5321  BuiltinTypeName[BuiltinTypeName["Inferred"] = 6] = "Inferred";
5322  BuiltinTypeName[BuiltinTypeName["None"] = 7] = "None";
5323})(BuiltinTypeName || (BuiltinTypeName = {}));
5324
5325class BuiltinType extends Type {
5326  constructor(name, modifiers) {
5327    super(modifiers);
5328    this.name = name;
5329  }
5330
5331  visitType(visitor, context) {
5332    return visitor.visitBuiltinType(this, context);
5333  }
5334
5335}
5336
5337class ExpressionType extends Type {
5338  constructor(value, modifiers, typeParams = null) {
5339    super(modifiers);
5340    this.value = value;
5341    this.typeParams = typeParams;
5342  }
5343
5344  visitType(visitor, context) {
5345    return visitor.visitExpressionType(this, context);
5346  }
5347
5348}
5349
5350class ArrayType extends Type {
5351  constructor(of, modifiers) {
5352    super(modifiers);
5353    this.of = of;
5354  }
5355
5356  visitType(visitor, context) {
5357    return visitor.visitArrayType(this, context);
5358  }
5359
5360}
5361
5362class MapType extends Type {
5363  constructor(valueType, modifiers) {
5364    super(modifiers);
5365    this.valueType = valueType || null;
5366  }
5367
5368  visitType(visitor, context) {
5369    return visitor.visitMapType(this, context);
5370  }
5371
5372}
5373
5374const DYNAMIC_TYPE = new BuiltinType(BuiltinTypeName.Dynamic);
5375const INFERRED_TYPE = new BuiltinType(BuiltinTypeName.Inferred);
5376const BOOL_TYPE = new BuiltinType(BuiltinTypeName.Bool);
5377const INT_TYPE = new BuiltinType(BuiltinTypeName.Int);
5378const NUMBER_TYPE = new BuiltinType(BuiltinTypeName.Number);
5379const STRING_TYPE = new BuiltinType(BuiltinTypeName.String);
5380const FUNCTION_TYPE = new BuiltinType(BuiltinTypeName.Function);
5381const NONE_TYPE = new BuiltinType(BuiltinTypeName.None); ///// Expressions
5382
5383var UnaryOperator;
5384
5385(function (UnaryOperator) {
5386  UnaryOperator[UnaryOperator["Minus"] = 0] = "Minus";
5387  UnaryOperator[UnaryOperator["Plus"] = 1] = "Plus";
5388})(UnaryOperator || (UnaryOperator = {}));
5389
5390var BinaryOperator;
5391
5392(function (BinaryOperator) {
5393  BinaryOperator[BinaryOperator["Equals"] = 0] = "Equals";
5394  BinaryOperator[BinaryOperator["NotEquals"] = 1] = "NotEquals";
5395  BinaryOperator[BinaryOperator["Identical"] = 2] = "Identical";
5396  BinaryOperator[BinaryOperator["NotIdentical"] = 3] = "NotIdentical";
5397  BinaryOperator[BinaryOperator["Minus"] = 4] = "Minus";
5398  BinaryOperator[BinaryOperator["Plus"] = 5] = "Plus";
5399  BinaryOperator[BinaryOperator["Divide"] = 6] = "Divide";
5400  BinaryOperator[BinaryOperator["Multiply"] = 7] = "Multiply";
5401  BinaryOperator[BinaryOperator["Modulo"] = 8] = "Modulo";
5402  BinaryOperator[BinaryOperator["And"] = 9] = "And";
5403  BinaryOperator[BinaryOperator["Or"] = 10] = "Or";
5404  BinaryOperator[BinaryOperator["BitwiseAnd"] = 11] = "BitwiseAnd";
5405  BinaryOperator[BinaryOperator["Lower"] = 12] = "Lower";
5406  BinaryOperator[BinaryOperator["LowerEquals"] = 13] = "LowerEquals";
5407  BinaryOperator[BinaryOperator["Bigger"] = 14] = "Bigger";
5408  BinaryOperator[BinaryOperator["BiggerEquals"] = 15] = "BiggerEquals";
5409  BinaryOperator[BinaryOperator["NullishCoalesce"] = 16] = "NullishCoalesce";
5410})(BinaryOperator || (BinaryOperator = {}));
5411
5412function nullSafeIsEquivalent(base, other) {
5413  if (base == null || other == null) {
5414    return base == other;
5415  }
5416
5417  return base.isEquivalent(other);
5418}
5419
5420function areAllEquivalentPredicate(base, other, equivalentPredicate) {
5421  const len = base.length;
5422
5423  if (len !== other.length) {
5424    return false;
5425  }
5426
5427  for (let i = 0; i < len; i++) {
5428    if (!equivalentPredicate(base[i], other[i])) {
5429      return false;
5430    }
5431  }
5432
5433  return true;
5434}
5435
5436function areAllEquivalent(base, other) {
5437  return areAllEquivalentPredicate(base, other, (baseElement, otherElement) => baseElement.isEquivalent(otherElement));
5438}
5439
5440class Expression {
5441  constructor(type, sourceSpan) {
5442    this.type = type || null;
5443    this.sourceSpan = sourceSpan || null;
5444  }
5445
5446  prop(name, sourceSpan) {
5447    return new ReadPropExpr(this, name, null, sourceSpan);
5448  }
5449
5450  key(index, type, sourceSpan) {
5451    return new ReadKeyExpr(this, index, type, sourceSpan);
5452  }
5453
5454  callFn(params, sourceSpan, pure) {
5455    return new InvokeFunctionExpr(this, params, null, sourceSpan, pure);
5456  }
5457
5458  instantiate(params, type, sourceSpan) {
5459    return new InstantiateExpr(this, params, type, sourceSpan);
5460  }
5461
5462  conditional(trueCase, falseCase = null, sourceSpan) {
5463    return new ConditionalExpr(this, trueCase, falseCase, null, sourceSpan);
5464  }
5465
5466  equals(rhs, sourceSpan) {
5467    return new BinaryOperatorExpr(BinaryOperator.Equals, this, rhs, null, sourceSpan);
5468  }
5469
5470  notEquals(rhs, sourceSpan) {
5471    return new BinaryOperatorExpr(BinaryOperator.NotEquals, this, rhs, null, sourceSpan);
5472  }
5473
5474  identical(rhs, sourceSpan) {
5475    return new BinaryOperatorExpr(BinaryOperator.Identical, this, rhs, null, sourceSpan);
5476  }
5477
5478  notIdentical(rhs, sourceSpan) {
5479    return new BinaryOperatorExpr(BinaryOperator.NotIdentical, this, rhs, null, sourceSpan);
5480  }
5481
5482  minus(rhs, sourceSpan) {
5483    return new BinaryOperatorExpr(BinaryOperator.Minus, this, rhs, null, sourceSpan);
5484  }
5485
5486  plus(rhs, sourceSpan) {
5487    return new BinaryOperatorExpr(BinaryOperator.Plus, this, rhs, null, sourceSpan);
5488  }
5489
5490  divide(rhs, sourceSpan) {
5491    return new BinaryOperatorExpr(BinaryOperator.Divide, this, rhs, null, sourceSpan);
5492  }
5493
5494  multiply(rhs, sourceSpan) {
5495    return new BinaryOperatorExpr(BinaryOperator.Multiply, this, rhs, null, sourceSpan);
5496  }
5497
5498  modulo(rhs, sourceSpan) {
5499    return new BinaryOperatorExpr(BinaryOperator.Modulo, this, rhs, null, sourceSpan);
5500  }
5501
5502  and(rhs, sourceSpan) {
5503    return new BinaryOperatorExpr(BinaryOperator.And, this, rhs, null, sourceSpan);
5504  }
5505
5506  bitwiseAnd(rhs, sourceSpan, parens = true) {
5507    return new BinaryOperatorExpr(BinaryOperator.BitwiseAnd, this, rhs, null, sourceSpan, parens);
5508  }
5509
5510  or(rhs, sourceSpan) {
5511    return new BinaryOperatorExpr(BinaryOperator.Or, this, rhs, null, sourceSpan);
5512  }
5513
5514  lower(rhs, sourceSpan) {
5515    return new BinaryOperatorExpr(BinaryOperator.Lower, this, rhs, null, sourceSpan);
5516  }
5517
5518  lowerEquals(rhs, sourceSpan) {
5519    return new BinaryOperatorExpr(BinaryOperator.LowerEquals, this, rhs, null, sourceSpan);
5520  }
5521
5522  bigger(rhs, sourceSpan) {
5523    return new BinaryOperatorExpr(BinaryOperator.Bigger, this, rhs, null, sourceSpan);
5524  }
5525
5526  biggerEquals(rhs, sourceSpan) {
5527    return new BinaryOperatorExpr(BinaryOperator.BiggerEquals, this, rhs, null, sourceSpan);
5528  }
5529
5530  isBlank(sourceSpan) {
5531    // Note: We use equals by purpose here to compare to null and undefined in JS.
5532    // We use the typed null to allow strictNullChecks to narrow types.
5533    return this.equals(TYPED_NULL_EXPR, sourceSpan);
5534  }
5535
5536  nullishCoalesce(rhs, sourceSpan) {
5537    return new BinaryOperatorExpr(BinaryOperator.NullishCoalesce, this, rhs, null, sourceSpan);
5538  }
5539
5540  toStmt() {
5541    return new ExpressionStatement(this, null);
5542  }
5543
5544}
5545
5546class ReadVarExpr extends Expression {
5547  constructor(name, type, sourceSpan) {
5548    super(type, sourceSpan);
5549    this.name = name;
5550  }
5551
5552  isEquivalent(e) {
5553    return e instanceof ReadVarExpr && this.name === e.name;
5554  }
5555
5556  isConstant() {
5557    return false;
5558  }
5559
5560  visitExpression(visitor, context) {
5561    return visitor.visitReadVarExpr(this, context);
5562  }
5563
5564  set(value) {
5565    return new WriteVarExpr(this.name, value, null, this.sourceSpan);
5566  }
5567
5568}
5569
5570class TypeofExpr extends Expression {
5571  constructor(expr, type, sourceSpan) {
5572    super(type, sourceSpan);
5573    this.expr = expr;
5574  }
5575
5576  visitExpression(visitor, context) {
5577    return visitor.visitTypeofExpr(this, context);
5578  }
5579
5580  isEquivalent(e) {
5581    return e instanceof TypeofExpr && e.expr.isEquivalent(this.expr);
5582  }
5583
5584  isConstant() {
5585    return this.expr.isConstant();
5586  }
5587
5588}
5589
5590class WrappedNodeExpr extends Expression {
5591  constructor(node, type, sourceSpan) {
5592    super(type, sourceSpan);
5593    this.node = node;
5594  }
5595
5596  isEquivalent(e) {
5597    return e instanceof WrappedNodeExpr && this.node === e.node;
5598  }
5599
5600  isConstant() {
5601    return false;
5602  }
5603
5604  visitExpression(visitor, context) {
5605    return visitor.visitWrappedNodeExpr(this, context);
5606  }
5607
5608}
5609
5610class WriteVarExpr extends Expression {
5611  constructor(name, value, type, sourceSpan) {
5612    super(type || value.type, sourceSpan);
5613    this.name = name;
5614    this.value = value;
5615  }
5616
5617  isEquivalent(e) {
5618    return e instanceof WriteVarExpr && this.name === e.name && this.value.isEquivalent(e.value);
5619  }
5620
5621  isConstant() {
5622    return false;
5623  }
5624
5625  visitExpression(visitor, context) {
5626    return visitor.visitWriteVarExpr(this, context);
5627  }
5628
5629  toDeclStmt(type, modifiers) {
5630    return new DeclareVarStmt(this.name, this.value, type, modifiers, this.sourceSpan);
5631  }
5632
5633  toConstDecl() {
5634    return this.toDeclStmt(INFERRED_TYPE, StmtModifier.Final);
5635  }
5636
5637}
5638
5639class WriteKeyExpr extends Expression {
5640  constructor(receiver, index, value, type, sourceSpan) {
5641    super(type || value.type, sourceSpan);
5642    this.receiver = receiver;
5643    this.index = index;
5644    this.value = value;
5645  }
5646
5647  isEquivalent(e) {
5648    return e instanceof WriteKeyExpr && this.receiver.isEquivalent(e.receiver) && this.index.isEquivalent(e.index) && this.value.isEquivalent(e.value);
5649  }
5650
5651  isConstant() {
5652    return false;
5653  }
5654
5655  visitExpression(visitor, context) {
5656    return visitor.visitWriteKeyExpr(this, context);
5657  }
5658
5659}
5660
5661class WritePropExpr extends Expression {
5662  constructor(receiver, name, value, type, sourceSpan) {
5663    super(type || value.type, sourceSpan);
5664    this.receiver = receiver;
5665    this.name = name;
5666    this.value = value;
5667  }
5668
5669  isEquivalent(e) {
5670    return e instanceof WritePropExpr && this.receiver.isEquivalent(e.receiver) && this.name === e.name && this.value.isEquivalent(e.value);
5671  }
5672
5673  isConstant() {
5674    return false;
5675  }
5676
5677  visitExpression(visitor, context) {
5678    return visitor.visitWritePropExpr(this, context);
5679  }
5680
5681}
5682
5683class InvokeFunctionExpr extends Expression {
5684  constructor(fn, args, type, sourceSpan, pure = false) {
5685    super(type, sourceSpan);
5686    this.fn = fn;
5687    this.args = args;
5688    this.pure = pure;
5689  }
5690
5691  isEquivalent(e) {
5692    return e instanceof InvokeFunctionExpr && this.fn.isEquivalent(e.fn) && areAllEquivalent(this.args, e.args) && this.pure === e.pure;
5693  }
5694
5695  isConstant() {
5696    return false;
5697  }
5698
5699  visitExpression(visitor, context) {
5700    return visitor.visitInvokeFunctionExpr(this, context);
5701  }
5702
5703}
5704
5705class TaggedTemplateExpr extends Expression {
5706  constructor(tag, template, type, sourceSpan) {
5707    super(type, sourceSpan);
5708    this.tag = tag;
5709    this.template = template;
5710  }
5711
5712  isEquivalent(e) {
5713    return e instanceof TaggedTemplateExpr && this.tag.isEquivalent(e.tag) && areAllEquivalentPredicate(this.template.elements, e.template.elements, (a, b) => a.text === b.text) && areAllEquivalent(this.template.expressions, e.template.expressions);
5714  }
5715
5716  isConstant() {
5717    return false;
5718  }
5719
5720  visitExpression(visitor, context) {
5721    return visitor.visitTaggedTemplateExpr(this, context);
5722  }
5723
5724}
5725
5726class InstantiateExpr extends Expression {
5727  constructor(classExpr, args, type, sourceSpan) {
5728    super(type, sourceSpan);
5729    this.classExpr = classExpr;
5730    this.args = args;
5731  }
5732
5733  isEquivalent(e) {
5734    return e instanceof InstantiateExpr && this.classExpr.isEquivalent(e.classExpr) && areAllEquivalent(this.args, e.args);
5735  }
5736
5737  isConstant() {
5738    return false;
5739  }
5740
5741  visitExpression(visitor, context) {
5742    return visitor.visitInstantiateExpr(this, context);
5743  }
5744
5745}
5746
5747class LiteralExpr extends Expression {
5748  constructor(value, type, sourceSpan) {
5749    super(type, sourceSpan);
5750    this.value = value;
5751  }
5752
5753  isEquivalent(e) {
5754    return e instanceof LiteralExpr && this.value === e.value;
5755  }
5756
5757  isConstant() {
5758    return true;
5759  }
5760
5761  visitExpression(visitor, context) {
5762    return visitor.visitLiteralExpr(this, context);
5763  }
5764
5765}
5766
5767class TemplateLiteral {
5768  constructor(elements, expressions) {
5769    this.elements = elements;
5770    this.expressions = expressions;
5771  }
5772
5773}
5774
5775class TemplateLiteralElement {
5776  constructor(text, sourceSpan, rawText) {
5777    this.text = text;
5778    this.sourceSpan = sourceSpan; // If `rawText` is not provided, try to extract the raw string from its
5779    // associated `sourceSpan`. If that is also not available, "fake" the raw
5780    // string instead by escaping the following control sequences:
5781    // - "\" would otherwise indicate that the next character is a control character.
5782    // - "`" and "${" are template string control sequences that would otherwise prematurely
5783    // indicate the end of the template literal element.
5784
5785    this.rawText = rawText ?? sourceSpan?.toString() ?? escapeForTemplateLiteral(escapeSlashes(text));
5786  }
5787
5788}
5789
5790class LiteralPiece {
5791  constructor(text, sourceSpan) {
5792    this.text = text;
5793    this.sourceSpan = sourceSpan;
5794  }
5795
5796}
5797
5798class PlaceholderPiece {
5799  /**
5800   * Create a new instance of a `PlaceholderPiece`.
5801   *
5802   * @param text the name of this placeholder (e.g. `PH_1`).
5803   * @param sourceSpan the location of this placeholder in its localized message the source code.
5804   * @param associatedMessage reference to another message that this placeholder is associated with.
5805   * The `associatedMessage` is mainly used to provide a relationship to an ICU message that has
5806   * been extracted out from the message containing the placeholder.
5807   */
5808  constructor(text, sourceSpan, associatedMessage) {
5809    this.text = text;
5810    this.sourceSpan = sourceSpan;
5811    this.associatedMessage = associatedMessage;
5812  }
5813
5814}
5815
5816const MEANING_SEPARATOR$1 = '|';
5817const ID_SEPARATOR$1 = '@@';
5818const LEGACY_ID_INDICATOR = '␟';
5819
5820class LocalizedString extends Expression {
5821  constructor(metaBlock, messageParts, placeHolderNames, expressions, sourceSpan) {
5822    super(STRING_TYPE, sourceSpan);
5823    this.metaBlock = metaBlock;
5824    this.messageParts = messageParts;
5825    this.placeHolderNames = placeHolderNames;
5826    this.expressions = expressions;
5827  }
5828
5829  isEquivalent(e) {
5830    // return e instanceof LocalizedString && this.message === e.message;
5831    return false;
5832  }
5833
5834  isConstant() {
5835    return false;
5836  }
5837
5838  visitExpression(visitor, context) {
5839    return visitor.visitLocalizedString(this, context);
5840  }
5841  /**
5842   * Serialize the given `meta` and `messagePart` into "cooked" and "raw" strings that can be used
5843   * in a `$localize` tagged string. The format of the metadata is the same as that parsed by
5844   * `parseI18nMeta()`.
5845   *
5846   * @param meta The metadata to serialize
5847   * @param messagePart The first part of the tagged string
5848   */
5849
5850
5851  serializeI18nHead() {
5852    let metaBlock = this.metaBlock.description || '';
5853
5854    if (this.metaBlock.meaning) {
5855      metaBlock = `${this.metaBlock.meaning}${MEANING_SEPARATOR$1}${metaBlock}`;
5856    }
5857
5858    if (this.metaBlock.customId) {
5859      metaBlock = `${metaBlock}${ID_SEPARATOR$1}${this.metaBlock.customId}`;
5860    }
5861
5862    if (this.metaBlock.legacyIds) {
5863      this.metaBlock.legacyIds.forEach(legacyId => {
5864        metaBlock = `${metaBlock}${LEGACY_ID_INDICATOR}${legacyId}`;
5865      });
5866    }
5867
5868    return createCookedRawString(metaBlock, this.messageParts[0].text, this.getMessagePartSourceSpan(0));
5869  }
5870
5871  getMessagePartSourceSpan(i) {
5872    return this.messageParts[i]?.sourceSpan ?? this.sourceSpan;
5873  }
5874
5875  getPlaceholderSourceSpan(i) {
5876    return this.placeHolderNames[i]?.sourceSpan ?? this.expressions[i]?.sourceSpan ?? this.sourceSpan;
5877  }
5878  /**
5879   * Serialize the given `placeholderName` and `messagePart` into "cooked" and "raw" strings that
5880   * can be used in a `$localize` tagged string.
5881   *
5882   * The format is `:<placeholder-name>[@@<associated-id>]:`.
5883   *
5884   * The `associated-id` is the message id of the (usually an ICU) message to which this placeholder
5885   * refers.
5886   *
5887   * @param partIndex The index of the message part to serialize.
5888   */
5889
5890
5891  serializeI18nTemplatePart(partIndex) {
5892    const placeholder = this.placeHolderNames[partIndex - 1];
5893    const messagePart = this.messageParts[partIndex];
5894    let metaBlock = placeholder.text;
5895
5896    if (placeholder.associatedMessage?.legacyIds.length === 0) {
5897      metaBlock += `${ID_SEPARATOR$1}${computeMsgId(placeholder.associatedMessage.messageString, placeholder.associatedMessage.meaning)}`;
5898    }
5899
5900    return createCookedRawString(metaBlock, messagePart.text, this.getMessagePartSourceSpan(partIndex));
5901  }
5902
5903}
5904
5905const escapeSlashes = str => str.replace(/\\/g, '\\\\');
5906
5907const escapeStartingColon = str => str.replace(/^:/, '\\:');
5908
5909const escapeColons = str => str.replace(/:/g, '\\:');
5910
5911const escapeForTemplateLiteral = str => str.replace(/`/g, '\\`').replace(/\${/g, '$\\{');
5912/**
5913 * Creates a `{cooked, raw}` object from the `metaBlock` and `messagePart`.
5914 *
5915 * The `raw` text must have various character sequences escaped:
5916 * * "\" would otherwise indicate that the next character is a control character.
5917 * * "`" and "${" are template string control sequences that would otherwise prematurely indicate
5918 *   the end of a message part.
5919 * * ":" inside a metablock would prematurely indicate the end of the metablock.
5920 * * ":" at the start of a messagePart with no metablock would erroneously indicate the start of a
5921 *   metablock.
5922 *
5923 * @param metaBlock Any metadata that should be prepended to the string
5924 * @param messagePart The message part of the string
5925 */
5926
5927
5928function createCookedRawString(metaBlock, messagePart, range) {
5929  if (metaBlock === '') {
5930    return {
5931      cooked: messagePart,
5932      raw: escapeForTemplateLiteral(escapeStartingColon(escapeSlashes(messagePart))),
5933      range
5934    };
5935  } else {
5936    return {
5937      cooked: `:${metaBlock}:${messagePart}`,
5938      raw: escapeForTemplateLiteral(`:${escapeColons(escapeSlashes(metaBlock))}:${escapeSlashes(messagePart)}`),
5939      range
5940    };
5941  }
5942}
5943
5944class ExternalExpr extends Expression {
5945  constructor(value, type, typeParams = null, sourceSpan) {
5946    super(type, sourceSpan);
5947    this.value = value;
5948    this.typeParams = typeParams;
5949  }
5950
5951  isEquivalent(e) {
5952    return e instanceof ExternalExpr && this.value.name === e.value.name && this.value.moduleName === e.value.moduleName && this.value.runtime === e.value.runtime;
5953  }
5954
5955  isConstant() {
5956    return false;
5957  }
5958
5959  visitExpression(visitor, context) {
5960    return visitor.visitExternalExpr(this, context);
5961  }
5962
5963}
5964
5965class ExternalReference {
5966  constructor(moduleName, name, runtime) {
5967    this.moduleName = moduleName;
5968    this.name = name;
5969    this.runtime = runtime;
5970  }
5971
5972}
5973
5974class ConditionalExpr extends Expression {
5975  constructor(condition, trueCase, falseCase = null, type, sourceSpan) {
5976    super(type || trueCase.type, sourceSpan);
5977    this.condition = condition;
5978    this.falseCase = falseCase;
5979    this.trueCase = trueCase;
5980  }
5981
5982  isEquivalent(e) {
5983    return e instanceof ConditionalExpr && this.condition.isEquivalent(e.condition) && this.trueCase.isEquivalent(e.trueCase) && nullSafeIsEquivalent(this.falseCase, e.falseCase);
5984  }
5985
5986  isConstant() {
5987    return false;
5988  }
5989
5990  visitExpression(visitor, context) {
5991    return visitor.visitConditionalExpr(this, context);
5992  }
5993
5994}
5995
5996class NotExpr extends Expression {
5997  constructor(condition, sourceSpan) {
5998    super(BOOL_TYPE, sourceSpan);
5999    this.condition = condition;
6000  }
6001
6002  isEquivalent(e) {
6003    return e instanceof NotExpr && this.condition.isEquivalent(e.condition);
6004  }
6005
6006  isConstant() {
6007    return false;
6008  }
6009
6010  visitExpression(visitor, context) {
6011    return visitor.visitNotExpr(this, context);
6012  }
6013
6014}
6015
6016class FnParam {
6017  constructor(name, type = null) {
6018    this.name = name;
6019    this.type = type;
6020  }
6021
6022  isEquivalent(param) {
6023    return this.name === param.name;
6024  }
6025
6026}
6027
6028class FunctionExpr extends Expression {
6029  constructor(params, statements, type, sourceSpan, name) {
6030    super(type, sourceSpan);
6031    this.params = params;
6032    this.statements = statements;
6033    this.name = name;
6034  }
6035
6036  isEquivalent(e) {
6037    return e instanceof FunctionExpr && areAllEquivalent(this.params, e.params) && areAllEquivalent(this.statements, e.statements);
6038  }
6039
6040  isConstant() {
6041    return false;
6042  }
6043
6044  visitExpression(visitor, context) {
6045    return visitor.visitFunctionExpr(this, context);
6046  }
6047
6048  toDeclStmt(name, modifiers) {
6049    return new DeclareFunctionStmt(name, this.params, this.statements, this.type, modifiers, this.sourceSpan);
6050  }
6051
6052}
6053
6054class UnaryOperatorExpr extends Expression {
6055  constructor(operator, expr, type, sourceSpan, parens = true) {
6056    super(type || NUMBER_TYPE, sourceSpan);
6057    this.operator = operator;
6058    this.expr = expr;
6059    this.parens = parens;
6060  }
6061
6062  isEquivalent(e) {
6063    return e instanceof UnaryOperatorExpr && this.operator === e.operator && this.expr.isEquivalent(e.expr);
6064  }
6065
6066  isConstant() {
6067    return false;
6068  }
6069
6070  visitExpression(visitor, context) {
6071    return visitor.visitUnaryOperatorExpr(this, context);
6072  }
6073
6074}
6075
6076class BinaryOperatorExpr extends Expression {
6077  constructor(operator, lhs, rhs, type, sourceSpan, parens = true) {
6078    super(type || lhs.type, sourceSpan);
6079    this.operator = operator;
6080    this.rhs = rhs;
6081    this.parens = parens;
6082    this.lhs = lhs;
6083  }
6084
6085  isEquivalent(e) {
6086    return e instanceof BinaryOperatorExpr && this.operator === e.operator && this.lhs.isEquivalent(e.lhs) && this.rhs.isEquivalent(e.rhs);
6087  }
6088
6089  isConstant() {
6090    return false;
6091  }
6092
6093  visitExpression(visitor, context) {
6094    return visitor.visitBinaryOperatorExpr(this, context);
6095  }
6096
6097}
6098
6099class ReadPropExpr extends Expression {
6100  constructor(receiver, name, type, sourceSpan) {
6101    super(type, sourceSpan);
6102    this.receiver = receiver;
6103    this.name = name;
6104  }
6105
6106  isEquivalent(e) {
6107    return e instanceof ReadPropExpr && this.receiver.isEquivalent(e.receiver) && this.name === e.name;
6108  }
6109
6110  isConstant() {
6111    return false;
6112  }
6113
6114  visitExpression(visitor, context) {
6115    return visitor.visitReadPropExpr(this, context);
6116  }
6117
6118  set(value) {
6119    return new WritePropExpr(this.receiver, this.name, value, null, this.sourceSpan);
6120  }
6121
6122}
6123
6124class ReadKeyExpr extends Expression {
6125  constructor(receiver, index, type, sourceSpan) {
6126    super(type, sourceSpan);
6127    this.receiver = receiver;
6128    this.index = index;
6129  }
6130
6131  isEquivalent(e) {
6132    return e instanceof ReadKeyExpr && this.receiver.isEquivalent(e.receiver) && this.index.isEquivalent(e.index);
6133  }
6134
6135  isConstant() {
6136    return false;
6137  }
6138
6139  visitExpression(visitor, context) {
6140    return visitor.visitReadKeyExpr(this, context);
6141  }
6142
6143  set(value) {
6144    return new WriteKeyExpr(this.receiver, this.index, value, null, this.sourceSpan);
6145  }
6146
6147}
6148
6149class LiteralArrayExpr extends Expression {
6150  constructor(entries, type, sourceSpan) {
6151    super(type, sourceSpan);
6152    this.entries = entries;
6153  }
6154
6155  isConstant() {
6156    return this.entries.every(e => e.isConstant());
6157  }
6158
6159  isEquivalent(e) {
6160    return e instanceof LiteralArrayExpr && areAllEquivalent(this.entries, e.entries);
6161  }
6162
6163  visitExpression(visitor, context) {
6164    return visitor.visitLiteralArrayExpr(this, context);
6165  }
6166
6167}
6168
6169class LiteralMapEntry {
6170  constructor(key, value, quoted) {
6171    this.key = key;
6172    this.value = value;
6173    this.quoted = quoted;
6174  }
6175
6176  isEquivalent(e) {
6177    return this.key === e.key && this.value.isEquivalent(e.value);
6178  }
6179
6180}
6181
6182class LiteralMapExpr extends Expression {
6183  constructor(entries, type, sourceSpan) {
6184    super(type, sourceSpan);
6185    this.entries = entries;
6186    this.valueType = null;
6187
6188    if (type) {
6189      this.valueType = type.valueType;
6190    }
6191  }
6192
6193  isEquivalent(e) {
6194    return e instanceof LiteralMapExpr && areAllEquivalent(this.entries, e.entries);
6195  }
6196
6197  isConstant() {
6198    return this.entries.every(e => e.value.isConstant());
6199  }
6200
6201  visitExpression(visitor, context) {
6202    return visitor.visitLiteralMapExpr(this, context);
6203  }
6204
6205}
6206
6207class CommaExpr extends Expression {
6208  constructor(parts, sourceSpan) {
6209    super(parts[parts.length - 1].type, sourceSpan);
6210    this.parts = parts;
6211  }
6212
6213  isEquivalent(e) {
6214    return e instanceof CommaExpr && areAllEquivalent(this.parts, e.parts);
6215  }
6216
6217  isConstant() {
6218    return false;
6219  }
6220
6221  visitExpression(visitor, context) {
6222    return visitor.visitCommaExpr(this, context);
6223  }
6224
6225}
6226
6227const NULL_EXPR = new LiteralExpr(null, null, null);
6228const TYPED_NULL_EXPR = new LiteralExpr(null, INFERRED_TYPE, null); //// Statements
6229
6230var StmtModifier;
6231
6232(function (StmtModifier) {
6233  StmtModifier[StmtModifier["None"] = 0] = "None";
6234  StmtModifier[StmtModifier["Final"] = 1] = "Final";
6235  StmtModifier[StmtModifier["Private"] = 2] = "Private";
6236  StmtModifier[StmtModifier["Exported"] = 4] = "Exported";
6237  StmtModifier[StmtModifier["Static"] = 8] = "Static";
6238})(StmtModifier || (StmtModifier = {}));
6239
6240class LeadingComment {
6241  constructor(text, multiline, trailingNewline) {
6242    this.text = text;
6243    this.multiline = multiline;
6244    this.trailingNewline = trailingNewline;
6245  }
6246
6247  toString() {
6248    return this.multiline ? ` ${this.text} ` : this.text;
6249  }
6250
6251}
6252
6253class JSDocComment extends LeadingComment {
6254  constructor(tags) {
6255    super('',
6256    /* multiline */
6257    true,
6258    /* trailingNewline */
6259    true);
6260    this.tags = tags;
6261  }
6262
6263  toString() {
6264    return serializeTags(this.tags);
6265  }
6266
6267}
6268
6269class Statement {
6270  constructor(modifiers = StmtModifier.None, sourceSpan = null, leadingComments) {
6271    this.modifiers = modifiers;
6272    this.sourceSpan = sourceSpan;
6273    this.leadingComments = leadingComments;
6274  }
6275
6276  hasModifier(modifier) {
6277    return (this.modifiers & modifier) !== 0;
6278  }
6279
6280  addLeadingComment(leadingComment) {
6281    this.leadingComments = this.leadingComments ?? [];
6282    this.leadingComments.push(leadingComment);
6283  }
6284
6285}
6286
6287class DeclareVarStmt extends Statement {
6288  constructor(name, value, type, modifiers, sourceSpan, leadingComments) {
6289    super(modifiers, sourceSpan, leadingComments);
6290    this.name = name;
6291    this.value = value;
6292    this.type = type || value && value.type || null;
6293  }
6294
6295  isEquivalent(stmt) {
6296    return stmt instanceof DeclareVarStmt && this.name === stmt.name && (this.value ? !!stmt.value && this.value.isEquivalent(stmt.value) : !stmt.value);
6297  }
6298
6299  visitStatement(visitor, context) {
6300    return visitor.visitDeclareVarStmt(this, context);
6301  }
6302
6303}
6304
6305class DeclareFunctionStmt extends Statement {
6306  constructor(name, params, statements, type, modifiers, sourceSpan, leadingComments) {
6307    super(modifiers, sourceSpan, leadingComments);
6308    this.name = name;
6309    this.params = params;
6310    this.statements = statements;
6311    this.type = type || null;
6312  }
6313
6314  isEquivalent(stmt) {
6315    return stmt instanceof DeclareFunctionStmt && areAllEquivalent(this.params, stmt.params) && areAllEquivalent(this.statements, stmt.statements);
6316  }
6317
6318  visitStatement(visitor, context) {
6319    return visitor.visitDeclareFunctionStmt(this, context);
6320  }
6321
6322}
6323
6324class ExpressionStatement extends Statement {
6325  constructor(expr, sourceSpan, leadingComments) {
6326    super(StmtModifier.None, sourceSpan, leadingComments);
6327    this.expr = expr;
6328  }
6329
6330  isEquivalent(stmt) {
6331    return stmt instanceof ExpressionStatement && this.expr.isEquivalent(stmt.expr);
6332  }
6333
6334  visitStatement(visitor, context) {
6335    return visitor.visitExpressionStmt(this, context);
6336  }
6337
6338}
6339
6340class ReturnStatement extends Statement {
6341  constructor(value, sourceSpan = null, leadingComments) {
6342    super(StmtModifier.None, sourceSpan, leadingComments);
6343    this.value = value;
6344  }
6345
6346  isEquivalent(stmt) {
6347    return stmt instanceof ReturnStatement && this.value.isEquivalent(stmt.value);
6348  }
6349
6350  visitStatement(visitor, context) {
6351    return visitor.visitReturnStmt(this, context);
6352  }
6353
6354}
6355
6356class IfStmt extends Statement {
6357  constructor(condition, trueCase, falseCase = [], sourceSpan, leadingComments) {
6358    super(StmtModifier.None, sourceSpan, leadingComments);
6359    this.condition = condition;
6360    this.trueCase = trueCase;
6361    this.falseCase = falseCase;
6362  }
6363
6364  isEquivalent(stmt) {
6365    return stmt instanceof IfStmt && this.condition.isEquivalent(stmt.condition) && areAllEquivalent(this.trueCase, stmt.trueCase) && areAllEquivalent(this.falseCase, stmt.falseCase);
6366  }
6367
6368  visitStatement(visitor, context) {
6369    return visitor.visitIfStmt(this, context);
6370  }
6371
6372}
6373
6374class RecursiveAstVisitor$1 {
6375  visitType(ast, context) {
6376    return ast;
6377  }
6378
6379  visitExpression(ast, context) {
6380    if (ast.type) {
6381      ast.type.visitType(this, context);
6382    }
6383
6384    return ast;
6385  }
6386
6387  visitBuiltinType(type, context) {
6388    return this.visitType(type, context);
6389  }
6390
6391  visitExpressionType(type, context) {
6392    type.value.visitExpression(this, context);
6393
6394    if (type.typeParams !== null) {
6395      type.typeParams.forEach(param => this.visitType(param, context));
6396    }
6397
6398    return this.visitType(type, context);
6399  }
6400
6401  visitArrayType(type, context) {
6402    return this.visitType(type, context);
6403  }
6404
6405  visitMapType(type, context) {
6406    return this.visitType(type, context);
6407  }
6408
6409  visitWrappedNodeExpr(ast, context) {
6410    return ast;
6411  }
6412
6413  visitTypeofExpr(ast, context) {
6414    return this.visitExpression(ast, context);
6415  }
6416
6417  visitReadVarExpr(ast, context) {
6418    return this.visitExpression(ast, context);
6419  }
6420
6421  visitWriteVarExpr(ast, context) {
6422    ast.value.visitExpression(this, context);
6423    return this.visitExpression(ast, context);
6424  }
6425
6426  visitWriteKeyExpr(ast, context) {
6427    ast.receiver.visitExpression(this, context);
6428    ast.index.visitExpression(this, context);
6429    ast.value.visitExpression(this, context);
6430    return this.visitExpression(ast, context);
6431  }
6432
6433  visitWritePropExpr(ast, context) {
6434    ast.receiver.visitExpression(this, context);
6435    ast.value.visitExpression(this, context);
6436    return this.visitExpression(ast, context);
6437  }
6438
6439  visitInvokeFunctionExpr(ast, context) {
6440    ast.fn.visitExpression(this, context);
6441    this.visitAllExpressions(ast.args, context);
6442    return this.visitExpression(ast, context);
6443  }
6444
6445  visitTaggedTemplateExpr(ast, context) {
6446    ast.tag.visitExpression(this, context);
6447    this.visitAllExpressions(ast.template.expressions, context);
6448    return this.visitExpression(ast, context);
6449  }
6450
6451  visitInstantiateExpr(ast, context) {
6452    ast.classExpr.visitExpression(this, context);
6453    this.visitAllExpressions(ast.args, context);
6454    return this.visitExpression(ast, context);
6455  }
6456
6457  visitLiteralExpr(ast, context) {
6458    return this.visitExpression(ast, context);
6459  }
6460
6461  visitLocalizedString(ast, context) {
6462    return this.visitExpression(ast, context);
6463  }
6464
6465  visitExternalExpr(ast, context) {
6466    if (ast.typeParams) {
6467      ast.typeParams.forEach(type => type.visitType(this, context));
6468    }
6469
6470    return this.visitExpression(ast, context);
6471  }
6472
6473  visitConditionalExpr(ast, context) {
6474    ast.condition.visitExpression(this, context);
6475    ast.trueCase.visitExpression(this, context);
6476    ast.falseCase.visitExpression(this, context);
6477    return this.visitExpression(ast, context);
6478  }
6479
6480  visitNotExpr(ast, context) {
6481    ast.condition.visitExpression(this, context);
6482    return this.visitExpression(ast, context);
6483  }
6484
6485  visitFunctionExpr(ast, context) {
6486    this.visitAllStatements(ast.statements, context);
6487    return this.visitExpression(ast, context);
6488  }
6489
6490  visitUnaryOperatorExpr(ast, context) {
6491    ast.expr.visitExpression(this, context);
6492    return this.visitExpression(ast, context);
6493  }
6494
6495  visitBinaryOperatorExpr(ast, context) {
6496    ast.lhs.visitExpression(this, context);
6497    ast.rhs.visitExpression(this, context);
6498    return this.visitExpression(ast, context);
6499  }
6500
6501  visitReadPropExpr(ast, context) {
6502    ast.receiver.visitExpression(this, context);
6503    return this.visitExpression(ast, context);
6504  }
6505
6506  visitReadKeyExpr(ast, context) {
6507    ast.receiver.visitExpression(this, context);
6508    ast.index.visitExpression(this, context);
6509    return this.visitExpression(ast, context);
6510  }
6511
6512  visitLiteralArrayExpr(ast, context) {
6513    this.visitAllExpressions(ast.entries, context);
6514    return this.visitExpression(ast, context);
6515  }
6516
6517  visitLiteralMapExpr(ast, context) {
6518    ast.entries.forEach(entry => entry.value.visitExpression(this, context));
6519    return this.visitExpression(ast, context);
6520  }
6521
6522  visitCommaExpr(ast, context) {
6523    this.visitAllExpressions(ast.parts, context);
6524    return this.visitExpression(ast, context);
6525  }
6526
6527  visitAllExpressions(exprs, context) {
6528    exprs.forEach(expr => expr.visitExpression(this, context));
6529  }
6530
6531  visitDeclareVarStmt(stmt, context) {
6532    if (stmt.value) {
6533      stmt.value.visitExpression(this, context);
6534    }
6535
6536    if (stmt.type) {
6537      stmt.type.visitType(this, context);
6538    }
6539
6540    return stmt;
6541  }
6542
6543  visitDeclareFunctionStmt(stmt, context) {
6544    this.visitAllStatements(stmt.statements, context);
6545
6546    if (stmt.type) {
6547      stmt.type.visitType(this, context);
6548    }
6549
6550    return stmt;
6551  }
6552
6553  visitExpressionStmt(stmt, context) {
6554    stmt.expr.visitExpression(this, context);
6555    return stmt;
6556  }
6557
6558  visitReturnStmt(stmt, context) {
6559    stmt.value.visitExpression(this, context);
6560    return stmt;
6561  }
6562
6563  visitIfStmt(stmt, context) {
6564    stmt.condition.visitExpression(this, context);
6565    this.visitAllStatements(stmt.trueCase, context);
6566    this.visitAllStatements(stmt.falseCase, context);
6567    return stmt;
6568  }
6569
6570  visitAllStatements(stmts, context) {
6571    stmts.forEach(stmt => stmt.visitStatement(this, context));
6572  }
6573
6574}
6575
6576function leadingComment(text, multiline = false, trailingNewline = true) {
6577  return new LeadingComment(text, multiline, trailingNewline);
6578}
6579
6580function jsDocComment(tags = []) {
6581  return new JSDocComment(tags);
6582}
6583
6584function variable(name, type, sourceSpan) {
6585  return new ReadVarExpr(name, type, sourceSpan);
6586}
6587
6588function importExpr(id, typeParams = null, sourceSpan) {
6589  return new ExternalExpr(id, null, typeParams, sourceSpan);
6590}
6591
6592function importType(id, typeParams, typeModifiers) {
6593  return id != null ? expressionType(importExpr(id, typeParams, null), typeModifiers) : null;
6594}
6595
6596function expressionType(expr, typeModifiers, typeParams) {
6597  return new ExpressionType(expr, typeModifiers, typeParams);
6598}
6599
6600function typeofExpr(expr) {
6601  return new TypeofExpr(expr);
6602}
6603
6604function literalArr(values, type, sourceSpan) {
6605  return new LiteralArrayExpr(values, type, sourceSpan);
6606}
6607
6608function literalMap(values, type = null) {
6609  return new LiteralMapExpr(values.map(e => new LiteralMapEntry(e.key, e.value, e.quoted)), type, null);
6610}
6611
6612function unary(operator, expr, type, sourceSpan) {
6613  return new UnaryOperatorExpr(operator, expr, type, sourceSpan);
6614}
6615
6616function not(expr, sourceSpan) {
6617  return new NotExpr(expr, sourceSpan);
6618}
6619
6620function fn(params, body, type, sourceSpan, name) {
6621  return new FunctionExpr(params, body, type, sourceSpan, name);
6622}
6623
6624function ifStmt(condition, thenClause, elseClause, sourceSpan, leadingComments) {
6625  return new IfStmt(condition, thenClause, elseClause, sourceSpan, leadingComments);
6626}
6627
6628function taggedTemplate(tag, template, type, sourceSpan) {
6629  return new TaggedTemplateExpr(tag, template, type, sourceSpan);
6630}
6631
6632function literal(value, type, sourceSpan) {
6633  return new LiteralExpr(value, type, sourceSpan);
6634}
6635
6636function localizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan) {
6637  return new LocalizedString(metaBlock, messageParts, placeholderNames, expressions, sourceSpan);
6638}
6639
6640function isNull(exp) {
6641  return exp instanceof LiteralExpr && exp.value === null;
6642}
6643/*
6644 * Serializes a `Tag` into a string.
6645 * Returns a string like " @foo {bar} baz" (note the leading whitespace before `@foo`).
6646 */
6647
6648
6649function tagToString(tag) {
6650  let out = '';
6651
6652  if (tag.tagName) {
6653    out += ` @${tag.tagName}`;
6654  }
6655
6656  if (tag.text) {
6657    if (tag.text.match(/\/\*|\*\//)) {
6658      throw new Error('JSDoc text cannot contain "/*" and "*/"');
6659    }
6660
6661    out += ' ' + tag.text.replace(/@/g, '\\@');
6662  }
6663
6664  return out;
6665}
6666
6667function serializeTags(tags) {
6668  if (tags.length === 0) return '';
6669
6670  if (tags.length === 1 && tags[0].tagName && !tags[0].text) {
6671    // The JSDOC comment is a single simple tag: e.g `/** @tagname */`.
6672    return `*${tagToString(tags[0])} `;
6673  }
6674
6675  let out = '*\n';
6676
6677  for (const tag of tags) {
6678    out += ' *'; // If the tagToString is multi-line, insert " * " prefixes on lines.
6679
6680    out += tagToString(tag).replace(/\n/g, '\n * ');
6681    out += '\n';
6682  }
6683
6684  out += ' ';
6685  return out;
6686}
6687
6688var output_ast = /*#__PURE__*/Object.freeze({
6689  __proto__: null,
6690
6691  get TypeModifier() {
6692    return TypeModifier;
6693  },
6694
6695  Type: Type,
6696
6697  get BuiltinTypeName() {
6698    return BuiltinTypeName;
6699  },
6700
6701  BuiltinType: BuiltinType,
6702  ExpressionType: ExpressionType,
6703  ArrayType: ArrayType,
6704  MapType: MapType,
6705  DYNAMIC_TYPE: DYNAMIC_TYPE,
6706  INFERRED_TYPE: INFERRED_TYPE,
6707  BOOL_TYPE: BOOL_TYPE,
6708  INT_TYPE: INT_TYPE,
6709  NUMBER_TYPE: NUMBER_TYPE,
6710  STRING_TYPE: STRING_TYPE,
6711  FUNCTION_TYPE: FUNCTION_TYPE,
6712  NONE_TYPE: NONE_TYPE,
6713
6714  get UnaryOperator() {
6715    return UnaryOperator;
6716  },
6717
6718  get BinaryOperator() {
6719    return BinaryOperator;
6720  },
6721
6722  nullSafeIsEquivalent: nullSafeIsEquivalent,
6723  areAllEquivalent: areAllEquivalent,
6724  Expression: Expression,
6725  ReadVarExpr: ReadVarExpr,
6726  TypeofExpr: TypeofExpr,
6727  WrappedNodeExpr: WrappedNodeExpr,
6728  WriteVarExpr: WriteVarExpr,
6729  WriteKeyExpr: WriteKeyExpr,
6730  WritePropExpr: WritePropExpr,
6731  InvokeFunctionExpr: InvokeFunctionExpr,
6732  TaggedTemplateExpr: TaggedTemplateExpr,
6733  InstantiateExpr: InstantiateExpr,
6734  LiteralExpr: LiteralExpr,
6735  TemplateLiteral: TemplateLiteral,
6736  TemplateLiteralElement: TemplateLiteralElement,
6737  LiteralPiece: LiteralPiece,
6738  PlaceholderPiece: PlaceholderPiece,
6739  LocalizedString: LocalizedString,
6740  ExternalExpr: ExternalExpr,
6741  ExternalReference: ExternalReference,
6742  ConditionalExpr: ConditionalExpr,
6743  NotExpr: NotExpr,
6744  FnParam: FnParam,
6745  FunctionExpr: FunctionExpr,
6746  UnaryOperatorExpr: UnaryOperatorExpr,
6747  BinaryOperatorExpr: BinaryOperatorExpr,
6748  ReadPropExpr: ReadPropExpr,
6749  ReadKeyExpr: ReadKeyExpr,
6750  LiteralArrayExpr: LiteralArrayExpr,
6751  LiteralMapEntry: LiteralMapEntry,
6752  LiteralMapExpr: LiteralMapExpr,
6753  CommaExpr: CommaExpr,
6754  NULL_EXPR: NULL_EXPR,
6755  TYPED_NULL_EXPR: TYPED_NULL_EXPR,
6756
6757  get StmtModifier() {
6758    return StmtModifier;
6759  },
6760
6761  LeadingComment: LeadingComment,
6762  JSDocComment: JSDocComment,
6763  Statement: Statement,
6764  DeclareVarStmt: DeclareVarStmt,
6765  DeclareFunctionStmt: DeclareFunctionStmt,
6766  ExpressionStatement: ExpressionStatement,
6767  ReturnStatement: ReturnStatement,
6768  IfStmt: IfStmt,
6769  RecursiveAstVisitor: RecursiveAstVisitor$1,
6770  leadingComment: leadingComment,
6771  jsDocComment: jsDocComment,
6772  variable: variable,
6773  importExpr: importExpr,
6774  importType: importType,
6775  expressionType: expressionType,
6776  typeofExpr: typeofExpr,
6777  literalArr: literalArr,
6778  literalMap: literalMap,
6779  unary: unary,
6780  not: not,
6781  fn: fn,
6782  ifStmt: ifStmt,
6783  taggedTemplate: taggedTemplate,
6784  literal: literal,
6785  localizedString: localizedString,
6786  isNull: isNull
6787});
6788/**
6789 * @license
6790 * Copyright Google LLC All Rights Reserved.
6791 *
6792 * Use of this source code is governed by an MIT-style license that can be
6793 * found in the LICENSE file at https://angular.io/license
6794 */
6795
6796const CONSTANT_PREFIX = '_c';
6797/**
6798 * `ConstantPool` tries to reuse literal factories when two or more literals are identical.
6799 * We determine whether literals are identical by creating a key out of their AST using the
6800 * `KeyVisitor`. This constant is used to replace dynamic expressions which can't be safely
6801 * converted into a key. E.g. given an expression `{foo: bar()}`, since we don't know what
6802 * the result of `bar` will be, we create a key that looks like `{foo: <unknown>}`. Note
6803 * that we use a variable, rather than something like `null` in order to avoid collisions.
6804 */
6805
6806const UNKNOWN_VALUE_KEY = variable('<unknown>');
6807/**
6808 * Context to use when producing a key.
6809 *
6810 * This ensures we see the constant not the reference variable when producing
6811 * a key.
6812 */
6813
6814const KEY_CONTEXT = {};
6815/**
6816 * Generally all primitive values are excluded from the `ConstantPool`, but there is an exclusion
6817 * for strings that reach a certain length threshold. This constant defines the length threshold for
6818 * strings.
6819 */
6820
6821const POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS = 50;
6822/**
6823 * A node that is a place-holder that allows the node to be replaced when the actual
6824 * node is known.
6825 *
6826 * This allows the constant pool to change an expression from a direct reference to
6827 * a constant to a shared constant. It returns a fix-up node that is later allowed to
6828 * change the referenced expression.
6829 */
6830
6831class FixupExpression extends Expression {
6832  constructor(resolved) {
6833    super(resolved.type);
6834    this.resolved = resolved;
6835    this.original = resolved;
6836  }
6837
6838  visitExpression(visitor, context) {
6839    if (context === KEY_CONTEXT) {
6840      // When producing a key we want to traverse the constant not the
6841      // variable used to refer to it.
6842      return this.original.visitExpression(visitor, context);
6843    } else {
6844      return this.resolved.visitExpression(visitor, context);
6845    }
6846  }
6847
6848  isEquivalent(e) {
6849    return e instanceof FixupExpression && this.resolved.isEquivalent(e.resolved);
6850  }
6851
6852  isConstant() {
6853    return true;
6854  }
6855
6856  fixup(expression) {
6857    this.resolved = expression;
6858    this.shared = true;
6859  }
6860
6861}
6862/**
6863 * A constant pool allows a code emitter to share constant in an output context.
6864 *
6865 * The constant pool also supports sharing access to ivy definitions references.
6866 */
6867
6868
6869class ConstantPool {
6870  constructor(isClosureCompilerEnabled = false) {
6871    this.isClosureCompilerEnabled = isClosureCompilerEnabled;
6872    this.statements = [];
6873    this.literals = new Map();
6874    this.literalFactories = new Map();
6875    this.nextNameIndex = 0;
6876  }
6877
6878  getConstLiteral(literal, forceShared) {
6879    if (literal instanceof LiteralExpr && !isLongStringLiteral(literal) || literal instanceof FixupExpression) {
6880      // Do no put simple literals into the constant pool or try to produce a constant for a
6881      // reference to a constant.
6882      return literal;
6883    }
6884
6885    const key = this.keyOf(literal);
6886    let fixup = this.literals.get(key);
6887    let newValue = false;
6888
6889    if (!fixup) {
6890      fixup = new FixupExpression(literal);
6891      this.literals.set(key, fixup);
6892      newValue = true;
6893    }
6894
6895    if (!newValue && !fixup.shared || newValue && forceShared) {
6896      // Replace the expression with a variable
6897      const name = this.freshName();
6898      let definition;
6899      let usage;
6900
6901      if (this.isClosureCompilerEnabled && isLongStringLiteral(literal)) {
6902        // For string literals, Closure will **always** inline the string at
6903        // **all** usages, duplicating it each time. For large strings, this
6904        // unnecessarily bloats bundle size. To work around this restriction, we
6905        // wrap the string in a function, and call that function for each usage.
6906        // This tricks Closure into using inline logic for functions instead of
6907        // string literals. Function calls are only inlined if the body is small
6908        // enough to be worth it. By doing this, very large strings will be
6909        // shared across multiple usages, rather than duplicating the string at
6910        // each usage site.
6911        //
6912        // const myStr = function() { return "very very very long string"; };
6913        // const usage1 = myStr();
6914        // const usage2 = myStr();
6915        definition = variable(name).set(new FunctionExpr([], // Params.
6916        [// Statements.
6917        new ReturnStatement(literal)]));
6918        usage = variable(name).callFn([]);
6919      } else {
6920        // Just declare and use the variable directly, without a function call
6921        // indirection. This saves a few bytes and avoids an unnecessary call.
6922        definition = variable(name).set(literal);
6923        usage = variable(name);
6924      }
6925
6926      this.statements.push(definition.toDeclStmt(INFERRED_TYPE, StmtModifier.Final));
6927      fixup.fixup(usage);
6928    }
6929
6930    return fixup;
6931  }
6932
6933  getLiteralFactory(literal) {
6934    // Create a pure function that builds an array of a mix of constant and variable expressions
6935    if (literal instanceof LiteralArrayExpr) {
6936      const argumentsForKey = literal.entries.map(e => e.isConstant() ? e : UNKNOWN_VALUE_KEY);
6937      const key = this.keyOf(literalArr(argumentsForKey));
6938      return this._getLiteralFactory(key, literal.entries, entries => literalArr(entries));
6939    } else {
6940      const expressionForKey = literalMap(literal.entries.map(e => ({
6941        key: e.key,
6942        value: e.value.isConstant() ? e.value : UNKNOWN_VALUE_KEY,
6943        quoted: e.quoted
6944      })));
6945      const key = this.keyOf(expressionForKey);
6946      return this._getLiteralFactory(key, literal.entries.map(e => e.value), entries => literalMap(entries.map((value, index) => ({
6947        key: literal.entries[index].key,
6948        value,
6949        quoted: literal.entries[index].quoted
6950      }))));
6951    }
6952  }
6953
6954  _getLiteralFactory(key, values, resultMap) {
6955    let literalFactory = this.literalFactories.get(key);
6956    const literalFactoryArguments = values.filter(e => !e.isConstant());
6957
6958    if (!literalFactory) {
6959      const resultExpressions = values.map((e, index) => e.isConstant() ? this.getConstLiteral(e, true) : variable(`a${index}`));
6960      const parameters = resultExpressions.filter(isVariable).map(e => new FnParam(e.name, DYNAMIC_TYPE));
6961      const pureFunctionDeclaration = fn(parameters, [new ReturnStatement
6961(resultMap(resultExpressions))], INFERRED_TYPE);
6962      const name = this.freshName();
6963      this.statements.push(variable(name).set(pureFunctionDeclaration).toDeclStmt(INFERRED_TYPE, StmtModifier.Final));
6964      literalFactory = variable(name);
6965      this.literalFactories.set(key, literalFactory);
6966    }
6967
6968    return {
6969      literalFactory,
6970      literalFactoryArguments
6971    };
6972  }
6973  /**
6974   * Produce a unique name.
6975   *
6976   * The name might be unique among different prefixes if any of the prefixes end in
6977   * a digit so the prefix should be a constant string (not based on user input) and
6978   * must not end in a digit.
6979   */
6980
6981
6982  uniqueName(prefix) {
6983    return `${prefix}${this.nextNameIndex++}`;
6984  }
6985
6986  freshName() {
6987    return this.uniqueName(CONSTANT_PREFIX);
6988  }
6989
6990  keyOf(expression) {
6991    return expression.visitExpression(new KeyVisitor(), KEY_CONTEXT);
6992  }
6993
6994}
6995/**
6996 * Visitor used to determine if 2 expressions are equivalent and can be shared in the
6997 * `ConstantPool`.
6998 *
6999 * When the id (string) generated by the visitor is equal, expressions are considered equivalent.
7000 */
7001
7002
7003class KeyVisitor {
7004  constructor() {
7005    this.visitWrappedNodeExpr = invalid$1;
7006    this.visitWriteVarExpr = invalid$1;
7007    this.visitWriteKeyExpr = invalid$1;
7008    this.visitWritePropExpr = invalid$1;
7009    this.visitInvokeFunctionExpr = invalid$1;
7010    this.visitTaggedTemplateExpr = invalid$1;
7011    this.visitInstantiateExpr = invalid$1;
7012    this.visitConditionalExpr = invalid$1;
7013    this.visitNotExpr = invalid$1;
7014    this.visitAssertNotNullExpr = invalid$1;
7015    this.visitCastExpr = invalid$1;
7016    this.visitFunctionExpr = invalid$1;
7017    this.visitUnaryOperatorExpr = invalid$1;
7018    this.visitBinaryOperatorExpr = invalid$1;
7019    this.visitReadPropExpr = invalid$1;
7020    this.visitReadKeyExpr = invalid$1;
7021    this.visitCommaExpr = invalid$1;
7022    this.visitLocalizedString = invalid$1;
7023  }
7024
7025  visitLiteralExpr(ast) {
7026    return `${typeof ast.value === 'string' ? '"' + ast.value + '"' : ast.value}`;
7027  }
7028
7029  visitLiteralArrayExpr(ast, context) {
7030    return `[${ast.entries.map(entry => entry.visitExpression(this, context)).join(',')}]`;
7031  }
7032
7033  visitLiteralMapExpr(ast, context) {
7034    const mapKey = entry => {
7035      const quote = entry.quoted ? '"' : '';
7036      return `${quote}${entry.key}${quote}`;
7037    };
7038
7039    const mapEntry = entry => `${mapKey(entry)}:${entry.value.visitExpression(this, context)}`;
7040
7041    return `{${ast.entries.map(mapEntry).join(',')}`;
7042  }
7043
7044  visitExternalExpr(ast) {
7045    return ast.value.moduleName ? `EX:${ast.value.moduleName}:${ast.value.name}` : `EX:${ast.value.runtime.name}`;
7046  }
7047
7048  visitReadVarExpr(node) {
7049    return `VAR:${node.name}`;
7050  }
7051
7052  visitTypeofExpr(node, context) {
7053    return `TYPEOF:${node.expr.visitExpression(this, context)}`;
7054  }
7055
7056}
7057
7058function invalid$1(arg) {
7059  throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
7060}
7061
7062function isVariable(e) {
7063  return e instanceof ReadVarExpr;
7064}
7065
7066function isLongStringLiteral(expr) {
7067  return expr instanceof LiteralExpr && typeof expr.value === 'string' && expr.value.length >= POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS;
7068}
7069/**
7070 * @license
7071 * Copyright Google LLC All Rights Reserved.
7072 *
7073 * Use of this source code is governed by an MIT-style license that can be
7074 * found in the LICENSE file at https://angular.io/license
7075 */
7076
7077
7078const CORE = '@angular/core';
7079
7080class Identifiers {}
7081/* Methods */
7082
7083
7084Identifiers.NEW_METHOD = 'factory';
7085Identifiers.TRANSFORM_METHOD = 'transform';
7086Identifiers.PATCH_DEPS = 'patchedDeps';
7087Identifiers.core = {
7088  name: null,
7089  moduleName: CORE
7090};
7091/* Instructions */
7092
7093Identifiers.namespaceHTML = {
7094  name: 'ɵɵnamespaceHTML',
7095  moduleName: CORE
7096};
7097Identifiers.namespaceMathML = {
7098  name: 'ɵɵnamespaceMathML',
7099  moduleName: CORE
7100};
7101Identifiers.namespaceSVG = {
7102  name: 'ɵɵnamespaceSVG',
7103  moduleName: CORE
7104};
7105Identifiers.element = {
7106  name: 'ɵɵelement',
7107  moduleName: CORE
7108};
7109Identifiers.elementStart = {
7110  name: 'ɵɵelementStart',
7111  moduleName: CORE
7112};
7113Identifiers.elementEnd = {
7114  name: 'ɵɵelementEnd',
7115  moduleName: CORE
7116};
7117Identifiers.advance = {
7118  name: 'ɵɵadvance',
7119  moduleName: CORE
7120};
7121Identifiers.syntheticHostProperty = {
7122  name: 'ɵɵsyntheticHostProperty',
7123  moduleName: CORE
7124};
7125Identifiers.syntheticHostListener = {
7126  name: 'ɵɵsyntheticHostListener',
7127  moduleName: CORE
7128};
7129Identifiers.attribute = {
7130  name: 'ɵɵattribute',
7131  moduleName: CORE
7132};
7133Identifiers.attributeInterpolate1 = {
7134  name: 'ɵɵattributeInterpolate1',
7135  moduleName: CORE
7136};
7137Identifiers.attributeInterpolate2 = {
7138  name: 'ɵɵattributeInterpolate2',
7139  moduleName: CORE
7140};
7141Identifiers.attributeInterpolate3 = {
7142  name: 'ɵɵattributeInterpolate3',
7143  moduleName: CORE
7144};
7145Identifiers.attributeInterpolate4 = {
7146  name: 'ɵɵattributeInterpolate4',
7147  moduleName: CORE
7148};
7149Identifiers.attributeInterpolate5 = {
7150  name: 'ɵɵattributeInterpolate5',
7151  moduleName: CORE
7152};
7153Identifiers.attributeInterpolate6 = {
7154  name: 'ɵɵattributeInterpolate6',
7155  moduleName: CORE
7156};
7157Identifiers.attributeInterpolate7 = {
7158  name: 'ɵɵattributeInterpolate7',
7159  moduleName: CORE
7160};
7161Identifiers.attributeInterpolate8 = {
7162  name: 'ɵɵattributeInterpolate8',
7163  moduleName: CORE
7164};
7165Identifiers.attributeInterpolateV = {
7166  name: 'ɵɵattributeInterpolateV',
7167  moduleName: CORE
7168};
7169Identifiers.classProp = {
7170  name: 'ɵɵclassProp',
7171  moduleName: CORE
7172};
7173Identifiers.elementContainerStart = {
7174  name: 'ɵɵelementContainerStart',
7175  moduleName: CORE
7176};
7177Identifiers.elementContainerEnd = {
7178  name: 'ɵɵelementContainerEnd',
7179  moduleName: CORE
7180};
7181Identifiers.elementContainer = {
7182  name: 'ɵɵelementContainer',
7183  moduleName: CORE
7184};
7185Identifiers.styleMap = {
7186  name: 'ɵɵstyleMap',
7187  moduleName: CORE
7188};
7189Identifiers.styleMapInterpolate1 = {
7190  name: 'ɵɵstyleMapInterpolate1',
7191  moduleName: CORE
7192};
7193Identifiers.styleMapInterpolate2 = {
7194  name: 'ɵɵstyleMapInterpolate2',
7195  moduleName: CORE
7196};
7197Identifiers.styleMapInterpolate3 = {
7198  name: 'ɵɵstyleMapInterpolate3',
7199  moduleName: CORE
7200};
7201Identifiers.styleMapInterpolate4 = {
7202  name: 'ɵɵstyleMapInterpolate4',
7203  moduleName: CORE
7204};
7205Identifiers.styleMapInterpolate5 = {
7206  name: 'ɵɵstyleMapInterpolate5',
7207  moduleName: CORE
7208};
7209Identifiers.styleMapInterpolate6 = {
7210  name: 'ɵɵstyleMapInterpolate6',
7211  moduleName: CORE
7212};
7213Identifiers.styleMapInterpolate7 = {
7214  name: 'ɵɵstyleMapInterpolate7',
7215  moduleName: CORE
7216};
7217Identifiers.styleMapInterpolate8 = {
7218  name: 'ɵɵstyleMapInterpolate8',
7219  moduleName: CORE
7220};
7221Identifiers.styleMapInterpolateV = {
7222  name: 'ɵɵstyleMapInterpolateV',
7223  moduleName: CORE
7224};
7225Identifiers.classMap = {
7226  name: 'ɵɵclassMap',
7227  moduleName: CORE
7228};
7229Identifiers.classMapInterpolate1 = {
7230  name: 'ɵɵclassMapInterpolate1',
7231  moduleName: CORE
7232};
7233Identifiers.classMapInterpolate2 = {
7234  name: 'ɵɵclassMapInterpolate2',
7235  moduleName: CORE
7236};
7237Identifiers.classMapInterpolate3 = {
7238  name: 'ɵɵclassMapInterpolate3',
7239  moduleName: CORE
7240};
7241Identifiers.classMapInterpolate4 = {
7242  name: 'ɵɵclassMapInterpolate4',
7243  moduleName: CORE
7244};
7245Identifiers.classMapInterpolate5 = {
7246  name: 'ɵɵclassMapInterpolate5',
7247  moduleName: CORE
7248};
7249Identifiers.classMapInterpolate6 = {
7250  name: 'ɵɵclassMapInterpolate6',
7251  moduleName: CORE
7252};
7253Identifiers.classMapInterpolate7 = {
7254  name: 'ɵɵclassMapInterpolate7',
7255  moduleName: CORE
7256};
7257Identifiers.classMapInterpolate8 = {
7258  name: 'ɵɵclassMapInterpolate8',
7259  moduleName: CORE
7260};
7261Identifiers.classMapInterpolateV = {
7262  name: 'ɵɵclassMapInterpolateV',
7263  moduleName: CORE
7264};
7265Identifiers.styleProp = {
7266  name: 'ɵɵstyleProp',
7267  moduleName: CORE
7268};
7269Identifiers.stylePropInterpolate1 = {
7270  name: 'ɵɵstylePropInterpolate1',
7271  moduleName: CORE
7272};
7273Identifiers.stylePropInterpolate2 = {
7274  name: 'ɵɵstylePropInterpolate2',
7275  moduleName: CORE
7276};
7277Identifiers.stylePropInterpolate3 = {
7278  name: 'ɵɵstylePropInterpolate3',
7279  moduleName: CORE
7280};
7281Identifiers.stylePropInterpolate4 = {
7282  name: 'ɵɵstylePropInterpolate4',
7283  moduleName: CORE
7284};
7285Identifiers.stylePropInterpolate5 = {
7286  name: 'ɵɵstylePropInterpolate5',
7287  moduleName: CORE
7288};
7289Identifiers.stylePropInterpolate6 = {
7290  name: 'ɵɵstylePropInterpolate6',
7291  moduleName: CORE
7292};
7293Identifiers.stylePropInterpolate7 = {
7294  name: 'ɵɵstylePropInterpolate7',
7295  moduleName: CORE
7296};
7297Identifiers.stylePropInterpolate8 = {
7298  name: 'ɵɵstylePropInterpolate8',
7299  moduleName: CORE
7300};
7301Identifiers.stylePropInterpolateV = {
7302  name: 'ɵɵstylePropInterpolateV',
7303  moduleName: CORE
7304};
7305Identifiers.nextContext = {
7306  name: 'ɵɵnextContext',
7307  moduleName: CORE
7308};
7309Identifiers.resetView = {
7310  name: 'ɵɵresetView',
7311  moduleName: CORE
7312};
7313Identifiers.templateCreate = {
7314  name: 'ɵɵtemplate',
7315  moduleName: CORE
7316};
7317Identifiers.text = {
7318  name: 'ɵɵtext',
7319  moduleName: CORE
7320};
7321Identifiers.enableBindings = {
7322  name: 'ɵɵenableBindings',
7323  moduleName: CORE
7324};
7325Identifiers.disableBindings = {
7326  name: 'ɵɵdisableBindings',
7327  moduleName: CORE
7328};
7329Identifiers.getCurrentView = {
7330  name: 'ɵɵgetCurrentView',
7331  moduleName: CORE
7332};
7333Identifiers.textInterpolate = {
7334  name: 'ɵɵtextInterpolate',
7335  moduleName: CORE
7336};
7337Identifiers.textInterpolate1 = {
7338  name: 'ɵɵtextInterpolate1',
7339  moduleName: CORE
7340};
7341Identifiers.textInterpolate2 = {
7342  name: 'ɵɵtextInterpolate2',
7343  moduleName: CORE
7344};
7345Identifiers.textInterpolate3 = {
7346  name: 'ɵɵtextInterpolate3',
7347  moduleName: CORE
7348};
7349Identifiers.textInterpolate4 = {
7350  name: 'ɵɵtextInterpolate4',
7351  moduleName: CORE
7352};
7353Identifiers.textInterpolate5 = {
7354  name: 'ɵɵtextInterpolate5',
7355  moduleName: CORE
7356};
7357Identifiers.textInterpolate6 = {
7358  name: 'ɵɵtextInterpolate6',
7359  moduleName: CORE
7360};
7361Identifiers.textInterpolate7 = {
7362  name: 'ɵɵtextInterpolate7',
7363  moduleName: CORE
7364};
7365Identifiers.textInterpolate8 = {
7366  name: 'ɵɵtextInterpolate8',
7367  moduleName: CORE
7368};
7369Identifiers.textInterpolateV = {
7370  name: 'ɵɵtextInterpolateV',
7371  moduleName: CORE
7372};
7373Identifiers.restoreView = {
7374  name: 'ɵɵrestoreView',
7375  moduleName: CORE
7376};
7377Identifiers.pureFunction0 = {
7378  name: 'ɵɵpureFunction0',
7379  moduleName: CORE
7380};
7381Identifiers.pureFunction1 = {
7382  name: 'ɵɵpureFunction1',
7383  moduleName: CORE
7384};
7385Identifiers.pureFunction2 = {
7386  name: 'ɵɵpureFunction2',
7387  moduleName: CORE
7388};
7389Identifiers.pureFunction3 = {
7390  name: 'ɵɵpureFunction3',
7391  moduleName: CORE
7392};
7393Identifiers.pureFunction4 = {
7394  name: 'ɵɵpureFunction4',
7395  moduleName: CORE
7396};
7397Identifiers.pureFunction5 = {
7398  name: 'ɵɵpureFunction5',
7399  moduleName: CORE
7400};
7401Identifiers.pureFunction6 = {
7402  name: 'ɵɵpureFunction6',
7403  moduleName: CORE
7404};
7405Identifiers.pureFunction7 = {
7406  name: 'ɵɵpureFunction7',
7407  moduleName: CORE
7408};
7409Identifiers.pureFunction8 = {
7410  name: 'ɵɵpureFunction8',
7411  moduleName: CORE
7412};
7413Identifiers.pureFunctionV = {
7414  name: 'ɵɵpureFunctionV',
7415  moduleName: CORE
7416};
7417Identifiers.pipeBind1 = {
7418  name: 'ɵɵpipeBind1',
7419  moduleName: CORE
7420};
7421Identifiers.pipeBind2 = {
7422  name: 'ɵɵpipeBind2',
7423  moduleName: CORE
7424};
7425Identifiers.pipeBind3 = {
7426  name: 'ɵɵpipeBind3',
7427  moduleName: CORE
7428};
7429Identifiers.pipeBind4 = {
7430  name: 'ɵɵpipeBind4',
7431  moduleName: CORE
7432};
7433Identifiers.pipeBindV = {
7434  name: 'ɵɵpipeBindV',
7435  moduleName: CORE
7436};
7437Identifiers.hostProperty = {
7438  name: 'ɵɵhostProperty',
7439  moduleName: CORE
7440};
7441Identifiers.property = {
7442  name: 'ɵɵproperty',
7443  moduleName: CORE
7444};
7445Identifiers.propertyInterpolate = {
7446  name: 'ɵɵpropertyInterpolate',
7447  moduleName: CORE
7448};
7449Identifiers.propertyInterpolate1 = {
7450  name: 'ɵɵpropertyInterpolate1',
7451  moduleName: CORE
7452};
7453Identifiers.propertyInterpolate2 = {
7454  name: 'ɵɵpropertyInterpolate2',
7455  moduleName: CORE
7456};
7457Identifiers.propertyInterpolate3 = {
7458  name: 'ɵɵpropertyInterpolate3',
7459  moduleName: CORE
7460};
7461Identifiers.propertyInterpolate4 = {
7462  name: 'ɵɵpropertyInterpolate4',
7463  moduleName: CORE
7464};
7465Identifiers.propertyInterpolate5 = {
7466  name: 'ɵɵpropertyInterpolate5',
7467  moduleName: CORE
7468};
7469Identifiers.propertyInterpolate6 = {
7470  name: 'ɵɵpropertyInterpolate6',
7471  moduleName: CORE
7472};
7473Identifiers.propertyInterpolate7 = {
7474  name: 'ɵɵpropertyInterpolate7',
7475  moduleName: CORE
7476};
7477Identifiers.propertyInterpolate8 = {
7478  name: 'ɵɵpropertyInterpolate8',
7479  moduleName: CORE
7480};
7481Identifiers.propertyInterpolateV = {
7482  name: 'ɵɵpropertyInterpolateV',
7483  moduleName: CORE
7484};
7485Identifiers.i18n = {
7486  name: 'ɵɵi18n',
7487  moduleName: CORE
7488};
7489Identifiers.i18nAttributes = {
7490  name: 'ɵɵi18nAttributes',
7491  moduleName: CORE
7492};
7493Identifiers.i18nExp = {
7494  name: 'ɵɵi18nExp',
7495  moduleName: CORE
7496};
7497Identifiers.i18nStart = {
7498  name: 'ɵɵi18nStart',
7499  moduleName: CORE
7500};
7501Identifiers.i18nEnd = {
7502  name: 'ɵɵi18nEnd',
7503  moduleName: CORE
7504};
7505Identifiers.i18nApply = {
7506  name: 'ɵɵi18nApply',
7507  moduleName: CORE
7508};
7509Identifiers.i18nPostprocess = {
7510  name: 'ɵɵi18nPostprocess',
7511  moduleName: CORE
7512};
7513Identifiers.pipe = {
7514  name: 'ɵɵpipe',
7515  moduleName: CORE
7516};
7517Identifiers.projection = {
7518  name: 'ɵɵprojection',
7519  moduleName: CORE
7520};
7521Identifiers.projectionDef = {
7522  name: 'ɵɵprojectionDef',
7523  moduleName: CORE
7524};
7525Identifiers.reference = {
7526  name: 'ɵɵreference',
7527  moduleName: CORE
7528};
7529Identifiers.inject = {
7530  name: 'ɵɵinject',
7531  moduleName: CORE
7532};
7533Identifiers.injectAttribute = {
7534  name: 'ɵɵinjectAttribute',
7535  moduleName: CORE
7536};
7537Identifiers.directiveInject = {
7538  name: 'ɵɵdirectiveInject',
7539  moduleName: CORE
7540};
7541Identifiers.invalidFactory = {
7542  name: 'ɵɵinvalidFactory',
7543  moduleName: CORE
7544};
7545Identifiers.invalidFactoryDep = {
7546  name: 'ɵɵinvalidFactoryDep',
7547  moduleName: CORE
7548};
7549Identifiers.templateRefExtractor = {
7550  name: 'ɵɵtemplateRefExtractor',
7551  moduleName: CORE
7552};
7553Identifiers.forwardRef = {
7554  name: 'forwardRef',
7555  moduleName: CORE
7556};
7557Identifiers.resolveForwardRef = {
7558  name: 'resolveForwardRef',
7559  moduleName: CORE
7560};
7561Identifiers.ɵɵdefineInjectable = {
7562  name: 'ɵɵdefineInjectable',
7563  moduleName: CORE
7564};
7565Identifiers.declareInjectable = {
7566  name: 'ɵɵngDeclareInjectable',
7567  moduleName: CORE
7568};
7569Identifiers.InjectableDeclaration = {
7570  name: 'ɵɵInjectableDeclaration',
7571  moduleName: CORE
7572};
7573Identifiers.resolveWindow = {
7574  name: 'ɵɵresolveWindow',
7575  moduleName: CORE
7576};
7577Identifiers.resolveDocument = {
7578  name: 'ɵɵresolveDocument',
7579  moduleName: CORE
7580};
7581Identifiers.resolveBody = {
7582  name: 'ɵɵresolveBody',
7583  moduleName: CORE
7584};
7585Identifiers.defineComponent = {
7586  name: 'ɵɵdefineComponent',
7587  moduleName: CORE
7588};
7589Identifiers.declareComponent = {
7590  name: 'ɵɵngDeclareComponent',
7591  moduleName: CORE
7592};
7593Identifiers.setComponentScope = {
7594  name: 'ɵɵsetComponentScope',
7595  moduleName: CORE
7596};
7597Identifiers.ChangeDetectionStrategy = {
7598  name: 'ChangeDetectionStrategy',
7599  moduleName: CORE
7600};
7601Identifiers.ViewEncapsulation = {
7602  name: 'ViewEncapsulation',
7603  moduleName: CORE
7604};
7605Identifiers.ComponentDeclaration = {
7606  name: 'ɵɵComponentDeclaration',
7607  moduleName: CORE
7608};
7609Identifiers.FactoryDeclaration = {
7610  name: 'ɵɵFactoryDeclaration',
7611  moduleName: CORE
7612};
7613Identifiers.declareFactory = {
7614  name: 'ɵɵngDeclareFactory',
7615  moduleName: CORE
7616};
7617Identifiers.FactoryTarget = {
7618  name: 'ɵɵFactoryTarget',
7619  moduleName: CORE
7620};
7621Identifiers.defineDirective = {
7622  name: 'ɵɵdefineDirective',
7623  moduleName: CORE
7624};
7625Identifiers.declareDirective = {
7626  name: 'ɵɵngDeclareDirective',
7627  moduleName: CORE
7628};
7629Identifiers.DirectiveDeclaration = {
7630  name: 'ɵɵDirectiveDeclaration',
7631  moduleName: CORE
7632};
7633Identifiers.InjectorDef = {
7634  name: 'ɵɵInjectorDef',
7635  moduleName: CORE
7636};
7637Identifiers.InjectorDeclaration = {
7638  name: 'ɵɵInjectorDeclaration',
7639  moduleName: CORE
7640};
7641Identifiers.defineInjector = {
7642  name: 'ɵɵdefineInjector',
7643  moduleName: CORE
7644};
7645Identifiers.declareInjector = {
7646  name: 'ɵɵngDeclareInjector',
7647  moduleName: CORE
7648};
7649Identifiers.NgModuleDeclaration = {
7650  name: 'ɵɵNgModuleDeclaration',
7651  moduleName: CORE
7652};
7653Identifiers.ModuleWithProviders = {
7654  name: 'ModuleWithProviders',
7655  moduleName: CORE
7656};
7657Identifiers.defineNgModule = {
7658  name: 'ɵɵdefineNgModule',
7659  moduleName: CORE
7660};
7661Identifiers.declareNgModule = {
7662  name: 'ɵɵngDeclareNgModule',
7663  moduleName: CORE
7664};
7665Identifiers.setNgModuleScope = {
7666  name: 'ɵɵsetNgModuleScope',
7667  moduleName: CORE
7668};
7669Identifiers.registerNgModuleType = {
7670  name: 'ɵɵregisterNgModuleType',
7671  moduleName: CORE
7672};
7673Identifiers.PipeDeclaration = {
7674  name: 'ɵɵPipeDeclaration',
7675  moduleName: CORE
7676};
7677Identifiers.definePipe = {
7678  name: 'ɵɵdefinePipe',
7679  moduleName: CORE
7680};
7681Identifiers.declarePipe = {
7682  name: 'ɵɵngDeclarePipe',
7683  moduleName: CORE
7684};
7685Identifiers.declareClassMetadata = {
7686  name: 'ɵɵngDeclareClassMetadata',
7687  moduleName: CORE
7688};
7689Identifiers.setClassMetadata = {
7690  name: 'ɵsetClassMetadata',
7691  moduleName: CORE
7692};
7693Identifiers.queryRefresh = {
7694  name: 'ɵɵqueryRefresh',
7695  moduleName: CORE
7696};
7697Identifiers.viewQuery = {
7698  name: 'ɵɵviewQuery',
7699  moduleName: CORE
7700};
7701Identifiers.loadQuery = {
7702  name: 'ɵɵloadQuery',
7703  moduleName: CORE
7704};
7705Identifiers.contentQuery = {
7706  name: 'ɵɵcontentQuery',
7707  moduleName: CORE
7708};
7709Identifiers.NgOnChangesFeature = {
7710  name: 'ɵɵNgOnChangesFeature',
7711  moduleName: CORE
7712};
7713Identifiers.InheritDefinitionFeature = {
7714  name: 'ɵɵInheritDefinitionFeature',
7715  moduleName: CORE
7716};
7717Identifiers.CopyDefinitionFeature = {
7718  name: 'ɵɵCopyDefinitionFeature',
7719  moduleName: CORE
7720};
7721Identifiers.StandaloneFeature = {
7722  name: 'ɵɵStandaloneFeature',
7723  moduleName: CORE
7724};
7725Identifiers.ProvidersFeature = {
7726  name: 'ɵɵProvidersFeature',
7727  moduleName: CORE
7728};
7729Identifiers.listener = {
7730  name: 'ɵɵlistener',
7731  moduleName: CORE
7732};
7733Identifiers.getInheritedFactory = {
7734  name: 'ɵɵgetInheritedFactory',
7735  moduleName: CORE
7736}; // sanitization-related functions
7737
7738Identifiers.sanitizeHtml = {
7739  name: 'ɵɵsanitizeHtml',
7740  moduleName: CORE
7741};
7742Identifiers.sanitizeStyle = {
7743  name: 'ɵɵsanitizeStyle',
7744  moduleName: CORE
7745};
7746Identifiers.sanitizeResourceUrl = {
7747  name: 'ɵɵsanitizeResourceUrl',
7748  moduleName: CORE
7749};
7750Identifiers.sanitizeScript = {
7751  name: 'ɵɵsanitizeScript',
7752  moduleName: CORE
7753};
7754Identifiers.sanitizeUrl = {
7755  name: 'ɵɵsanitizeUrl',
7756  moduleName: CORE
7757};
7758Identifiers.sanitizeUrlOrResourceUrl = {
7759  name: 'ɵɵsanitizeUrlOrResourceUrl',
7760  moduleName: CORE
7761};
7762Identifiers.trustConstantHtml = {
7763  name: 'ɵɵtrustConstantHtml',
7764  moduleName: CORE
7765};
7766Identifiers.trustConstantResourceUrl = {
7767  name: 'ɵɵtrustConstantResourceUrl',
7768  moduleName: CORE
7769};
7770Identifiers.validateIframeAttribute = {
7771  name: 'ɵɵvalidateIframeAttribute',
7772  moduleName: CORE
7773};
7774/**
7775 * @license
7776 * Copyright Google LLC All Rights Reserved.
7777 *
7778 * Use of this source code is governed by an MIT-style license that can be
7779 * found in the LICENSE file at https://angular.io/license
7780 */
7781// https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
7782
7783const VERSION$1 = 3;
7784const JS_B64_PREFIX = '# sourceMappingURL=data:application/json;base64,';
7785
7786class SourceMapGenerator {
7787  constructor(file = null) {
7788    this.file = file;
7789    this.sourcesContent = new Map();
7790    this.lines = [];
7791    this.lastCol0 = 0;
7792    this.hasMappings = false;
7793  } // The content is `null` when the content is expected to be loaded using the URL
7794
7795
7796  addSource(url, content = null) {
7797    if (!this.sourcesContent.has(url)) {
7798      this.sourcesContent.set(url, content);
7799    }
7800
7801    return this;
7802  }
7803
7804  addLine() {
7805    this.lines.push([]);
7806    this.lastCol0 = 0;
7807    return this;
7808  }
7809
7810  addMapping(col0, sourceUrl, sourceLine0, sourceCol0) {
7811    if (!this.currentLine) {
7812      throw new Error(`A line must be added before mappings can be added`);
7813    }
7814
7815    if (sourceUrl != null && !this.sourcesContent.has(sourceUrl)) {
7816      throw new Error(`Unknown source file "${sourceUrl}"`);
7817    }
7818
7819    if (col0 == null) {
7820      throw new Error(`The column in the generated code must be provided`);
7821    }
7822
7823    if (col0 < this.lastCol0) {
7824      throw new Error(`Mapping should be added in output order`);
7825    }
7826
7827    if (sourceUrl && (sourceLine0 == null || sourceCol0 == null)) {
7828      throw new Error(`The source location must be provided when a source url is provided`);
7829    }
7830
7831    this.hasMappings = true;
7832    this.lastCol0 = col0;
7833    this.currentLine.push({
7834      col0,
7835      sourceUrl,
7836      sourceLine0,
7837      sourceCol0
7838    });
7839    return this;
7840  }
7841  /**
7842   * @internal strip this from published d.ts files due to
7843   * https://github.com/microsoft/TypeScript/issues/36216
7844   */
7845
7846
7847  get currentLine() {
7848    return this.lines.slice(-1)[0];
7849  }
7850
7851  toJSON() {
7852    if (!this.hasMappings) {
7853      return null;
7854    }
7855
7856    const sourcesIndex = new Map();
7857    const sources = [];
7858    const sourcesContent = [];
7859    Array.from(this.sourcesContent.keys()).forEach((url, i) => {
7860      sourcesIndex.set(url, i);
7861      sources.push(url);
7862      sourcesContent.push(this.sourcesContent.get(url) || null);
7863    });
7864    let mappings = '';
7865    let lastCol0 = 0;
7866    let lastSourceIndex = 0;
7867    let lastSourceLine0 = 0;
7868    let lastSourceCol0 = 0;
7869    this.lines.forEach(segments => {
7870      lastCol0 = 0;
7871      mappings += segments.map(segment => {
7872        // zero-based starting column of the line in the generated code
7873        let segAsStr = toBase64VLQ(segment.col0 - lastCol0);
7874        lastCol0 = segment.col0;
7875
7876        if (segment.sourceUrl != null) {
7877          // zero-based index into the “sources” list
7878          segAsStr += toBase64VLQ(sourcesIndex.get(segment.sourceUrl) - lastSourceIndex);
7879          lastSourceIndex = sourcesIndex.get(segment.sourceUrl); // the zero-based starting line in the original source
7880
7881          segAsStr += toBase64VLQ(segment.sourceLine0 - lastSourceLine0);
7882          lastSourceLine0 = segment.sourceLine0; // the zero-based starting column in the original source
7883
7884          segAsStr += toBase64VLQ(segment.sourceCol0 - lastSourceCol0);
7885          lastSourceCol0 = segment.sourceCol0;
7886        }
7887
7888        return segAsStr;
7889      }).join(',');
7890      mappings += ';';
7891    });
7892    mappings = mappings.slice(0, -1);
7893    return {
7894      'file': this.file || '',
7895      'version': VERSION$1,
7896      'sourceRoot': '',
7897      'sources': sources,
7898      'sourcesContent': sourcesContent,
7899      'mappings': mappings
7900    };
7901  }
7902
7903  toJsComment() {
7904    return this.hasMappings ? '//' + JS_B64_PREFIX + toBase64String(JSON.stringify(this, null, 0)) : '';
7905  }
7906
7907}
7908
7909function toBase64String(value) {
7910  let b64 = '';
7911  const encoded = utf8Encode(value);
7912
7913  for (let i = 0; i < encoded.length;) {
7914    const i1 = encoded[i++];
7915    const i2 = i < encoded.length ? encoded[i++] : null;
7916    const i3 = i < encoded.length ? encoded[i++] : null;
7917    b64 += toBase64Digit(i1 >> 2);
7918    b64 += toBase64Digit((i1 & 3) << 4 | (i2 === null ? 0 : i2 >> 4));
7919    b64 += i2 === null ? '=' : toBase64Digit((i2 & 15) << 2 | (i3 === null ? 0 : i3 >> 6));
7920    b64 += i2 === null || i3 === null ? '=' : toBase64Digit(i3 & 63);
7921  }
7922
7923  return b64;
7924}
7925
7926function toBase64VLQ(value) {
7927  value = value < 0 ? (-value << 1) + 1 : value << 1;
7928  let out = '';
7929
7930  do {
7931    let digit = value & 31;
7932    value = value >> 5;
7933
7934    if (value > 0) {
7935      digit = digit | 32;
7936    }
7937
7938    out += toBase64Digit(digit);
7939  } while (value > 0);
7940
7941  return out;
7942}
7943
7944const B64_DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
7944+/';
7945
7946function toBase64Digit(value) {
7947  if (value < 0 || value >= 64) {
7948    throw new Error(`Can only encode value in the range [0, 63]`);
7949  }
7950
7951  return B64_DIGITS[value];
7952}
7953/**
7954 * @license
7955 * Copyright Google LLC All Rights Reserved.
7956 *
7957 * Use of this source code is governed by an MIT-style license that can be
7958 * found in the LICENSE file at https://angular.io/license
7959 */
7960
7961
7962const _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
7963const _LEGAL_IDENTIFIER_RE = /^[$A-Z_][0-9A-Z_$]*$/i;
7964const _INDENT_WITH = '  ';
7965
7966class _EmittedLine {
7967  constructor(indent) {
7968    this.indent = indent;
7969    this.partsLength = 0;
7970    this.parts = [];
7971    this.srcSpans = [];
7972  }
7973
7974}
7975
7976class EmitterVisitorContext {
7977  constructor(_indent) {
7978    this._indent = _indent;
7979    this._lines = [new _EmittedLine(_indent)];
7980  }
7981
7982  static createRoot() {
7983    return new EmitterVisitorContext(0);
7984  }
7985  /**
7986   * @internal strip this from published d.ts files due to
7987   * https://github.com/microsoft/TypeScript/issues/36216
7988   */
7989
7990
7991  get _currentLine() {
7992    return this._lines[this._lines.length - 1];
7993  }
7994
7995  println(from, lastPart = '') {
7996    this.print(from || null, lastPart, true);
7997  }
7998
7999  lineIsEmpty() {
8000    return this._currentLine.parts.length === 0;
8001  }
8002
8003  lineLength() {
8004    return this._currentLine.indent * _INDENT_WITH.length + this._currentLine.partsLength;
8005  }
8006
8007  print(from, part, newLine = false) {
8008    if (part.length > 0) {
8009      this._currentLine.parts.push(part);
8010
8011      this._currentLine.partsLength += part.length;
8012
8013      this._currentLine.srcSpans.push(from && from.sourceSpan || null);
8014    }
8015
8016    if (newLine) {
8017      this._lines.push(new _EmittedLine(this._indent));
8018    }
8019  }
8020
8021  removeEmptyLastLine() {
8022    if (this.lineIsEmpty()) {
8023      this._lines.pop();
8024    }
8025  }
8026
8027  incIndent() {
8028    this._indent++;
8029
8030    if (this.lineIsEmpty()) {
8031      this._currentLine.indent = this._indent;
8032    }
8033  }
8034
8035  decIndent() {
8036    this._indent--;
8037
8038    if (this.lineIsEmpty()) {
8039      this._currentLine.indent = this._indent;
8040    }
8041  }
8042
8043  toSource() {
8044    return this.sourceLines.map(l => l.parts.length > 0 ? _createIndent(l.indent) + l.parts.join('') : '').join('\n');
8045  }
8046
8047  toSourceMapGenerator(genFilePath, startsAtLine = 0) {
8048    const map = new SourceMapGenerator(genFilePath);
8049    let firstOffsetMapped = false;
8050
8051    const mapFirstOffsetIfNeeded = () => {
8052      if (!firstOffsetMapped) {
8053        // Add a single space so that tools won't try to load the file from disk.
8054        // Note: We are using virtual urls like `ng:///`, so we have to
8055        // provide a content here.
8056        map.addSource(genFilePath, ' ').addMapping(0, genFilePath, 0, 0);
8057        firstOffsetMapped = true;
8058      }
8059    };
8060
8061    for (let i = 0; i < startsAtLine; i++) {
8062      map.addLine();
8063      mapFirstOffsetIfNeeded();
8064    }
8065
8066    this.sourceLines.forEach((line, lineIdx) => {
8067      map.addLine();
8068      const spans = line.srcSpans;
8069      const parts = line.parts;
8070      let col0 = line.indent * _INDENT_WITH.length;
8071      let spanIdx = 0; // skip leading parts without source spans
8072
8073      while (spanIdx < spans.length && !spans[spanIdx]) {
8074        col0 += parts[spanIdx].length;
8075        spanIdx++;
8076      }
8077
8078      if (spanIdx < spans.length && lineIdx === 0 && col0 === 0) {
8079        firstOffsetMapped = true;
8080      } else {
8081        mapFirstOffsetIfNeeded();
8082      }
8083
8084      while (spanIdx < spans.length) {
8085        const span = spans[spanIdx];
8086        const source = span.start.file;
8087        const sourceLine = span.start.line;
8088        const sourceCol = span.start.col;
8089        map.addSource(source.url, source.content).addMapping(col0, source.url, sourceLine, sourceCol);
8090        col0 += parts[spanIdx].length;
8091        spanIdx++; // assign parts without span or the same span to the previous segment
8092
8093        while (spanIdx < spans.length && (span === spans[spanIdx] || !spans[spanIdx])) {
8094          col0 += parts[spanIdx].length;
8095          spanIdx++;
8096        }
8097      }
8098    });
8099    return map;
8100  }
8101
8102  spanOf(line, column) {
8103    const emittedLine = this._lines[line];
8104
8105    if (emittedLine) {
8106      let columnsLeft = column - _createIndent(emittedLine.indent).length;
8107
8108      for (let partIndex = 0; partIndex < emittedLine.parts.length; partIndex++) {
8109        const part = emittedLine.parts[partIndex];
8110
8111        if (part.length > columnsLeft) {
8112          return emittedLine.srcSpans[partIndex];
8113        }
8114
8115        columnsLeft -= part.length;
8116      }
8117    }
8118
8119    return null;
8120  }
8121  /**
8122   * @internal strip this from published d.ts files due to
8123   * https://github.com/microsoft/TypeScript/issues/36216
8124   */
8125
8126
8127  get sourceLines() {
8128    if (this._lines.length && this._lines[this._lines.length - 1].parts.length === 0) {
8129      return this._lines.slice(0, -1);
8130    }
8131
8132    return this._lines;
8133  }
8134
8135}
8136
8137class AbstractEmitterVisitor {
8138  constructor(_escapeDollarInStrings) {
8139    this._escapeDollarInStrings = _escapeDollarInStrings;
8140  }
8141
8142  printLeadingComments(stmt, ctx) {
8143    if (stmt.leadingComments === undefined) {
8144      return;
8145    }
8146
8147    for (const comment of stmt.leadingComments) {
8148      if (comment instanceof JSDocComment) {
8149        ctx.print(stmt, `/*${comment.toString()}*/`, comment.trailingNewline);
8150      } else {
8151        if (comment.multiline) {
8152          ctx.print(stmt, `/* ${comment.text} */`, comment.trailingNewline);
8153        } else {
8154          comment.text.split('\n').forEach(line => {
8155            ctx.println(stmt, `// ${line}`);
8156          });
8157        }
8158      }
8159    }
8160  }
8161
8162  visitExpressionStmt(stmt, ctx) {
8163    this.printLeadingComments(stmt, ctx);
8164    stmt.expr.visitExpression(this, ctx);
8165    ctx.println(stmt, ';');
8166    return null;
8167  }
8168
8169  visitReturnStmt(stmt, ctx) {
8170    this.printLeadingComments(stmt, ctx);
8171    ctx.print(stmt, `return `);
8172    stmt.value.visitExpression(this, ctx);
8173    ctx.println(stmt, ';');
8174    return null;
8175  }
8176
8177  visitIfStmt(stmt, ctx) {
8178    this.printLeadingComments(stmt, ctx);
8179    ctx.print(stmt, `if (`);
8180    stmt.condition.visitExpression(this, ctx);
8181    ctx.print(stmt, `) {`);
8182    const hasElseCase = stmt.falseCase != null && stmt.falseCase.length > 0;
8183
8184    if (stmt.trueCase.length <= 1 && !hasElseCase) {
8185      ctx.print(stmt, ` `);
8186      this.visitAllStatements(stmt.trueCase, ctx);
8187      ctx.removeEmptyLastLine();
8188      ctx.print(stmt, ` `);
8189    } else {
8190      ctx.println();
8191      ctx.incIndent();
8192      this.visitAllStatements(stmt.trueCase, ctx);
8193      ctx.decIndent();
8194
8195      if (hasElseCase) {
8196        ctx.println(stmt, `} else {`);
8197        ctx.incIndent();
8198        this.visitAllStatements(stmt.falseCase, ctx);
8199        ctx.decIndent();
8200      }
8201    }
8202
8203    ctx.println(stmt, `}`);
8204    return null;
8205  }
8206
8207  visitWriteVarExpr(expr, ctx) {
8208    const lineWasEmpty = ctx.lineIsEmpty();
8209
8210    if (!lineWasEmpty) {
8211      ctx.print(expr, '(');
8212    }
8213
8214    ctx.print(expr, `${expr.name} = `);
8215    expr.value.visitExpression(this, ctx);
8216
8217    if (!lineWasEmpty) {
8218      ctx.print(expr, ')');
8219    }
8220
8221    return null;
8222  }
8223
8224  visitWriteKeyExpr(expr, ctx) {
8225    const lineWasEmpty = ctx.lineIsEmpty();
8226
8227    if (!lineWasEmpty) {
8228      ctx.print(expr, '(');
8229    }
8230
8231    expr.receiver.visitExpression(this, ctx);
8232    ctx.print(expr, `[`);
8233    expr.index.visitExpression(this, ctx);
8234    ctx.print(expr, `] = `);
8235    expr.value.visitExpression(this, ctx);
8236
8237    if (!lineWasEmpty) {
8238      ctx.print(expr, ')');
8239    }
8240
8241    return null;
8242  }
8243
8244  visitWritePropExpr(expr, ctx) {
8245    const lineWasEmpty = ctx.lineIsEmpty();
8246
8247    if (!lineWasEmpty) {
8248      ctx.print(expr, '(');
8249    }
8250
8251    expr.receiver.visitExpression(this, ctx);
8252    ctx.print(expr, `.${expr.name} = `);
8253    expr.value.visitExpression(this, ctx);
8254
8255    if (!lineWasEmpty) {
8256      ctx.print(expr, ')');
8257    }
8258
8259    return null;
8260  }
8261
8262  visitInvokeFunctionExpr(expr, ctx) {
8263    expr.fn.visitExpression(this, ctx);
8264    ctx.print(expr, `(`);
8265    this.visitAllExpressions(expr.args, ctx, ',');
8266    ctx.print(expr, `)`);
8267    return null;
8268  }
8269
8270  visitTaggedTemplateExpr(expr, ctx) {
8271    expr.tag.visitExpression(this, ctx);
8272    ctx.print(expr, '`' + expr.template.elements[0].rawText);
8273
8274    for (let i = 1; i < expr.template.elements.length; i++) {
8275      ctx.print(expr, '${');
8276      expr.template.expressions[i - 1].visitExpression(this, ctx);
8277      ctx.print(expr, `}${expr.template.elements[i].rawText}`);
8278    }
8279
8280    ctx.print(expr, '`');
8281    return null;
8282  }
8283
8284  visitWrappedNodeExpr(ast, ctx) {
8285    throw new Error('Abstract emitter cannot visit WrappedNodeExpr.');
8286  }
8287
8288  visitTypeofExpr(expr, ctx) {
8289    ctx.print(expr, 'typeof ');
8290    expr.expr.visitExpression(this, ctx);
8291  }
8292
8293  visitReadVarExpr(ast, ctx) {
8294    ctx.print(ast, ast.name);
8295    return null;
8296  }
8297
8298  visitInstantiateExpr(ast, ctx) {
8299    ctx.print(ast, `new `);
8300    ast.classExpr.visitExpression(this, ctx);
8301    ctx.print(ast, `(`);
8302    this.visitAllExpressions(ast.args, ctx, ',');
8303    ctx.print(ast, `)`);
8304    return null;
8305  }
8306
8307  visitLiteralExpr(ast, ctx) {
8308    const value = ast.value;
8309
8310    if (typeof value === 'string') {
8311      ctx.print(ast, escapeIdentifier(value, this._escapeDollarInStrings));
8312    } else {
8313      ctx.print(ast, `${value}`);
8314    }
8315
8316    return null;
8317  }
8318
8319  visitLocalizedString(ast, ctx) {
8320    const head = ast.serializeI18nHead();
8321    ctx.print(ast, '$localize `' + head.raw);
8322
8323    for (let i = 1; i < ast.messageParts.length; i++) {
8324      ctx.print(ast, '${');
8325      ast.expressions[i - 1].visitExpression(this, ctx);
8326      ctx.print(ast, `}${ast.serializeI18nTemplatePart(i).raw}`);
8327    }
8328
8329    ctx.print(ast, '`');
8330    return null;
8331  }
8332
8333  visitConditionalExpr(ast, ctx) {
8334    ctx.print(ast, `(`);
8335    ast.condition.visitExpression(this, ctx);
8336    ctx.print(ast, '? ');
8337    ast.trueCase.visitExpression(this, ctx);
8338    ctx.print(ast, ': ');
8339    ast.falseCase.visitExpression(this, ctx);
8340    ctx.print(ast, `)`);
8341    return null;
8342  }
8343
8344  visitNotExpr(ast, ctx) {
8345    ctx.print(ast, '!');
8346    ast.condition.visitExpression(this, ctx);
8347    return null;
8348  }
8349
8350  visitUnaryOperatorExpr(ast, ctx) {
8351    let opStr;
8352
8353    switch (ast.operator) {
8354      case UnaryOperator.Plus:
8355        opStr = '+';
8356        break;
8357
8358      case UnaryOperator.Minus:
8359        opStr = '-';
8360        break;
8361
8362      default:
8363        throw new Error(`Unknown operator ${ast.operator}`);
8364    }
8365
8366    if (ast.parens) ctx.print(ast, `(`);
8367    ctx.print(ast, opStr);
8368    ast.expr.visitExpression(this, ctx);
8369    if (ast.parens) ctx.print(ast, `)`);
8370    return null;
8371  }
8372
8373  visitBinaryOperatorExpr(ast, ctx) {
8374    let opStr;
8375
8376    switch (ast.operator) {
8377      case BinaryOperator.Equals:
8378        opStr = '==';
8379        break;
8380
8381      case BinaryOperator.Identical:
8382        opStr = '===';
8383        break;
8384
8385      case BinaryOperator.NotEquals:
8386        opStr = '!=';
8387        break;
8388
8389      case BinaryOperator.NotIdentical:
8390        opStr = '!==';
8391        break;
8392
8393      case BinaryOperator.And:
8394        opStr = '&&';
8395        break;
8396
8397      case BinaryOperator.BitwiseAnd:
8398        opStr = '&';
8399        break;
8400
8401      case BinaryOperator.Or:
8402        opStr = '||';
8403        break;
8404
8405      case BinaryOperator.Plus:
8406        opStr = '+';
8407        break;
8408
8409      case BinaryOperator.Minus:
8410        opStr = '-';
8411        break;
8412
8413      case BinaryOperator.Divide:
8414        opStr = '/';
8415        break;
8416
8417      case BinaryOperator.Multiply:
8418        opStr = '*';
8419        break;
8420
8421      case BinaryOperator.Modulo:
8422        opStr = '%';
8423        break;
8424
8425      case BinaryOperator.Lower:
8426        opStr = '<';
8427        break;
8428
8429      case BinaryOperator.LowerEquals:
8430        opStr = '<=';
8431        break;
8432
8433      case BinaryOperator.Bigger:
8434        opStr = '>';
8435        break;
8436
8437      case BinaryOperator.BiggerEquals:
8438        opStr = '>=';
8439        break;
8440
8441      case BinaryOperator.NullishCoalesce:
8442        opStr = '??';
8443        break;
8444
8445      default:
8446        throw new Error(`Unknown operator ${ast.operator}`);
8447    }
8448
8449    if (ast.parens) ctx.print(ast, `(`);
8450    ast.lhs.visitExpression(this, ctx);
8451    ctx.print(ast, ` ${opStr} `);
8452    ast.rhs.visitExpression(this, ctx);
8453    if (ast.parens) ctx.print(ast, `)`);
8454    return null;
8455  }
8456
8457  visitReadPropExpr(ast, ctx) {
8458    ast.receiver.visitExpression(this, ctx);
8459    ctx.print(ast, `.`);
8460    ctx.print(ast, ast.name);
8461    return null;
8462  }
8463
8464  visitReadKeyExpr(ast, ctx) {
8465    ast.receiver.visitExpression(this, ctx);
8466    ctx.print(ast, `[`);
8467    ast.index.visitExpression(this, ctx);
8468    ctx.print(ast, `]`);
8469    return null;
8470  }
8471
8472  visitLiteralArrayExpr(ast, ctx) {
8473    ctx.print(ast, `[`);
8474    this.visitAllExpressions(ast.entries, ctx, ',');
8475    ctx.print(ast, `]`);
8476    return null;
8477  }
8478
8479  visitLiteralMapExpr(ast, ctx) {
8480    ctx.print(ast, `{`);
8481    this.visitAllObjects(entry => {
8482      ctx.print(ast, `${escapeIdentifier(entry.key, this._escapeDollarInStrings, entry.quoted)}:`);
8483      entry.value.visitExpression(this, ctx);
8484    }, ast.entries, ctx, ',');
8485    ctx.print(ast, `}`);
8486    return null;
8487  }
8488
8489  visitCommaExpr(ast, ctx) {
8490    ctx.print(ast, '(');
8491    this.visitAllExpressions(ast.parts, ctx, ',');
8492    ctx.print(ast, ')');
8493    return null;
8494  }
8495
8496  visitAllExpressions(expressions, ctx, separator) {
8497    this.visitAllObjects(expr => expr.visitExpression(this, ctx), expressions, ctx, separator);
8498  }
8499
8500  visitAllObjects(handler, expressions, ctx, separator) {
8501    let incrementedIndent = false;
8502
8503    for (let i = 0; i < expressions.length; i++) {
8504      if (i > 0) {
8505        if (ctx.lineLength() > 80) {
8506          ctx.print(null, separator, true);
8507
8508          if (!incrementedIndent) {
8509            // continuation are marked with double indent.
8510            ctx.incIndent();
8511            ctx.incIndent();
8512            incrementedIndent = true;
8513          }
8514        } else {
8515          ctx.print(null, separator, false);
8516        }
8517      }
8518
8519      handler(expressions[i]);
8520    }
8521
8522    if (incrementedIndent) {
8523      // continuation are marked with double indent.
8524      ctx.decIndent();
8525      ctx.decIndent();
8526    }
8527  }
8528
8529  visitAllStatements(statements, ctx) {
8530    statements.forEach(stmt => stmt.visitStatement(this, ctx));
8531  }
8532
8533}
8534
8535function escapeIdentifier(input, escapeDollar, alwaysQuote = true) {
8536  if (input == null) {
8537    return null;
8538  }
8539
8540  const body = input.replace(_SINGLE_QUOTE_ESCAPE_STRING_RE, (...match) => {
8541    if (match[0] == '$') {
8542      return escapeDollar ? '\\$' : '$';
8543    } else if (match[0] == '\n') {
8544      return '\\n';
8545    } else if (match[0] == '\r') {
8546      return '\\r';
8547    } else {
8548      return `\\${match[0]}`;
8549    }
8550  });
8551  const requiresQuotes = alwaysQuote || !_LEGAL_IDENTIFIER_RE.test(body);
8552  return requiresQuotes ? `'${body}'` : body;
8553}
8554
8555function _createIndent(count) {
8556  let res = '';
8557
8558  for (let i = 0; i < count; i++) {
8559    res += _INDENT_WITH;
8560  }
8561
8562  return res;
8563}
8564/**
8565 * @license
8566 * Copyright Google LLC All Rights Reserved.
8567 *
8568 * Use of this source code is governed by an MIT-style license that can be
8569 * found in the LICENSE file at https://angular.io/license
8570 */
8571
8572
8573function typeWithParameters(type, numParams) {
8574  if (numParams === 0) {
8575    return expressionType(type);
8576  }
8577
8578  const params = [];
8579
8580  for (let i = 0; i < numParams; i++) {
8581    params.push(DYNAMIC_TYPE);
8582  }
8583
8584  return expressionType(type, undefined, params);
8585}
8586
8587const ANIMATE_SYMBOL_PREFIX = '@';
8588
8589function prepareSyntheticPropertyName(name) {
8590  return `${ANIMATE_SYMBOL_PREFIX}${name}`;
8591}
8592
8593function prepareSyntheticListenerName(name, phase) {
8594  return `${ANIMATE_SYMBOL_PREFIX}${name}.${phase}`;
8595}
8596
8597function getSafePropertyAccessString(accessor, name) {
8598  const escapedName = escapeIdentifier(name, false, false);
8599  return escapedName !== name ? `${accessor}[${escapedName}]` : `${accessor}.${name}`;
8600}
8601
8602function prepareSyntheticListenerFunctionName(name, phase) {
8603  return `animation_${name}_${phase}`;
8604}
8605
8606function jitOnlyGuardedExpression(expr) {
8607  return guardedExpression('ngJitMode', expr);
8608}
8609
8610function devOnlyGuardedExpression(expr) {
8611  return guardedExpression('ngDevMode', expr);
8612}
8613
8614function guardedExpression(guard, expr) {
8615  const guardExpr = new ExternalExpr({
8616    name: guard,
8617    moduleName: null
8618  });
8619  const guardNotDefined = new BinaryOperatorExpr(BinaryOperator.Identical, new TypeofExpr(guardExpr), literal('undefined'));
8620  const guardUndefinedOrTrue = new BinaryOperatorExpr(BinaryOperator.Or, guardNotDefined, guardExpr,
8621  /* type */
8622  undefined,
8623  /* sourceSpan */
8624  undefined, true);
8625  return new BinaryOperatorExpr(BinaryOperator.And, guardUndefinedOrTrue, expr);
8626}
8627
8628function wrapReference(value) {
8629  const wrapped = new WrappedNodeExpr(value);
8630  return {
8631    value: wrapped,
8632    type: wrapped
8633  };
8634}
8635
8636function refsToArray(refs, shouldForwardDeclare) {
8637  const values = literalArr(refs.map(ref => ref.value));
8638  return shouldForwardDeclare ? fn([], [new ReturnStatement(values)]) : values;
8639}
8640
8641function createMayBeForwardRefExpression(expression, forwardRef) {
8642  return {
8643    expression,
8644    forwardRef
8645  };
8646}
8647/**
8648 * Convert a `MaybeForwardRefExpression` to an `Expression`, possibly wrapping its expression in a
8649 * `forwardRef()` call.
8650 *
8651 * If `MaybeForwardRefExpression.forwardRef` is `ForwardRefHandling.Unwrapped` then the expression
8652 * was originally wrapped in a `forwardRef()` call to prevent the value from being eagerly evaluated
8653 * in the code.
8654 *
8655 * See `packages/compiler-cli/src/ngtsc/annotations/src/injectable.ts` and
8656 * `packages/compiler/src/jit_compiler_facade.ts` for more information.
8657 */
8658
8659
8660function convertFromMaybeForwardRefExpression({
8661  expression,
8662  forwardRef
8663}) {
8664  switch (forwardRef) {
8665    case 0
8666    /* ForwardRefHandling.None */
8667    :
8668    case 1
8669    /* ForwardRefHandling.Wrapped */
8670    :
8671      return expression;
8672
8673    case 2
8674    /* ForwardRefHandling.Unwrapped */
8675    :
8676      return generateForwardRef(expression);
8677  }
8678}
8679/**
8680 * Generate an expression that has the given `expr` wrapped in the following form:
8681 *
8682 * ```
8683 * forwardRef(() => expr)
8684 * ```
8685 */
8686
8687
8688function generateForwardRef(expr) {
8689  return importExpr(Identifiers.forwardRef).callFn([fn([], [new ReturnStatement
8689(expr)])]);
8690}
8691
8692var R3FactoryDelegateType;
8693
8694(function (R3FactoryDelegateType) {
8695  R3FactoryDelegateType[R3FactoryDelegateType["Class"] = 0] = "Class";
8696  R3FactoryDelegateType[R3FactoryDelegateType["Function"] = 1] = "Function";
8697})(R3FactoryDelegateType || (R3FactoryDelegateType = {}));
8698
8699var FactoryTarget$1;
8700
8701(function (FactoryTarget) {
8702  FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
8703  FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
8704  FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
8705  FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
8706  FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
8707})(FactoryTarget$1 || (FactoryTarget$1 = {}));
8708/**
8709 * Construct a factory function expression for the given `R3FactoryMetadata`.
8710 */
8711
8712
8713function compileFactoryFunction(meta) {
8714  const t = variable('t');
8715  let baseFactoryVar = null; // The type to instantiate via constructor invocation. If there is no delegated factory, meaning
8716  // this type is always created by constructor invocation, then this is the type-to-create
8717  // parameter provided by the user (t) if specified, or the current type if not. If there is a
8718  // delegated factory (which is used to create the current type) then this is only the type-to-
8719  // create parameter (t).
8720
8721  const typeForCtor = !isDelegatedFactoryMetadata(meta) ? new BinaryOperatorExpr(BinaryOperator.Or, t, meta.internalType) : t;
8722  let ctorExpr = null;
8723
8724  if (meta.deps !== null) {
8725    // There is a constructor (either explicitly or implicitly defined).
8726    if (meta.deps !== 'invalid') {
8727      ctorExpr = new InstantiateExpr(typeForCtor, injectDependencies(meta.deps, meta.target));
8728    }
8729  } else {
8730    // There is no constructor, use the base class' factory to construct typeForCtor.
8731    baseFactoryVar = variable(`ɵ${meta.name}_BaseFactory`);
8732    ctorExpr = baseFactoryVar.callFn([typeForCtor]);
8733  }
8734
8735  const body = [];
8736  let retExpr = null;
8737
8738  function makeConditionalFactory(nonCtorExpr) {
8739    const r = variable('r');
8740    body.push(r.set(NULL_EXPR).toDeclStmt());
8741    const ctorStmt = ctorExpr !== null ? r.set(ctorExpr).toStmt() : importExpr(Identifiers.invalidFactory).callFn([]).toStmt();
8742    body.push(ifStmt(t, [ctorStmt], [r.set(nonCtorExpr).toStmt()]));
8743    return r;
8744  }
8745
8746  if (isDelegatedFactoryMetadata(meta)) {
8747    // This type is created with a delegated factory. If a type parameter is not specified, call
8748    // the factory instead.
8749    const delegateArgs = injectDependencies(meta.delegateDeps, meta.target); // Either call `new delegate(...)` or `delegate(...)` depending on meta.delegateType.
8750
8751    const factoryExpr = new (meta.delegateType === R3FactoryDelegateType.Class ? InstantiateExpr : InvokeFunctionExpr)(meta.delegate, delegateArgs);
8752    retExpr = makeConditionalFactory(factoryExpr);
8753  } else if (isExpressionFactoryMetadata(meta)) {
8754    // TODO(alxhub): decide whether to lower the value here or in the caller
8755    retExpr = makeConditionalFactory(meta.expression);
8756  } else {
8757    retExpr = ctorExpr;
8758  }
8759
8760  if (retExpr === null) {
8761    // The expression cannot be formed so render an `ɵɵinvalidFactory()` call.
8762    body.push(importExpr(Identifiers.invalidFactory).callFn([]).toStmt());
8763  } else if (baseFactoryVar !== null) {
8764    // This factory uses a base factory, so call `ɵɵgetInheritedFactory()` to compute it.
8765    const getInheritedFactoryCall = importExpr(Identifiers.getInheritedFactory).callFn([meta.internalType]); // Memoize the base factoryFn: `baseFactory || (baseFactory = ɵɵgetInheritedFactory(...))`
8766
8767    const baseFactory = new BinaryOperatorExpr(BinaryOperator.Or, baseFactoryVar, baseFactoryVar.set(getInheritedFactoryCall));
8768    body.push(new ReturnStatement(baseFactory.callFn([typeForCtor])));
8769  } else {
8770    // This is straightforward factory, just return it.
8771    body.push(new ReturnStatement(retExpr));
8772  }
8773
8774  let factoryFn = fn([new FnParam('t', DYNAMIC_TYPE)], body, INFERRED_TYPE, undefined, `${meta.name}_Factory`);
8775
8776  if (baseFactoryVar !== null) {
8777    // There is a base factory variable so wrap its declaration along with the factory function into
8778    // an IIFE.
8779    factoryFn = fn([], [new DeclareVarStmt(baseFactoryVar.name), new ReturnStatement(factoryFn)]).callFn([],
8780    /* sourceSpan */
8781    undefined,
8782    /* pure */
8783    true);
8784  }
8785
8786  return {
8787    expression: factoryFn,
8788    statements: [],
8789    type: createFactoryType(meta)
8790  };
8791}
8792
8793function createFactoryType(meta) {
8794  const ctorDepsType = meta.deps !== null && meta.deps !== 'invalid' ? createCtorDepsType(meta.deps) : NONE_TYPE;
8795  return expressionType(importExpr(Identifiers.FactoryDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount), ctorDepsType]));
8796}
8797
8798function injectDependencies(deps, target) {
8799  return deps.map((dep, index) => compileInjectDependency(dep, target, index));
8800}
8801
8802function compileInjectDependency(dep, target, index) {
8803  // Interpret the dependency according to its resolved type.
8804  if (dep.token === null) {
8805    return importExpr(Identifiers.invalidFactoryDep).callFn([literal(index)]);
8806  } else if (dep.attributeNameType === null) {
8807    // Build up the injection flags according to the metadata.
8808    const flags = 0
8809    /* InjectFlags.Default */
8810    | (dep.self ? 2
8811    /* InjectFlags.Self */
8812    : 0) | (dep.skipSelf ? 4
8813    /* InjectFlags.SkipSelf */
8814    : 0) | (dep.host ? 1
8815    /* InjectFlags.Host */
8816    : 0) | (dep.optional ? 8
8817    /* InjectFlags.Optional */
8818    : 0) | (target === FactoryTarget$1.Pipe ? 16
8819    /* InjectFlags.ForPipe */
8820    : 0); // If this dependency is optional or otherwise has non-default flags, then additional
8821    // parameters describing how to inject the dependency must be passed to the inject function
8822    // that's being used.
8823
8824    let flagsParam = flags !== 0
8825    /* InjectFlags.Default */
8826    || dep.optional ? literal(flags) : null; // Build up the arguments to the injectFn call.
8827
8828    const injectArgs = [dep.token];
8829
8830    if (flagsParam) {
8831      injectArgs.push(flagsParam);
8832    }
8833
8834    const injectFn = getInjectFn(target);
8835    return importExpr(injectFn).callFn(injectArgs);
8836  } else {
8837    // The `dep.attributeTypeName` value is defined, which indicates that this is an `@Attribute()`
8838    // type dependency. For the generated JS we still want to use the `dep.token` value in case the
8839    // name given for the attribute is not a string literal. For example given `@Attribute(foo())`,
8840    // we want to generate `ɵɵinjectAttribute(foo())`.
8841    //
8842    // The `dep.attributeTypeName` is only actually used (in `createCtorDepType()`) to generate
8843    // typings.
8844    return importExpr(Identifiers.injectAttribute).callFn([dep.token]);
8845  }
8846}
8847
8848function createCtorDepsType(deps) {
8849  let hasTypes = false;
8850  const attributeTypes = deps.map(dep => {
8851    const type = createCtorDepType(dep);
8852
8853    if (type !== null) {
8854      hasTypes = true;
8855      return type;
8856    } else {
8857      return literal(null);
8858    }
8859  });
8860
8861  if (hasTypes) {
8862    return expressionType(literalArr(attributeTypes));
8863  } else {
8864    return NONE_TYPE;
8865  }
8866}
8867
8868function createCtorDepType(dep) {
8869  const entries = [];
8870
8871  if (dep.attributeNameType !== null) {
8872    entries.push({
8873      key: 'attribute',
8874      value: dep.attributeNameType,
8875      quoted: false
8876    });
8877  }
8878
8879  if (dep.optional) {
8880    entries.push({
8881      key: 'optional',
8882      value: literal(true),
8883      quoted: false
8884    });
8885  }
8886
8887  if (dep.host) {
8888    entries.push({
8889      key: 'host',
8890      value: literal(true),
8891      quoted: false
8892    });
8893  }
8894
8895  if (dep.self) {
8896    entries.push({
8897      key: 'self',
8898      value: literal(true),
8899      quoted: false
8900    });
8901  }
8902
8903  if (dep.skipSelf) {
8904    entries.push({
8905      key: 'skipSelf',
8906      value: literal(true),
8907      quoted: false
8908    });
8909  }
8910
8911  return entries.length > 0 ? literalMap(entries) : null;
8912}
8913
8914function isDelegatedFactoryMetadata(meta) {
8915  return meta.delegateType !== undefined;
8916}
8917
8918function isExpressionFactoryMetadata(meta) {
8919  return meta.expression !== undefined;
8920}
8921
8922function getInjectFn(target) {
8923  switch (target) {
8924    case FactoryTarget$1.Component:
8925    case FactoryTarget$1.Directive:
8926    case FactoryTarget$1.Pipe:
8927      return Identifiers.directiveInject;
8928
8929    case FactoryTarget$1.NgModule:
8930    case FactoryTarget$1.Injectable:
8931    default:
8932      return Identifiers.inject;
8933  }
8934}
8935/**
8936 * @license
8937 * Copyright Google LLC All Rights Reserved.
8938 *
8939 * Use of this source code is governed by an MIT-style license that can be
8940 * found in the LICENSE file at https://angular.io/license
8941 */
8942
8943/**
8944 * This is an R3 `Node`-like wrapper for a raw `html.Comment` node. We do not currently
8945 * require the implementation of a visitor for Comments as they are only collected at
8946 * the top-level of the R3 AST, and only if `Render3ParseOptions['collectCommentNodes']`
8947 * is true.
8948 */
8949
8950
8951class Comment$1 {
8952  constructor(value, sourceSpan) {
8953    this.value = value;
8954    this.sourceSpan = sourceSpan;
8955  }
8956
8957  visit(_visitor) {
8958    throw new Error('visit() not implemented for Comment');
8959  }
8960
8961}
8962
8963class Text$3 {
8964  constructor(value, sourceSpan) {
8965    this.value = value;
8966    this.sourceSpan = sourceSpan;
8967  }
8968
8969  visit(visitor) {
8970    return visitor.visitText(this);
8971  }
8972
8973}
8974
8975class BoundText {
8976  constructor(value, sourceSpan, i18n) {
8977    this.value = value;
8978    this.sourceSpan = sourceSpan;
8979    this.i18n = i18n;
8980  }
8981
8982  visit(visitor) {
8983    return visitor.visitBoundText(this);
8984  }
8985
8986}
8987/**
8988 * Represents a text attribute in the template.
8989 *
8990 * `valueSpan` may not be present in cases where there is no value `<div a></div>`.
8991 * `keySpan` may also not be present for synthetic attributes from ICU expansions.
8992 */
8993
8994
8995class TextAttribute {
8996  constructor(name, value, sourceSpan, keySpan, valueSpan, i18n) {
8997    this.name = name;
8998    this.value = value;
8999    this.sourceSpan = sourceSpan;
9000    this.keySpan = keySpan;
9001    this.valueSpan = valueSpan;
9002    this.i18n = i18n;
9003  }
9004
9005  visit(visitor) {
9006    return visitor.visitTextAttribute(this);
9007  }
9008
9009}
9010
9011class BoundAttribute {
9012  constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan, i18n) {
9013    this.name = name;
9014    this.type = type;
9015    this.securityContext = securityContext;
9016    this.value = value;
9017    this.unit = unit;
9018    this.sourceSpan = sourceSpan;
9019    this.keySpan = keySpan;
9020    this.valueSpan = valueSpan;
9021    this.i18n = i18n;
9022  }
9023
9024  static fromBoundElementProperty(prop, i18n) {
9025    if (prop.keySpan === undefined) {
9026      throw new Error(`Unexpected state: keySpan must be defined for bound attributes but was not for ${prop.name}: ${prop.sourceSpan}`);
9027    }
9028
9029    return new BoundAttribute(prop.name, prop.type, prop.securityContext, prop.value, prop.unit, prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n);
9030  }
9031
9032  visit(visitor) {
9033    return visitor.visitBoundAttribute(this);
9034  }
9035
9036}
9037
9038class BoundEvent {
9039  constructor(name, type, handler, target, phase, sourceSpan, handlerSpan, keySpan) {
9040    this.name = name;
9041    this.type = type;
9042    this.handler = handler;
9043    this.target = target;
9044    this.phase = phase;
9045    this.sourceSpan = sourceSpan;
9046    this.handlerSpan = handlerSpan;
9047    this.keySpan = keySpan;
9048  }
9049
9050  static fromParsedEvent(event) {
9051    const target = event.type === 0
9052    /* ParsedEventType.Regular */
9053    ? event.targetOrPhase : null;
9054    const phase = event.type === 1
9055    /* ParsedEventType.Animation */
9056    ? event.targetOrPhase : null;
9057
9058    if (event.keySpan === undefined) {
9059      throw new Error(`Unexpected state: keySpan must be defined for bound event but was not for ${event.name}: ${event.sourceSpan}`);
9060    }
9061
9062    return new BoundEvent(event.name, event.type, event.handler, target, phase, event.sourceSpan, event.handlerSpan, event.keySpan);
9063  }
9064
9065  visit(visitor) {
9066    return visitor.visitBoundEvent(this);
9067  }
9068
9069}
9070
9071class Element$1 {
9072  constructor(name, attributes, inputs, outputs, children, references, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
9073    this.name = name;
9074    this.attributes = attributes;
9075    this.inputs = inputs;
9076    this.outputs = outputs;
9077    this.children = children;
9078    this.references = references;
9079    this.sourceSpan = sourceSpan;
9080    this.startSourceSpan = startSourceSpan;
9081    this.endSourceSpan = endSourceSpan;
9082    this.i18n = i18n;
9083  }
9084
9085  visit(visitor) {
9086    return visitor.visitElement(this);
9087  }
9088
9089}
9090
9091class Template {
9092  constructor( // tagName is the name of the container element, if applicable.
9093  // `null` is a special case for when there is a structural directive on an `ng-template` so
9094  // the renderer can differentiate between the synthetic template and the one written in the
9095  // file.
9096  tagName, attributes, inputs, outputs, templateAttrs, children, references, variables, sourceSpan, startSourceSpan, endSourceSpan, i18n) {
9097    this.tagName = tagName;
9098    this.attributes = attributes;
9099    this.inputs = inputs;
9100    this.outputs = outputs;
9101    this.templateAttrs = templateAttrs;
9102    this.children = children;
9103    this.references = references;
9104    this.variables = variables;
9105    this.sourceSpan = sourceSpan;
9106    this.startSourceSpan = startSourceSpan;
9107    this.endSourceSpan = endSourceSpan;
9108    this.i18n = i18n;
9109  }
9110
9111  visit(visitor) {
9112    return visitor.visitTemplate(this);
9113  }
9114
9115}
9116
9117class Content {
9118  constructor(selector, attributes, sourceSpan, i18n) {
9119    this.selector = selector;
9120    this.attributes = attributes;
9121    this.sourceSpan = sourceSpan;
9122    this.i18n = i18n;
9123    this.name = 'ng-content';
9124  }
9125
9126  visit(visitor) {
9127    return visitor.visitContent(this);
9128  }
9129
9130}
9131
9132class Variable {
9133  constructor(name, value, sourceSpan, keySpan, valueSpan) {
9134    this.name = name;
9135    this.value = value;
9136    this.sourceSpan = sourceSpan;
9137    this.keySpan = keySpan;
9138    this.valueSpan = valueSpan;
9139  }
9140
9141  visit(visitor) {
9142    return visitor.visitVariable(this);
9143  }
9144
9145}
9146
9147class Reference {
9148  constructor(name, value, sourceSpan, keySpan, valueSpan) {
9149    this.name = name;
9150    this.value = value;
9151    this.sourceSpan = sourceSpan;
9152    this.keySpan = keySpan;
9153    this.valueSpan = valueSpan;
9154  }
9155
9156  visit(visitor) {
9157    return visitor.visitReference(this);
9158  }
9159
9160}
9161
9162class Icu$1 {
9163  constructor(vars, placeholders, sourceSpan, i18n) {
9164    this.vars = vars;
9165    this.placeholders = placeholders;
9166    this.sourceSpan = sourceSpan;
9167    this.i18n = i18n;
9168  }
9169
9170  visit(visitor) {
9171    return visitor.visitIcu(this);
9172  }
9173
9174}
9175
9176class NullVisitor {
9177  visitElement(element) {}
9178
9179  visitTemplate(template) {}
9180
9181  visitContent(content) {}
9182
9183  visitVariable(variable) {}
9184
9185  visitReference(reference) {}
9186
9187  visitTextAttribute(attribute) {}
9188
9189  visitBoundAttribute(attribute) {}
9190
9191  visitBoundEvent(attribute) {}
9192
9193  visitText(text) {}
9194
9195  visitBoundText(text) {}
9196
9197  visitIcu(icu) {}
9198
9199}
9200
9201class RecursiveVisitor$1 {
9202  visitElement(element) {
9203    visitAll$1(this, element.attributes);
9204    visitAll$1(this, element.inputs);
9205    visitAll$1(this, element.outputs);
9206    visitAll$1(this, element.children);
9207    visitAll$1(this, element.references);
9208  }
9209
9210  visitTemplate(template) {
9211    visitAll$1(this, template.attributes);
9212    visitAll$1(this, template.inputs);
9213    visitAll$1(this, template.outputs);
9214    visitAll$1(this, template.children);
9215    visitAll$1(this, template.references);
9216    visitAll$1(this, template.variables);
9217  }
9218
9219  visitContent(content) {}
9220
9221  visitVariable(variable) {}
9222
9223  visitReference(reference) {}
9224
9225  visitTextAttribute(attribute) {}
9226
9227  visitBoundAttribute(attribute) {}
9228
9229  visitBoundEvent(attribute) {}
9230
9231  visitText(text) {}
9232
9233  visitBoundText(text) {}
9234
9235  visitIcu(icu) {}
9236
9237}
9238
9239class TransformVisitor {
9240  visitElement(element) {
9241    const newAttributes = transformAll(this, element.attributes);
9242    const newInputs = transformAll(this, element.inputs);
9243    const newOutputs = transformAll(this, element.outputs);
9244    const newChildren = transformAll(this, element.children);
9245    const newReferences = transformAll(this, element.references);
9246
9247    if (newAttributes != element.attributes || newInputs != element.inputs || newOutputs != element.outputs || newChildren != element.children || newReferences != element.references) {
9248      return new Element$1(element.name, newAttributes, newInputs, newOutputs, newChildren, newReferences, element.sourceSpan, element.startSourceSpan, element.endSourceSpan);
9249    }
9250
9251    return element;
9252  }
9253
9254  visitTemplate(template) {
9255    const newAttributes = transformAll(this, template.attributes);
9256    const newInputs = transformAll(this, template.inputs);
9257    const newOutputs = transformAll(this, template.outputs);
9258    const newTemplateAttrs = transformAll(this, template.templateAttrs);
9259    const newChildren = transformAll(this, template.children);
9260    const newReferences = transformAll(this, template.references);
9261    const newVariables = transformAll(this, template.variables);
9262
9263    if (newAttributes != template.attributes || newInputs != template.inputs || newOutputs != template.outputs || newTemplateAttrs != template.templateAttrs || newChildren != template.children || newReferences != template.references || newVariables != template.variables) {
9264      return new Template(template.tagName, newAttributes, newInputs, newOutputs, newTemplateAttrs, newChildren, newReferences, newVariables, template.sourceSpan, template.startSourceSpan, template.endSourceSpan);
9265    }
9266
9267    return template;
9268  }
9269
9270  visitContent(content) {
9271    return content;
9272  }
9273
9274  visitVariable(variable) {
9275    return variable;
9276  }
9277
9278  visitReference(reference) {
9279    return reference;
9280  }
9281
9282  visitTextAttribute(attribute) {
9283    return attribute;
9284  }
9285
9286  visitBoundAttribute(attribute) {
9287    return attribute;
9288  }
9289
9290  visitBoundEvent(attribute) {
9291    return attribute;
9292  }
9293
9294  visitText(text) {
9295    return text;
9296  }
9297
9298  visitBoundText(text) {
9299    return text;
9300  }
9301
9302  visitIcu(icu) {
9303    return icu;
9304  }
9305
9306}
9307
9308function visitAll$1(visitor, nodes) {
9309  const result = [];
9310
9311  if (visitor.visit) {
9312    for (const node of nodes) {
9313      const newNode = visitor.visit(node) || node.visit(visitor);
9314    }
9315  } else {
9316    for (const node of nodes) {
9317      const newNode = node.visit(visitor);
9318
9319      if (newNode) {
9320        result.push(newNode);
9321      }
9322    }
9323  }
9324
9325  return result;
9326}
9327
9328function transformAll(visitor, nodes) {
9329  const result = [];
9330  let changed = false;
9331
9332  for (const node of nodes) {
9333    const newNode = node.visit(visitor);
9334
9335    if (newNode) {
9336      result.push(newNode);
9337    }
9338
9339    changed = changed || newNode != node;
9340  }
9341
9342  return changed ? result : nodes;
9343}
9344/**
9345 * @license
9346 * Copyright Google LLC All Rights Reserved.
9347 *
9348 * Use of this source code is governed by an MIT-style license that can be
9349 * found in the LICENSE file at https://angular.io/license
9350 */
9351
9352
9353class Message {
9354  /**
9355   * @param nodes message AST
9356   * @param placeholders maps placeholder names to static content and their source spans
9357   * @param placeholderToMessage maps placeholder names to messages (used for nested ICU messages)
9358   * @param meaning
9359   * @param description
9360   * @param customId
9361   */
9362  constructor(nodes, placeholders, placeholderToMessage, meaning, description, customId) {
9363    this.nodes = nodes;
9364    this.placeholders = placeholders;
9365    this.placeholderToMessage = placeholderToMessage;
9366    this.meaning = meaning;
9367    this.description = description;
9368    this.customId = customId;
9369    this.id = this.customId;
9370    /** The ids to use if there are no custom id and if `i18nLegacyMessageIdFormat` is not empty */
9371
9372    this.legacyIds = [];
9373    this.messageString = serializeMessage(this.nodes);
9374
9375    if (nodes.length) {
9376      this.sources = [{
9377        filePath: nodes[0].sourceSpan.start.file.url,
9378        startLine: nodes[0].sourceSpan.start.line + 1,
9379        startCol: nodes[0].sourceSpan.start.col + 1,
9380        endLine: nodes[nodes.length - 1].sourceSpan.end.line + 1,
9381        endCol: nodes[0].sourceSpan.start.col + 1
9382      }];
9383    } else {
9384      this.sources = [];
9385    }
9386  }
9387
9388}
9389
9390class Text$2 {
9391  constructor(value, sourceSpan) {
9392    this.value = value;
9393    this.sourceSpan = sourceSpan;
9394  }
9395
9396  visit(visitor, context) {
9397    return visitor.visitText(this, context);
9398  }
9399
9400} // TODO(vicb): do we really need this node (vs an array) ?
9401
9402
9403class Container {
9404  constructor(children, sourceSpan) {
9405    this.children = children;
9406    this.sourceSpan = sourceSpan;
9407  }
9408
9409  visit(visitor, context) {
9410    return visitor.visitContainer(this, context);
9411  }
9412
9413}
9414
9415class Icu {
9416  constructor(expression, type, cases, sourceSpan) {
9417    this.expression = expression;
9418    this.type = type;
9419    this.cases = cases;
9420    this.sourceSpan = sourceSpan;
9421  }
9422
9423  visit(visitor, context) {
9424    return visitor.visitIcu(this, context);
9425  }
9426
9427}
9428
9429class TagPlaceholder {
9430  constructor(tag, attrs, startName, closeName, children, isVoid, // TODO sourceSpan should cover all (we need a startSourceSpan and endSourceSpan)
9431  sourceSpan, startSourceSpan, endSourceSpan) {
9432    this.tag = tag;
9433    this.attrs = attrs;
9434    this.startName = startName;
9435    this.closeName = closeName;
9436    this.children = children;
9437    this.isVoid = isVoid;
9438    this.sourceSpan = sourceSpan;
9439    this.startSourceSpan = startSourceSpan;
9440    this.endSourceSpan = endSourceSpan;
9441  }
9442
9443  visit(visitor, context) {
9444    return visitor.visitTagPlaceholder(this, context);
9445  }
9446
9447}
9448
9449class Placeholder {
9450  constructor(value, name, sourceSpan) {
9451    this.value = value;
9452    this.name = name;
9453    this.sourceSpan = sourceSpan;
9454  }
9455
9456  visit(visitor, context) {
9457    return visitor.visitPlaceholder(this, context);
9458  }
9459
9460}
9461
9462class IcuPlaceholder {
9463  constructor(value, name, sourceSpan) {
9464    this.value = value;
9465    this.name = name;
9466    this.sourceSpan = sourceSpan;
9467  }
9468
9469  visit(visitor, context) {
9470    return visitor.visitIcuPlaceholder(this, context);
9471  }
9472
9473} // Clone the AST
9474
9475
9476class CloneVisitor {
9477  visitText(text, context) {
9478    return new Text$2(text.value, text.sourceSpan);
9479  }
9480
9481  visitContainer(container, context) {
9482    const children = container.children.map(n => n.visit(this, context));
9483    return new Container(children, container.sourceSpan);
9484  }
9485
9486  visitIcu(icu, context) {
9487    const cases = {};
9488    Object.keys(icu.cases).forEach(key => cases[key] = icu.cases[key].visit(this, context));
9489    const msg = new Icu(icu.expression, icu.type, cases, icu.sourceSpan);
9490    msg.expressionPlaceholder = icu.expressionPlaceholder;
9491    return msg;
9492  }
9493
9494  visitTagPlaceholder(ph, context) {
9495    const children = ph.children.map(n => n.visit(this, context));
9496    return new TagPlaceholder(ph.tag, ph.attrs, ph.startName, ph.closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
9497  }
9498
9499  visitPlaceholder(ph, context) {
9500    return new Placeholder(ph.value, ph.name, ph.sourceSpan);
9501  }
9502
9503  visitIcuPlaceholder(ph, context) {
9504    return new IcuPlaceholder(ph.value, ph.name, ph.sourceSpan);
9505  }
9506
9507} // Visit all the nodes recursively
9508
9509
9510class RecurseVisitor {
9511  visitText(text, context) {}
9512
9513  visitContainer(container, context) {
9514    container.children.forEach(child => child.visit(this));
9515  }
9516
9517  visitIcu(icu, context) {
9518    Object.keys(icu.cases).forEach(k => {
9519      icu.cases[k].visit(this);
9520    });
9521  }
9522
9523  visitTagPlaceholder(ph, context) {
9524    ph.children.forEach(child => child.visit(this));
9525  }
9526
9527  visitPlaceholder(ph, context) {}
9528
9529  visitIcuPlaceholder(ph, context) {}
9530
9531}
9532/**
9533 * Serialize the message to the Localize backtick string format that would appear in compiled code.
9534 */
9535
9536
9537function serializeMessage(messageNodes) {
9538  const visitor = new LocalizeMessageStringVisitor();
9539  const str = messageNodes.map(n => n.visit(visitor)).join('');
9540  return str;
9541}
9542
9543class LocalizeMessageStringVisitor {
9544  visitText(text) {
9545    return text.value;
9546  }
9547
9548  visitContainer(container) {
9549    return container.children.map(child => child.visit(this)).join('');
9550  }
9551
9552  visitIcu(icu) {
9553    const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
9554    return `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`;
9555  }
9556
9557  visitTagPlaceholder(ph) {
9558    const children = ph.children.map(child => child.visit(this)).join('');
9559    return `{$${ph.startName}}${children}{$${ph.closeName}}`;
9560  }
9561
9562  visitPlaceholder(ph) {
9563    return `{$${ph.name}}`;
9564  }
9565
9566  visitIcuPlaceholder(ph) {
9567    return `{$${ph.name}}`;
9568  }
9569
9570}
9571/**
9572 * @license
9573 * Copyright Google LLC All Rights Reserved.
9574 *
9575 * Use of this source code is governed by an MIT-style license that can be
9576 * found in the LICENSE file at https://angular.io/license
9577 */
9578
9579
9580class Serializer {
9581  // Creates a name mapper, see `PlaceholderMapper`
9582  // Returning `null` means that no name mapping is used.
9583  createNameMapper(message) {
9584    return null;
9585  }
9586
9587}
9588/**
9589 * A simple mapper that take a function to transform an internal name to a public name
9590 */
9591
9592
9593class SimplePlaceholderMapper extends RecurseVisitor {
9594  // create a mapping from the message
9595  constructor(message, mapName) {
9596    super();
9597    this.mapName = mapName;
9598    this.internalToPublic = {};
9599    this.publicToNextId = {};
9600    this.publicToInternal = {};
9601    message.nodes.forEach(node => node.visit(this));
9602  }
9603
9604  toPublicName(internalName) {
9605    return this.internalToPublic.hasOwnProperty(internalName) ? this.internalToPublic[internalName] : null;
9606  }
9607
9608  toInternalName(publicName) {
9609    return this.publicToInternal.hasOwnProperty(publicName) ? this.publicToInternal[publicName] : null;
9610  }
9611
9612  visitText(text, context) {
9613    return null;
9614  }
9615
9616  visitTagPlaceholder(ph, context) {
9617    this.visitPlaceholderName(ph.startName);
9618    super.visitTagPlaceholder(ph, context);
9619    this.visitPlaceholderName(ph.closeName);
9620  }
9621
9622  visitPlaceholder(ph, context) {
9623    this.visitPlaceholderName(ph.name);
9624  }
9625
9626  visitIcuPlaceholder(ph, context) {
9627    this.visitPlaceholderName(ph.name);
9628  } // XMB placeholders could only contains A-Z, 0-9 and _
9629
9630
9631  visitPlaceholderName(internalName) {
9632    if (!internalName || this.internalToPublic.hasOwnProperty(internalName)) {
9633      return;
9634    }
9635
9636    let publicName = this.mapName(internalName);
9637
9638    if (this.publicToInternal.hasOwnProperty(publicName)) {
9639      // Create a new XMB when it has already been used
9640      const nextId = this.publicToNextId[publicName];
9641      this.publicToNextId[publicName] = nextId + 1;
9642      publicName = `${publicName}_${nextId}`;
9643    } else {
9644      this.publicToNextId[publicName] = 1;
9645    }
9646
9647    this.internalToPublic[internalName] = publicName;
9648    this.publicToInternal[publicName] = internalName;
9649  }
9650
9651}
9652/**
9653 * @license
9654 * Copyright Google LLC All Rights Reserved.
9655 *
9656 * Use of this source code is governed by an MIT-style license that can be
9657 * found in the LICENSE file at https://angular.io/license
9658 */
9659
9660
9661class _Visitor$2 {
9662  visitTag(tag) {
9663    const strAttrs = this._serializeAttributes(tag.attrs);
9664
9665    if (tag.children.length == 0) {
9666      return `<${tag.name}${strAttrs}/>`;
9667    }
9668
9669    const strChildren = tag.children.map(node =>
9669 node.visit(this));
9670    return `<${tag.name}${strAttrs}>${strChildren.join('')}</${tag.name}>`;
9671  }
9672
9673  visitText(text) {
9674    return text.value;
9675  }
9676
9677  visitDeclaration(decl) {
9678    return `<?xml${this._serializeAttributes(decl.attrs)} ?>`;
9679  }
9680
9681  _serializeAttributes(attrs) {
9682    const strAttrs = Object.keys(attrs).map(name => `${name}="${attrs[name]}"`).join(' ');
9683    return strAttrs.length > 0 ? ' ' + strAttrs : '';
9684  }
9685
9686  visitDoctype(doctype) {
9687    return `<!DOCTYPE ${doctype.rootTag} [\n${doctype.dtd}\n]>`;
9688  }
9689
9690}
9691
9692const _visitor = new _Visitor$2();
9693
9694function serialize(nodes) {
9695  return nodes.map(node => node.visit(_visitor)).join('');
9696}
9697
9698class Declaration {
9699  constructor(unescapedAttrs) {
9700    this.attrs = {};
9701    Object.keys(unescapedAttrs).forEach(k => {
9702      this.attrs[k] = escapeXml(unescapedAttrs[k]);
9703    });
9704  }
9705
9706  visit(visitor) {
9707    return visitor.visitDeclaration(this);
9708  }
9709
9710}
9711
9712class Doctype {
9713  constructor(rootTag, dtd) {
9714    this.rootTag = rootTag;
9715    this.dtd = dtd;
9716  }
9717
9718  visit(visitor) {
9719    return visitor.visitDoctype(this);
9720  }
9721
9722}
9723
9724class Tag {
9725  constructor(name, unescapedAttrs = {}, children = []) {
9726    this.name = name;
9727    this.children = children;
9728    this.attrs = {};
9729    Object.keys(unescapedAttrs).forEach(k => {
9730      this.attrs[k] = escapeXml(unescapedAttrs[k]);
9731    });
9732  }
9733
9734  visit(visitor) {
9735    return visitor.visitTag(this);
9736  }
9737
9738}
9739
9740class Text$1 {
9741  constructor(unescapedValue) {
9742    this.value = escapeXml(unescapedValue);
9743  }
9744
9745  visit(visitor) {
9746    return visitor.visitText(this);
9747  }
9748
9749}
9750
9751class CR extends Text$1 {
9752  constructor(ws = 0) {
9753    super(`\n${new Array(ws + 1).join(' ')}`);
9754  }
9755
9756}
9757
9758const _ESCAPED_CHARS = [[/&/g, '&amp;'], [/"/g, '&quot;'], [/'/g, '&apos;'], [/</g, '&lt;'], [/>/g, '&gt;']]; // Escape `_ESCAPED_CHARS` characters in the given text with encoded entities
9759
9760function escapeXml(text) {
9761  return _ESCAPED_CHARS.reduce((text, entry) => text.replace(entry[0], entry[1]), text);
9762}
9763/**
9764 * @license
9765 * Copyright Google LLC All Rights Reserved.
9766 *
9767 * Use of this source code is governed by an MIT-style license that can be
9768 * found in the LICENSE file at https://angular.io/license
9769 */
9770
9771
9772const _MESSAGES_TAG = 'messagebundle';
9773const _MESSAGE_TAG = 'msg';
9774const _PLACEHOLDER_TAG$3 = 'ph';
9775const _EXAMPLE_TAG = 'ex';
9776const _SOURCE_TAG$2 = 'source';
9777const _DOCTYPE = `<!ELEMENT messagebundle (msg)*>
9778<!ATTLIST messagebundle class CDATA #IMPLIED>
9779
9780<!ELEMENT msg (#PCDATA|ph|source)*>
9781<!ATTLIST msg id CDATA #IMPLIED>
9782<!ATTLIST msg seq CDATA #IMPLIED>
9783<!ATTLIST msg name CDATA #IMPLIED>
9784<!ATTLIST msg desc CDATA #IMPLIED>
9785<!ATTLIST msg meaning CDATA #IMPLIED>
9786<!ATTLIST msg obsolete (obsolete) #IMPLIED>
9787<!ATTLIST msg xml:space (default|preserve) "default">
9788<!ATTLIST msg is_hidden CDATA #IMPLIED>
9789
9790<!ELEMENT source (#PCDATA)>
9791
9792<!ELEMENT ph (#PCDATA|ex)*>
9793<!ATTLIST ph name CDATA #REQUIRED>
9794
9795<!ELEMENT ex (#PCDATA)>`;
9796
9797class Xmb extends Serializer {
9798  write(messages, locale) {
9799    const exampleVisitor = new ExampleVisitor();
9800    const visitor = new _Visitor$1();
9801    let rootNode = new Tag(_MESSAGES_TAG);
9802    messages.forEach(message => {
9803      const attrs = {
9804        id: message.id
9805      };
9806
9807      if (message.description) {
9808        attrs['desc'] = message.description;
9809      }
9810
9811      if (message.meaning) {
9812        attrs['meaning'] = message.meaning;
9813      }
9814
9815      let sourceTags = [];
9816      message.sources.forEach(source => {
9817        sourceTags.push(new Tag(_SOURCE_TAG$2, {}, [new Text$1(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));
9818      });
9819      rootNode.children.push(new CR(2), new Tag(_MESSAGE_TAG, attrs, [...sourceTags, ...visitor.serialize(message.nodes)]));
9820    });
9821    rootNode.children.push(new CR());
9822    return serialize([new Declaration({
9823      version: '1.0',
9824      encoding: 'UTF-8'
9825    }), new CR(), new Doctype(_MESSAGES_TAG, _DOCTYPE), new CR(), exampleVisitor.addDefaultExamples(rootNode), new CR()]);
9826  }
9827
9828  load(content, url) {
9829    throw new Error('Unsupported');
9830  }
9831
9832  digest(message) {
9833    return digest(message);
9834  }
9835
9836  createNameMapper(message) {
9837    return new SimplePlaceholderMapper(message, toPublicName);
9838  }
9839
9840}
9841
9842class _Visitor$1 {
9843  visitText(text, context) {
9844    return [new Text$1(text.value)];
9845  }
9846
9847  visitContainer(container, context) {
9848    const nodes = [];
9849    container.children.forEach(node => nodes.push(...node.visit(this)));
9850    return nodes;
9851  }
9852
9853  visitIcu(icu, context) {
9854    const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
9855    Object.keys(icu.cases).forEach(c => {
9856      nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `));
9857    });
9858    nodes.push(new Text$1(`}`));
9859    return nodes;
9860  }
9861
9862  visitTagPlaceholder(ph, context) {
9863    const startTagAsText = new Text$1(`<${ph.tag}>`);
9864    const startEx = new Tag(_EXAMPLE_TAG, {}, [startTagAsText]); // TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
9865
9866    const startTagPh = new Tag(_PLACEHOLDER_TAG$3, {
9867      name: ph.startName
9868    }, [startEx, startTagAsText]);
9869
9870    if (ph.isVoid) {
9871      // void tags have no children nor closing tags
9872      return [startTagPh];
9873    }
9874
9875    const closeTagAsText = new Text$1(`</${ph.tag}>`);
9876    const closeEx = new Tag(_EXAMPLE_TAG, {}, [closeTagAsText]); // TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
9877
9878    const closeTagPh = new Tag(_PLACEHOLDER_TAG$3, {
9879      name: ph.closeName
9880    }, [closeEx, closeTagAsText]);
9881    return [startTagPh, ...this.serialize(ph.children), closeTagPh];
9882  }
9883
9884  visitPlaceholder(ph, context) {
9885    const interpolationAsText = new Text$1(`{{${ph.value}}}`); // Example tag needs to be not-empty for TC.
9886
9887    const exTag = new Tag(_EXAMPLE_TAG, {}, [interpolationAsText]);
9888    return [// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
9889    new Tag(_PLACEHOLDER_TAG$3, {
9890      name: ph.name
9891    }, [exTag, interpolationAsText])];
9892  }
9893
9894  visitIcuPlaceholder(ph, context) {
9895    const icuExpression = ph.value.expression;
9896    const icuType = ph.value.type;
9897    const icuCases = Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ');
9898    const icuAsText = new Text$1(`{${icuExpression}, ${icuType}, ${icuCases}}`);
9899    const exTag = new Tag(_EXAMPLE_TAG, {}, [icuAsText]);
9900    return [// TC requires PH to have a non empty EX, and uses the text node to show the "original" value.
9901    new Tag(_PLACEHOLDER_TAG$3, {
9902      name: ph.name
9903    }, [exTag, icuAsText])];
9904  }
9905
9906  serialize(nodes) {
9907    return [].concat(...nodes.map(node => node.visit(this)));
9908  }
9909
9910}
9911
9912function digest(message) {
9913  return decimalDigest(message);
9914} // TC requires at least one non-empty example on placeholders
9915
9916
9917class ExampleVisitor {
9918  addDefaultExamples(node) {
9919    node.visit(this);
9920    return node;
9921  }
9922
9923  visitTag(tag) {
9924    if (tag.name === _PLACEHOLDER_TAG$3) {
9925      if (!tag.children || tag.children.length == 0) {
9926        const exText = new Text$1(tag.attrs['name'] || '...');
9927        tag.children = [new Tag(_EXAMPLE_TAG, {}, [exText])];
9928      }
9929    } else if (tag.children) {
9930      tag.children.forEach(node => node.visit(this));
9931    }
9932  }
9933
9934  visitText(text) {}
9935
9936  visitDeclaration(decl) {}
9937
9938  visitDoctype(doctype) {}
9939
9940} // XMB/XTB placeholders can only contain A-Z, 0-9 and _
9941
9942
9943function toPublicName(internalName) {
9944  return internalName.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
9945}
9946/**
9947 * @license
9948 * Copyright Google LLC All Rights Reserved.
9949 *
9950 * Use of this source code is governed by an MIT-style license that can be
9951 * found in the LICENSE file at https://angular.io/license
9952 */
9953
9954/* Closure variables holding messages must be named `MSG_[A-Z0-9]+` */
9955
9956
9957const CLOSURE_TRANSLATION_VAR_PREFIX = 'MSG_';
9958/**
9959 * Prefix for non-`goog.getMsg` i18n-related vars.
9960 * Note: the prefix uses lowercase characters intentionally due to a Closure behavior that
9961 * considers variables like `I18N_0` as constants and throws an error when their value changes.
9962 */
9963
9964const TRANSLATION_VAR_PREFIX = 'i18n_';
9965/** Name of the i18n attributes **/
9966
9967const I18N_ATTR = 'i18n';
9968const I18N_ATTR_PREFIX = 'i18n-';
9969/** Prefix of var expressions used in ICUs */
9970
9971const I18N_ICU_VAR_PREFIX = 'VAR_';
9972/** Prefix of ICU expressions for post processing */
9973
9974const I18N_ICU_MAPPING_PREFIX = 'I18N_EXP_';
9975/** Placeholder wrapper for i18n expressions **/
9976
9977const I18N_PLACEHOLDER_SYMBOL = '�';
9978
9979function isI18nAttribute(name) {
9980  return name === I18N_ATTR || name.startsWith(I18N_ATTR_PREFIX);
9981}
9982
9983function isI18nRootNode(meta) {
9984  return meta instanceof Message;
9985}
9986
9987function isSingleI18nIcu(meta) {
9988  return isI18nRootNode(meta) && meta.nodes.length === 1 && meta.nodes[0] instanceof Icu;
9989}
9990
9991function hasI18nMeta(node) {
9992  return !!node.i18n;
9993}
9994
9995function hasI18nAttrs(element) {
9996  return element.attrs.some(attr => isI18nAttribute(attr.name));
9997}
9998
9999function icuFromI18nMessage(message) {
10000  return message.nodes[0];
10001}
10002
10003function wrapI18nPlaceholder(content, contextId = 0) {
10004  const blockId = contextId > 0 ? `:${contextId}` : '';
10005  return `${I18N_PLACEHOLDER_SYMBOL}${content}${blockId}${I18N_PLACEHOLDER_SYMBOL}`;
10006}
10007
10008function assembleI18nBoundString(strings, bindingStartIndex = 0, contextId = 0) {
10009  if (!strings.length) return '';
10010  let acc = '';
10011  const lastIdx = strings.length - 1;
10012
10013  for (let i = 0; i < lastIdx; i++) {
10014    acc += `${strings[i]}${wrapI18nPlaceholder(bindingStartIndex + i, contextId)}`;
10015  }
10016
10017  acc += strings[lastIdx];
10018  return acc;
10019}
10020
10021function getSeqNumberGenerator(startsAt = 0) {
10022  let current = startsAt;
10023  return () => current++;
10024}
10025
10026function placeholdersToParams(placeholders) {
10027  const params = {};
10028  placeholders.forEach((values, key) => {
10029    params[key] = literal(values.length > 1 ? `[${values.join('|')}]` : values[0]);
10030  });
10031  return params;
10032}
10033
10034function updatePlaceholderMap(map, name, ...values) {
10035  const current = map.get(name) || [];
10036  current.push(...values);
10037  map.set(name, current);
10038}
10039
10040function assembleBoundTextPlaceholders(meta, bindingStartIndex = 0, contextId = 0) {
10041  const startIdx = bindingStartIndex;
10042  const placeholders = new Map();
10043  const node = meta instanceof Message ? meta.nodes.find(node => node instanceof Container) : meta;
10044
10045  if (node) {
10046    node.children.filter(child => child instanceof Placeholder).forEach((child, idx) => {
10047      const content = wrapI18nPlaceholder(startIdx + idx, contextId);
10048      updatePlaceholderMap(placeholders, child.name, content);
10049    });
10050  }
10051
10052  return placeholders;
10053}
10054/**
10055 * Format the placeholder names in a map of placeholders to expressions.
10056 *
10057 * The placeholder names are converted from "internal" format (e.g. `START_TAG_DIV_1`) to "external"
10058 * format (e.g. `startTagDiv_1`).
10059 *
10060 * @param params A map of placeholder names to expressions.
10061 * @param useCamelCase whether to camelCase the placeholder name when formatting.
10062 * @returns A new map of formatted placeholder names to expressions.
10063 */
10064
10065
10066function formatI18nPlaceholderNamesInMap(params = {}, useCamelCase) {
10067  const _params = {};
10068
10069  if (params && Object.keys(params).length) {
10070    Object.keys(params).forEach(key => _params[formatI18nPlaceholderName(key, useCamelCase)] = params[key]);
10071  }
10072
10073  return _params;
10074}
10075/**
10076 * Converts internal placeholder names to public-facing format
10077 * (for example to use in goog.getMsg call).
10078 * Example: `START_TAG_DIV_1` is converted to `startTagDiv_1`.
10079 *
10080 * @param name The placeholder name that should be formatted
10081 * @returns Formatted placeholder name
10082 */
10083
10084
10085function formatI18nPlaceholderName(name, useCamelCase = true) {
10086  const publicName = toPublicName(name);
10087
10088  if (!useCamelCase) {
10089    return publicName;
10090  }
10091
10092  const chunks = publicName.split('_');
10093
10094  if (chunks.length === 1) {
10095    // if no "_" found - just lowercase the value
10096    return name.toLowerCase();
10097  }
10098
10099  let postfix; // eject last element if it's a number
10100
10101  if (/^\d+$/.test(chunks[chunks.length - 1])) {
10102    postfix = chunks.pop();
10103  }
10104
10105  let raw = chunks.shift().toLowerCase();
10106
10107  if (chunks.length) {
10108    raw += chunks.map(c => c.charAt(0).toUpperCase() + c.slice(1).toLowerCase()).join('');
10109  }
10110
10111  return postfix ? `${raw}_${postfix}` : raw;
10112}
10113/**
10114 * Generates a prefix for translation const name.
10115 *
10116 * @param extra Additional local prefix that should be injected into translation var name
10117 * @returns Complete translation const prefix
10118 */
10119
10120
10121function getTranslationConstPrefix(extra) {
10122  return `${CLOSURE_TRANSLATION_VAR_PREFIX}${extra}`.toUpperCase();
10123}
10124/**
10125 * Generate AST to declare a variable. E.g. `var I18N_1;`.
10126 * @param variable the name of the variable to declare.
10127 */
10128
10129
10130function declareI18nVariable(variable) {
10131  return new DeclareVarStmt(variable.name, undefined, INFERRED_TYPE, undefined, variable.sourceSpan);
10132}
10133/**
10134 * @license
10135 * Copyright Google LLC All Rights Reserved.
10136 *
10137 * Use of this source code is governed by an MIT-style license that can be
10138 * found in the LICENSE file at https://angular.io/license
10139 */
10140
10141/**
10142 * Checks whether an object key contains potentially unsafe chars, thus the key should be wrapped in
10143 * quotes. Note: we do not wrap all keys into quotes, as it may have impact on minification and may
10144 * bot work in some cases when object keys are mangled by minifier.
10145 *
10146 * TODO(FW-1136): this is a temporary solution, we need to come up with a better way of working with
10147 * inputs that contain potentially unsafe chars.
10148 */
10149
10150
10151const UNSAFE_OBJECT_KEY_NAME_REGEXP = /[-.]/;
10152/** Name of the temporary to use during data binding */
10153
10154const TEMPORARY_NAME = '_t';
10155/** Name of the context parameter passed into a template function */
10156
10157const CONTEXT_NAME = 'ctx';
10158/** Name of the RenderFlag passed into a template function */
10159
10160const RENDER_FLAGS = 'rf';
10161/** The prefix reference variables */
10162
10163const REFERENCE_PREFIX = '_r';
10164/** The name of the implicit context reference */
10165
10166const IMPLICIT_REFERENCE = '$implicit';
10167/** Non bindable attribute name **/
10168
10169const NON_BINDABLE_ATTR = 'ngNonBindable';
10170/** Name for the variable keeping track of the context returned by `ɵɵrestoreView`. */
10171
10172const RESTORED_VIEW_CONTEXT_NAME = 'restoredCtx';
10173/**
10174 * Maximum length of a single instruction chain. Because our output AST uses recursion, we're
10175 * limited in how many expressions we can nest before we reach the call stack limit. This
10176 * length is set very conservatively in order to reduce the chance of problems.
10177 */
10178
10179const MAX_CHAIN_LENGTH = 500;
10180/** Instructions that support chaining. */
10181
10182const CHAINABLE_INSTRUCTIONS = new Set([Identifiers.element, Identifiers.elementStart, Identifiers.elementEnd, Identifiers.elementContainer, Identifiers.elementContainerStart, Identifiers.elementContainerEnd, Identifiers.i18nExp, Identifiers.listener, Identifiers.classProp, Identifiers.syntheticHostListener, Identifiers.hostProperty, Identifiers.syntheticHostProperty, Identifiers.property, Identifiers.propertyInterpolate1, Identifiers.propertyInterpolate2, Identifiers.propertyInterpolate3, Identifiers.propertyInterpolate4, Identifiers.propertyInterpolate5, Identifiers.propertyInterpolate6, Identifiers.propertyInterpolate7, Identifiers.propertyInterpolate8, Identifiers.propertyInterpolateV, Identifiers.attribute, Identifiers.attributeInterpolate1, Identifiers.attributeInterpolate2, Identifiers.attributeInterpolate3, Identifiers.attributeInterpolate4, Identifiers.attributeInterpolate5, Identifiers.attributeInterpolate6, Identifiers.attributeInterpolate7, Identifiers.attributeInterpolate8, Identifiers.attributeInterpolateV, Identifiers.styleProp, Identifiers.stylePropInterpolate1, Identifiers.stylePropInterpolate2, Identifiers.stylePropInterpolate3, Identifiers.stylePropInterpolate4, Identifiers.stylePropInterpolate5, Identifiers.stylePropInterpolate6, Identifiers.stylePropInterpolate7, Identifiers.stylePropInterpolate8, Identifiers.stylePropInterpolateV, Identifiers.textInterpolate, Identifiers.textInterpolate1, Identifiers.textInterpolate2, Identifiers.textInterpolate3, Identifiers.textInterpolate4, Identifiers.textInterpolate5, Identifiers.textInterpolate6, Identifiers.textInterpolate7, Identifiers.textInterpolate8, Identifiers.textInterpolateV]);
10183/** Generates a call to a single instruction. */
10184
10185function invokeInstruction(span, reference, params) {
10186  return importExpr(reference, null, span).callFn(params, span);
10187}
10188/**
10189 * Creates an allocator for a temporary variable.
10190 *
10191 * A variable declaration is added to the statements the first time the allocator is invoked.
10192 */
10193
10194
10195function temporaryAllocator(statements, name) {
10196  let temp = null;
10197  return () => {
10198    if (!temp) {
10199      statements.push(new DeclareVarStmt(TEMPORARY_NAME, undefined, DYNAMIC_TYPE));
10200      temp = variable(name);
10201    }
10202
10203    return temp;
10204  };
10205}
10206
10207function invalid(arg) {
10208  throw new Error(`Invalid state: Visitor ${this.constructor.name} doesn't handle ${arg.constructor.name}`);
10209}
10210
10211function asLiteral(value) {
10212  if (Array.isArray(value)) {
10213    return literalArr(value.map(asLiteral));
10214  }
10215
10216  return literal(value, INFERRED_TYPE);
10217}
10218
10219function conditionallyCreateMapObjectLiteral(keys, keepDeclared) {
10220  if (Object.getOwnPropertyNames(keys).length > 0) {
10221    return mapToExpression(keys, keepDeclared);
10222  }
10223
10224  return null;
10225}
10226
10227function mapToExpression(map, keepDeclared) {
10228  return literalMap(Object.getOwnPropertyNames(map).map(key => {
10229    // canonical syntax: `dirProp: publicProp`
10230    const value = map[key];
10231    let declaredName;
10232    let publicName;
10233    let minifiedName;
10234    let needsDeclaredName;
10235
10236    if (Array.isArray(value)) {
10237      [publicName, declaredName] = value;
10238      minifiedName = key;
10239      needsDeclaredName = publicName !== declaredName;
10240    } else {
10241      minifiedName = declaredName = key;
10242      publicName = value;
10243      needsDeclaredName = false;
10244    }
10245
10246    return {
10247      key: minifiedName,
10248      // put quotes around keys that contain potentially unsafe characters
10249      quoted: UNSAFE_OBJECT_KEY_NAME_REGEXP.test(minifiedName),
10250      value: keepDeclared && needsDeclaredName ? literalArr([asLiteral(publicName), asLiteral(declaredName)]) : asLiteral(publicName)
10251    };
10252  }));
10253}
10254/**
10255 *  Remove trailing null nodes as they are implied.
10256 */
10257
10258
10259function trimTrailingNulls(parameters) {
10260  while (isNull(parameters[parameters.length - 1])) {
10261    parameters.pop();
10262  }
10263
10264  return parameters;
10265}
10266
10267function getQueryPredicate(query, constantPool) {
10268  if (Array.isArray(query.predicate)) {
10269    let predicate = [];
10270    query.predicate.forEach(selector => {
10271      // Each item in predicates array may contain strings with comma-separated refs
10272      // (for ex. 'ref, ref1, ..., refN'), thus we extract individual refs and store them
10273      // as separate array entities
10274      const selectors = selector.split(',').map(token => literal(token.trim()));
10275      predicate.push(...selectors);
10276    });
10277    return constantPool.getConstLiteral(literalArr(predicate), true);
10278  } else {
10279    // The original predicate may have been wrapped in a `forwardRef()` call.
10280    switch (query.predicate.forwardRef) {
10281      case 0
10282      /* ForwardRefHandling.None */
10283      :
10284      case 2
10285      /* ForwardRefHandling.Unwrapped */
10286      :
10287        return query.predicate.expression;
10288
10289      case 1
10290      /* ForwardRefHandling.Wrapped */
10291      :
10292        return importExpr(Identifiers.resolveForwardRef).callFn([query.predicate.expression]);
10293    }
10294  }
10295}
10296/**
10297 * A representation for an object literal used during codegen of definition objects. The generic
10298 * type `T` allows to reference a documented type of the generated structure, such that the
10299 * property names that are set can be resolved to their documented declaration.
10300 */
10301
10302
10303class DefinitionMap {
10304  constructor() {
10305    this.values = [];
10306  }
10307
10308  set(key, value) {
10309    if (value) {
10310      this.values.push({
10311        key: key,
10312        value,
10313        quoted: false
10314      });
10315    }
10316  }
10317
10318  toLiteralMap() {
10319    return literalMap(this.values);
10320  }
10321
10322}
10323/**
10324 * Extract a map of properties to values for a given element or template node, which can be used
10325 * by the directive matching machinery.
10326 *
10327 * @param elOrTpl the element or template in question
10328 * @return an object set up for directive matching. For attributes on the element/template, this
10329 * object maps a property name to its (static) value. For any bindings, this map simply maps the
10330 * property name to an empty string.
10331 */
10332
10333
10334function getAttrsForDirectiveMatching(elOrTpl) {
10335  const attributesMap = {};
10336
10337  if (elOrTpl instanceof Template && elOrTpl.tagName !== 'ng-template') {
10338    elOrTpl.templateAttrs.forEach(a => attributesMap[a.name] = '');
10339  } else {
10340    elOrTpl.attributes.forEach(a => {
10341      if (!isI18nAttribute(a.name)) {
10342        attributesMap[a.name] = a.value;
10343      }
10344    });
10345    elOrTpl.inputs.forEach(i => {
10346      attributesMap[i.name] = '';
10347    });
10348    elOrTpl.outputs.forEach(o => {
10349      attributesMap[o.name] = '';
10350    });
10351  }
10352
10353  return attributesMap;
10354}
10355/**
10356 * Gets the number of arguments expected to be passed to a generated instruction in the case of
10357 * interpolation instructions.
10358 * @param interpolation An interpolation ast
10359 */
10360
10361
10362function getInterpolationArgsLength(interpolation) {
10363  const {
10364    expressions,
10365    strings
10366  } = interpolation;
10367
10368  if (expressions.length === 1 && strings.length === 2 && strings[0] === '' && strings[1] === '') {
10369    // If the interpolation has one interpolated value, but the prefix and suffix are both empty
10370    // strings, we only pass one argument, to a special instruction like `propertyInterpolate` or
10371    // `textInterpolate`.
10372    return 1;
10373  } else {
10374    return expressions.length + strings.length;
10375  }
10376}
10377/**
10378 * Generates the final instruction call statements based on the passed in configuration.
10379 * Will try to chain instructions as much as possible, if chaining is supported.
10380 */
10381
10382
10383function getInstructionStatements(instructions) {
10384  const statements = [];
10385  let pendingExpression = null;
10386  let pendingExpressionType = null;
10387  let chainLength = 0;
10388
10389  for (const current of instructions) {
10390    const resolvedParams = (typeof current.paramsOrFn === 'function' ? current.paramsOrFn() : current.paramsOrFn) ?? [];
10391    const params = Array.isArray(resolvedParams) ? resolvedParams : [resolvedParams]; // If the current instruction is the same as the previous one
10392    // and it can be chained, add another call to the chain.
10393
10394    if (chainLength < MAX_CHAIN_LENGTH && pendingExpressionType === current.reference && CHAINABLE_INSTRUCTIONS.has(pendingExpressionType)) {
10395      // We'll always have a pending expression when there's a pending expression type.
10396      pendingExpression = pendingExpression.callFn(params, pendingExpression.sourceSpan);
10397      chainLength++;
10398    } else {
10399      if (pendingExpression !== null) {
10400        statements.push(pendingExpression.toStmt());
10401      }
10402
10403      pendingExpression = invokeInstruction(current.span, current.reference, params);
10404      pendingExpressionType = current.reference;
10405      chainLength = 0;
10406    }
10407  } // Since the current instruction adds the previous one to the statements,
10408  // we may be left with the final one at the end that is still pending.
10409
10410
10411  if (pendingExpression !== null) {
10412    statements.push(pendingExpression.toStmt());
10413  }
10414
10415  return statements;
10416}
10417/**
10418 * @license
10419 * Copyright Google LLC All Rights Reserved.
10420 *
10421 * Use of this source code is governed by an MIT-style license that can be
10422 * found in the LICENSE file at https://angular.io/license
10423 */
10424
10425
10426function compileInjectable(meta, resolveForwardRefs) {
10427  let result = null;
10428  const factoryMeta = {
10429    name: meta.name,
10430    type: meta.type,
10431    internalType: meta.internalType,
10432    typeArgumentCount: meta.typeArgumentCount,
10433    deps: [],
10434    target: FactoryTarget$1.Injectable
10435  };
10436
10437  if (meta.useClass !== undefined) {
10438    // meta.useClass has two modes of operation. Either deps are specified, in which case `new` is
10439    // used to instantiate the class with dependencies injected, or deps are not specified and
10440    // the factory of the class is used to instantiate it.
10441    //
10442    // A special case exists for useClass: Type where Type is the injectable type itself and no
10443    // deps are specified, in which case 'useClass' is effectively ignored.
10444    const useClassOnSelf = meta.useClass.expression.isEquivalent(meta.internalType);
10445    let deps = undefined;
10446
10447    if (meta.deps !== undefined) {
10448      deps = meta.deps;
10449    }
10450
10451    if (deps !== undefined) {
10452      // factory: () => new meta.useClass(...deps)
10453      result = compileFactoryFunction({ ...factoryMeta,
10454        delegate: meta.useClass.expression,
10455        delegateDeps: deps,
10456        delegateType: R3FactoryDelegateType.Class
10457      });
10458    } else if (useClassOnSelf) {
10459      result = compileFactoryFunction(factoryMeta);
10460    } else {
10461      result = {
10462        statements: [],
10463        expression: delegateToFactory(meta.type.value, meta.useClass.expression, resolveForwardRefs)
10464      };
10465    }
10466  } else if (meta.useFactory !== undefined) {
10467    if (meta.deps !== undefined) {
10468      result = compileFactoryFunction({ ...factoryMeta,
10469        delegate: meta.useFactory,
10470        delegateDeps: meta.deps || [],
10471        delegateType: R3FactoryDelegateType.Function
10472      });
10473    } else {
10474      result = {
10475        statements: [],
10476        expression: fn([], [new ReturnStatement(meta.useFactory.callFn([]))])
10477      };
10478    }
10479  } else if (meta.useValue !== undefined) {
10480    // Note: it's safe to use `meta.useValue` instead of the `USE_VALUE in meta` check used for
10481    // client code because meta.useValue is an Expression which will be defined even if the actual
10482    // value is undefined.
10483    result = compileFactoryFunction({ ...factoryMeta,
10484      expression: meta.useValue.expression
10485    });
10486  } else if (meta.useExisting !== undefined) {
10487    // useExisting is an `inject` call on the existing token.
10488    result = compileFactoryFunction({ ...factoryMeta,
10489      expression: importExpr(Identifiers.inject).callFn([meta.useExisting.expression])
10490    });
10491  } else {
10492    result = {
10493      statements: [],
10494      expression: delegateToFactory(meta.type.value, meta.internalType, resolveForwardRefs)
10495    };
10496  }
10497
10498  const token = meta.internalType;
10499  const injectableProps = new DefinitionMap();
10500  injectableProps.set('token', token);
10501  injectableProps.set('factory', result.expression); // Only generate providedIn property if it has a non-null value
10502
10503  if (meta.providedIn.expression.value !== null) {
10504    injectableProps.set('providedIn', convertFromMaybeForwardRefExpression(meta.providedIn));
10505  }
10506
10507  const expression = importExpr(Identifiers.ɵɵdefineInjectable).callFn([injectableProps.toLiteralMap()], undefined, true);
10508  return {
10509    expression,
10510    type: createInjectableType(meta),
10511    statements: result.statements
10512  };
10513}
10514
10515function createInjectableType(meta) {
10516  return new ExpressionType(importExpr(Identifiers.InjectableDeclaration, [typeWithParameters(meta.type.type, meta.typeArgumentCount)]));
10517}
10518
10519function delegateToFactory(type, internalType, unwrapForwardRefs) {
10520  if (type.node === internalType.node) {
10521    // The types are the same, so we can simply delegate directly to the type's factory.
10522    // ```
10523    // factory: type.ɵfac
10524    // ```
10525    return internalType.prop('ɵfac');
10526  }
10527
10528  if (!unwrapForwardRefs) {
10529    // The type is not wrapped in a `forwardRef()`, so we create a simple factory function that
10530    // accepts a sub-type as an argument.
10531    // ```
10532    // factory: function(t) { return internalType.ɵfac(t); }
10533    // ```
10534    return createFactoryFunction(internalType);
10535  } // The internalType is actually wrapped in a `forwardRef()` so we need to resolve that before
10536  // calling its factory.
10537  // ```
10538  // factory: function(t) { return core.resolveForwardRef(type).ɵfac(t); }
10539  // ```
10540
10541
10542  const unwrappedType = importExpr(Identifiers.resolveForwardRef).callFn([internalType]);
10543  return createFactoryFunction(unwrappedType);
10544}
10545
10546function createFactoryFunction(type) {
10547  return fn([new FnParam('t', DYNAMIC_TYPE)], [new ReturnStatement
10547(type.prop('ɵfac').callFn([variable('t')]))]);
10548}
10549/**
10550 * @license
10551 * Copyright Google LLC All Rights Reserved.
10552 *
10553 * Use of this source code is governed by an MIT-style license that can be
10554 * found in the LICENSE file at https://angular.io/license
10555 */
10556
10557
10558const UNUSABLE_INTERPOLATION_REGEXPS = [/^\s*$/, /[<>]/, /^[{}]$/, /&(#|[a-z])/i, /^\/\// // comment
10559];
10560
10561function assertInterpolationSymbols(identifier, value) {
10562  if (value != null && !(Array.isArray(value) && value.length == 2)) {
10563    throw new Error(`Expected '${identifier}' to be an array, [start, end].`);
10564  } else if (value != null) {
10565    const start = value[0];
10566    const end = value[1]; // Check for unusable interpolation symbols
10567
10568    UNUSABLE_INTERPOLATION_REGEXPS.forEach(regexp => {
10569      if (regexp.test(start) || regexp.test(end)) {
10570        throw new Error(`['${start}', '${end}'] contains unusable interpolation symbol.`);
10571      }
10572    });
10573  }
10574}
10575/**
10576 * @license
10577 * Copyright Google LLC All Rights Reserved.
10578 *
10579 * Use of this source code is governed by an MIT-style license that can be
10580 * found in the LICENSE file at https://angular.io/license
10581 */
10582
10583
10584class InterpolationConfig {
10585  constructor(start, end) {
10586    this.start = start;
10587    this.end = end;
10588  }
10589
10590  static fromArray(markers) {
10591    if (!markers) {
10592      return DEFAULT_INTERPOLATION_CONFIG;
10593    }
10594
10595    assertInterpolationSymbols('interpolation', markers);
10596    return new InterpolationConfig(markers[0], markers[1]);
10597  }
10598
10599}
10600
10601const DEFAULT_INTERPOLATION_CONFIG = new InterpolationConfig('{{', '}}');
10602/**
10603 * @license
10604 * Copyright Google LLC All Rights Reserved.
10605 *
10606 * Use of this source code is governed by an MIT-style license that can be
10607 * found in the LICENSE file at https://angular.io/license
10608 */
10609
10610const $EOF = 0;
10611const $BSPACE = 8;
10612const $TAB = 9;
10613const $LF = 10;
10614const $VTAB = 11;
10615const $FF = 12;
10616const $CR = 13;
10617const $SPACE = 32;
10618const $BANG = 33;
10619const $DQ = 34;
10620const $HASH = 35;
10621const $$ = 36;
10622const $PERCENT = 37;
10623const $AMPERSAND = 38;
10624const $SQ = 39;
10625const $LPAREN = 40;
10626const $RPAREN = 41;
10627const $STAR = 42;
10628const $PLUS = 43;
10629const $COMMA = 44;
10630const $MINUS = 45;
10631const $PERIOD = 46;
10632const $SLASH = 47;
10633const $COLON = 58;
10634const $SEMICOLON = 59;
10635const $LT = 60;
10636const $EQ = 61;
10637const $GT = 62;
10638const $QUESTION = 63;
10639const $0 = 48;
10640const $7 = 55;
10641const $9 = 57;
10642const $A = 65;
10643const $E = 69;
10644const $F = 70;
10645const $X = 88;
10646const $Z = 90;
10647const $LBRACKET = 91;
10648const $BACKSLASH = 92;
10649const $RBRACKET = 93;
10650const $CARET = 94;
10651const $_ = 95;
10652const $a = 97;
10653const $b = 98;
10654const $e = 101;
10655const $f = 102;
10656const $n = 110;
10657const $r = 114;
10658const $t = 116;
10659const $u = 117;
10660const $v = 118;
10661const $x = 120;
10662const $z = 122;
10663const $LBRACE = 123;
10664const $BAR = 124;
10665const $RBRACE = 125;
10666const $NBSP = 160;
10667const $PIPE = 124;
10668const $TILDA = 126;
10669const $AT = 64;
10670const $BT = 96;
10671
10672function isWhitespace(code) {
10673  return code >= $TAB && code <= $SPACE || code == $NBSP;
10674}
10675
10676function isDigit(code) {
10677  return $0 <= code && code <= $9;
10678}
10679
10680function isAsciiLetter(code) {
10681  return code >= $a && code <= $z || code >= $A && code <= $Z;
10682}
10683
10684function isAsciiHexDigit(code) {
10685  return code >= $a && code <= $f || code >= $A && code <= $F || isDigit(code);
10686}
10687
10688function isNewLine(code) {
10689  return code === $LF || code === $CR;
10690}
10691
10692function isOctalDigit(code) {
10693  return $0 <= code && code <= $7;
10694}
10695
10696function isQuote(code) {
10697  return code === $SQ || code === $DQ || code === $BT;
10698}
10699/**
10700 * @license
10701 * Copyright Google LLC All Rights Reserved.
10702 *
10703 * Use of this source code is governed by an MIT-style license that can be
10704 * found in the LICENSE file at https://angular.io/license
10705 */
10706
10707
10708class ParseLocation {
10709  constructor(file, offset, line, col) {
10710    this.file = file;
10711    this.offset = offset;
10712    this.line = line;
10713    this.col = col;
10714  }
10715
10716  toString() {
10717    return this.offset != null ? `${this.file.url}@${this.line}:${this.col}` : this.file.url;
10718  }
10719
10720  moveBy(delta) {
10721    const source = this.file.content;
10722    const len = source.length;
10723    let offset = this.offset;
10724    let line = this.line;
10725    let col = this.col;
10726
10727    while (offset > 0 && delta < 0) {
10728      offset--;
10729      delta++;
10730      const ch = source.charCodeAt(offset);
10731
10732      if (ch == $LF) {
10733        line--;
10734        const priorLine = source.substring(0, offset - 1).lastIndexOf(String.fromCharCode($LF));
10735        col = priorLine > 0 ? offset - priorLine : offset;
10736      } else {
10737        col--;
10738      }
10739    }
10740
10741    while (offset < len && delta > 0) {
10742      const ch = source.charCodeAt(offset);
10743      offset++;
10744      delta--;
10745
10746      if (ch == $LF) {
10747        line++;
10748        col = 0;
10749      } else {
10750        col++;
10751      }
10752    }
10753
10754    return new ParseLocation(this.file, offset, line, col);
10755  } // Return the source around the location
10756  // Up to `maxChars` or `maxLines` on each side of the location
10757
10758
10759  getContext(maxChars, maxLines) {
10760    const content = this.file.content;
10761    let startOffset = this.offset;
10762
10763    if (startOffset != null) {
10764      if (startOffset > content.length - 1) {
10765        startOffset = content.length - 1;
10766      }
10767
10768      let endOffset = startOffset;
10769      let ctxChars = 0;
10770      let ctxLines = 0;
10771
10772      while (ctxChars < maxChars && startOffset > 0) {
10773        startOffset--;
10774        ctxChars++;
10775
10776        if (content[startOffset] == '\n') {
10777          if (++ctxLines == maxLines) {
10778            break;
10779          }
10780        }
10781      }
10782
10783      ctxChars = 0;
10784      ctxLines = 0;
10785
10786      while (ctxChars < maxChars && endOffset < content.length - 1) {
10787        endOffset++;
10788        ctxChars++;
10789
10790        if (content[endOffset] == '\n') {
10791          if (++ctxLines == maxLines) {
10792            break;
10793          }
10794        }
10795      }
10796
10797      return {
10798        before: content.substring(startOffset, this.offset),
10799        after: content.substring(this.offset, endOffset + 1)
10800      };
10801    }
10802
10803    return null;
10804  }
10805
10806}
10807
10808class ParseSourceFile {
10809  constructor(content, url) {
10810    this.content = content;
10811    this.url = url;
10812  }
10813
10814}
10815
10816class ParseSourceSpan {
10817  /**
10818   * Create an object that holds information about spans of tokens/nodes captured during
10819   * lexing/parsing of text.
10820   *
10821   * @param start
10822   * The location of the start of the span (having skipped leading trivia).
10823   * Skipping leading trivia makes source-spans more "user friendly", since things like HTML
10824   * elements will appear to begin at the start of the opening tag, rather than at the start of any
10825   * leading trivia, which could include newlines.
10826   *
10827   * @param end
10828   * The location of the end of the span.
10829   *
10830   * @param fullStart
10831   * The start of the token without skipping the leading trivia.
10832   * This is used by tooling that splits tokens further, such as extracting Angular interpolations
10833   * from text tokens. Such tooling creates new source-spans relative to the original token's
10834   * source-span. If leading trivia characters have been skipped then the new source-spans may be
10835   * incorrectly offset.
10836   *
10837   * @param details
10838   * Additional information (such as identifier names) that should be associated with the span.
10839   */
10840  constructor(start, end, fullStart = start, details = null) {
10841    this.start = start;
10842    this.end = end;
10843    this.fullStart = fullStart;
10844    this.details = details;
10845  }
10846
10847  toString() {
10848    return this.start.file.content.substring(this.start.offset, this.end.offset);
10849  }
10850
10851}
10852
10853var ParseErrorLevel;
10854
10855(function (ParseErrorLevel) {
10856  ParseErrorLevel[ParseErrorLevel["WARNING"] = 0] = "WARNING";
10857  ParseErrorLevel[ParseErrorLevel["ERROR"] = 1] = "ERROR";
10858})(ParseErrorLevel || (ParseErrorLevel = {}));
10859
10860class ParseError {
10861  constructor(span, msg, level = ParseErrorLevel.ERROR) {
10862    this.span = span;
10863    this.msg = msg;
10864    this.level = level;
10865  }
10866
10867  contextualMessage() {
10868    const ctx = this.span.start.getContext(100, 3);
10869    return ctx ? `${this.msg} ("${ctx.before}[${ParseErrorLevel[this.level]} ->]${ctx.after}")` : this.msg;
10870  }
10871
10872  toString() {
10873    const details = this.span.details ? `, ${this.span.details}` : '';
10874    return `${this.contextualMessage()}: ${this.span.start}${details}`;
10875  }
10876
10877}
10878/**
10879 * Generates Source Span object for a given R3 Type for JIT mode.
10880 *
10881 * @param kind Component or Directive.
10882 * @param typeName name of the Component or Directive.
10883 * @param sourceUrl reference to Component or Directive source.
10884 * @returns instance of ParseSourceSpan that represent a given Component or Directive.
10885 */
10886
10887
10888function r3JitTypeSourceSpan(kind, typeName, sourceUrl) {
10889  const sourceFileName = `in ${kind} ${typeName} in ${sourceUrl}`;
10890  const sourceFile = new ParseSourceFile('', sourceFileName);
10891  return new ParseSourceSpan(new ParseLocation(sourceFile, -1, -1, -1), new ParseLocation(sourceFile, -1, -1, -1));
10892}
10893
10894let _anonymousTypeIndex = 0;
10895
10896function identifierName(compileIdentifier) {
10897  if (!compileIdentifier || !compileIdentifier.reference) {
10898    return null;
10899  }
10900
10901  const ref = compileIdentifier.reference;
10902
10903  if (ref['__anonymousType']) {
10904    return ref['__anonymousType'];
10905  }
10906
10907  if (ref['__forward_ref__']) {
10908    // We do not want to try to stringify a `forwardRef()` function because that would cause the
10909    // inner function to be evaluated too early, defeating the whole point of the `forwardRef`.
10910    return '__forward_ref__';
10911  }
10912
10913  let identifier = stringify(ref);
10914
10915  if (identifier.indexOf('(') >= 0) {
10916    // case: anonymous functions!
10917    identifier = `anonymous_${_anonymousTypeIndex++}`;
10918    ref['__anonymousType'] = identifier;
10919  } else {
10920    identifier = sanitizeIdentifier(identifier);
10921  }
10922
10923  return identifier;
10924}
10925
10926function sanitizeIdentifier(name) {
10927  return name.replace(/\W/g, '_');
10928}
10929/**
10930 * @license
10931 * Copyright Google LLC All Rights Reserved.
10932 *
10933 * Use of this source code is governed by an MIT-style license that can be
10934 * found in the LICENSE file at https://angular.io/license
10935 */
10936
10937/**
10938 * In TypeScript, tagged template functions expect a "template object", which is an array of
10939 * "cooked" strings plus a `raw` property that contains an array of "raw" strings. This is
10940 * typically constructed with a function called `__makeTemplateObject(cooked, raw)`, but it may not
10941 * be available in all environments.
10942 *
10943 * This is a JavaScript polyfill that uses __makeTemplateObject when it's available, but otherwise
10944 * creates an inline helper with the same functionality.
10945 *
10946 * In the inline function, if `Object.defineProperty` is available we use that to attach the `raw`
10947 * array.
10948 */
10949
10950
10951const makeTemplateObjectPolyfill = '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,"raw",{value:t}):e.raw=t,e})';
10952
10953class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
10954  constructor() {
10955    super(false);
10956  }
10957
10958  visitWrappedNodeExpr(ast, ctx) {
10959    throw new Error('Cannot emit a WrappedNodeExpr in Javascript.');
10960  }
10961
10962  visitDeclareVarStmt(stmt, ctx) {
10963    ctx.print(stmt, `var ${stmt.name}`);
10964
10965    if (stmt.value) {
10966      ctx.print(stmt, ' = ');
10967      stmt.value.visitExpression(this, ctx);
10968    }
10969
10970    ctx.println(stmt, `;`);
10971    return null;
10972  }
10973
10974  visitTaggedTemplateExpr(ast, ctx) {
10975    // The following convoluted piece of code is effectively the downlevelled equivalent of
10976    // ```
10977    // tag`...`
10978    // ```
10979    // which is effectively like:
10980    // ```
10981    // tag(__makeTemplateObject(cooked, raw), expression1, expression2, ...);
10982    // ```
10983    const elements = ast.template.elements;
10984    ast.tag.visitExpression(this, ctx);
10985    ctx.print(ast, `(${makeTemplateOb
10985jectPolyfill}(`);
10986    ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.text, false)).join(', ')}], `);
10987    ctx.print(ast, `[${elements.map(part => escapeIdentifier(part.rawText, false)).join(', ')}])`);
10988    ast.template.expressions.forEach(expression => {
10989      ctx.print(ast, ', ');
10990      expression.visitExpression(this, ctx);
10991    });
10992    ctx.print(ast, ')');
10993    return null;
10994  }
10995
10996  visitFunctionExpr(ast, ctx) {
10997    ctx.print(ast, `function${ast.name ? ' ' + ast.name : ''}(`);
10998
10999    this._visitParams(ast.params, ctx);
11000
11001    ctx.println(ast, `) {`);
11002    ctx.incIndent();
11003    this.visitAllStatements(ast.statements, ctx);
11004    ctx.decIndent();
11005    ctx.print(ast, `}`);
11006    return null;
11007  }
11008
11009  visitDeclareFunctionStmt(stmt, ctx) {
11010    ctx.print(stmt, `function ${stmt.name}(`);
11011
11012    this._visitParams(stmt.params, ctx);
11013
11014    ctx.println(stmt, `) {`);
11015    ctx.incIndent();
11016    this.visitAllStatements(stmt.statements, ctx);
11017    ctx.decIndent();
11018    ctx.println(stmt, `}`);
11019    return null;
11020  }
11021
11022  visitLocalizedString(ast, ctx) {
11023    // The following convoluted piece of code is effectively the downlevelled equivalent of
11024    // ```
11025    // $localize `...`
11026    // ```
11027    // which is effectively like:
11028    // ```
11029    // $localize(__makeTemplateObject(cooked, raw), expression1, expression2, ...);
11030    // ```
11031    ctx.print(ast, `$localize(${makeTemplateObjectPolyfill}(`);
11032    const parts = [ast.serializeI18nHead()];
11033
11034    for (let i = 1; i < ast.messageParts.length; i++) {
11035      parts.push(ast.serializeI18nTemplatePart(i));
11036    }
11037
11038    ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.cooked, false)).join(', ')}], `);
11039    ctx.print(ast, `[${parts.map(part => escapeIdentifier(part.raw, false)).join(', ')}])`);
11040    ast.expressions.forEach(expression => {
11041      ctx.print(ast, ', ');
11042      expression.visitExpression(this, ctx);
11043    });
11044    ctx.print(ast, ')');
11045    return null;
11046  }
11047
11048  _visitParams(params, ctx) {
11049    this.visitAllObjects(param => ctx.print(null, param.name), params, ctx, ',');
11050  }
11051
11052}
11053/**
11054 * @license
11055 * Copyright Google LLC All Rights Reserved.
11056 *
11057 * Use of this source code is governed by an MIT-style license that can be
11058 * found in the LICENSE file at https://angular.io/license
11059 */
11060
11061/**
11062 * The Trusted Types policy, or null if Trusted Types are not
11063 * enabled/supported, or undefined if the policy has not been created yet.
11064 */
11065
11066
11067let policy;
11068/**
11069 * Returns the Trusted Types policy, or null if Trusted Types are not
11070 * enabled/supported. The first call to this function will create the policy.
11071 */
11072
11073function getPolicy() {
11074  if (policy === undefined) {
11075    policy = null;
11076
11077    if (_global.trustedTypes) {
11078      try {
11079        policy = _global.trustedTypes.createPolicy('angular#unsafe-jit', {
11080          createScript: s => s
11081        });
11082      } catch {// trustedTypes.createPolicy throws if called with a name that is
11083        // already registered, even in report-only mode. Until the API changes,
11084        // catch the error not to break the applications functionally. In such
11085        // cases, the code will fall back to using strings.
11086      }
11087    }
11088  }
11089
11090  return policy;
11091}
11092/**
11093 * Unsafely promote a string to a TrustedScript, falling back to strings when
11094 * Trusted Types are not available.
11095 * @security In particular, it must be assured that the provided string will
11096 * never cause an XSS vulnerability if used in a context that will be
11097 * interpreted and executed as a script by a browser, e.g. when calling eval.
11098 */
11099
11100
11101function trustedScriptFromString(script) {
11102  return getPolicy()?.createScript(script) || script;
11103}
11104/**
11105 * Unsafely call the Function constructor with the given string arguments.
11106 * @security This is a security-sensitive function; any use of this function
11107 * must go through security review. In particular, it must be assured that it
11108 * is only called from the JIT compiler, as use in other code can lead to XSS
11109 * vulnerabilities.
11110 */
11111
11112
11113function newTrustedFunctionForJIT(...args) {
11114  if (!_global.trustedTypes) {
11115    // In environments that don't support Trusted Types, fall back to the most
11116    // straightforward implementation:
11117    return new Function(...args);
11118  } // Chrome currently does not support passing TrustedScript to the Function
11119  // constructor. The following implements the workaround proposed on the page
11120  // below, where the Chromium bug is also referenced:
11121  // https://github.com/w3c/webappsec-trusted-types/wiki/Trusted-Types-for-function-constructor
11122
11123
11124  const fnArgs = args.slice(0, -1).join(',');
11125  const fnBody = args[args.length - 1];
11126  const body = `(function anonymous(${fnArgs}
11127) { ${fnBody}
11128})`; // Using eval directly confuses the compiler and prevents this module from
11129  // being stripped out of JS binaries even if not used. The global['eval']
11130  // indirection fixes that.
11131
11132  const fn = _global['eval'](trustedScriptFromString(body));
11133
11134  if (fn.bind === undefined) {
11135    // Workaround for a browser bug that only exists in Chrome 83, where passing
11136    // a TrustedScript to eval just returns the TrustedScript back without
11137    // evaluating it. In that case, fall back to the most straightforward
11138    // implementation:
11139    return new Function(...args);
11140  } // To completely mimic the behavior of calling "new Function", two more
11141  // things need to happen:
11142  // 1. Stringifying the resulting function should return its source code
11143
11144
11145  fn.toString = () => body; // 2. When calling the resulting function, `this` should refer to `global`
11146
11147
11148  return fn.bind(_global); // When Trusted Types support in Function constructors is widely available,
11149  // the implementation of this function can be simplified to:
11150  // return new Function(...args.map(a => trustedScriptFromString(a)));
11151}
11152/**
11153 * @license
11154 * Copyright Google LLC All Rights Reserved.
11155 *
11156 * Use of this source code is governed by an MIT-style license that can be
11157 * found in the LICENSE file at https://angular.io/license
11158 */
11159
11160/**
11161 * A helper class to manage the evaluation of JIT generated code.
11162 */
11163
11164
11165class JitEvaluator {
11166  /**
11167   *
11168   * @param sourceUrl The URL of the generated code.
11169   * @param statements An array of Angular statement AST nodes to be evaluated.
11170   * @param refResolver Resolves `o.ExternalReference`s into values.
11171   * @param createSourceMaps If true then create a source-map for the generated code and include it
11172   * inline as a source-map comment.
11173   * @returns A map of all the variables in the generated code.
11174   */
11175  evaluateStatements(sourceUrl, statements, refResolver, createSourceMaps) {
11176    const converter = new JitEmitterVisitor(refResolver);
11177    const ctx = EmitterVisitorContext.createRoot(); // Ensure generated code is in strict mode
11178
11179    if (statements.length >
11179 0 && !isUseStrictStatement(statements[0])) {
11180      statements = [literal('use strict').toStmt(), ...statements];
11181    }
11182
11183    converter.visitAllStatements(statements, ctx);
11184    converter.createReturnStmt(ctx);
11185    return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps);
11186  }
11187  /**
11188   * Evaluate a piece of JIT generated code.
11189   * @param sourceUrl The URL of this generated code.
11190   * @param ctx A context object that contains an AST of the code to be evaluated.
11191   * @param vars A map containing the names and values of variables that the evaluated code might
11192   * reference.
11193   * @param createSourceMap If true then create a source-map for the generated code and include it
11194   * inline as a source-map comment.
11195   * @returns The result of evaluating the code.
11196   */
11197
11198
11199  evaluateCode(sourceUrl, ctx, vars, createSourceMap) {
11200    let fnBody = `"use strict";${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
11201    const fnArgNames = [];
11202    const fnArgValues = [];
11203
11204    for (const argName in vars) {
11205      fnArgValues.push(vars[argName]);
11206      fnArgNames.push(argName);
11207    }
11208
11209    if (createSourceMap) {
11210      // using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise
11211      // E.g. ```
11212      // function anonymous(a,b,c
11213      // /**/) { ... }```
11214      // We don't want to hard code this fact, so we auto detect it via an empty function first.
11215      const emptyFn = newTrustedFunctionForJIT(...fnArgNames.concat('return null;')).toString();
11216      const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
11217      fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
11218    }
11219
11220    const fn = newTrustedFunctionForJIT(...fnArgNames.concat(fnBody));
11221    return this.executeFunction(fn, fnArgValues);
11222  }
11223  /**
11224   * Execute a JIT generated function by calling it.
11225   *
11226   * This method can be overridden in tests to capture the functions that are generated
11227   * by this `JitEvaluator` class.
11228   *
11229   * @param fn A function to execute.
11230   * @param args The arguments to pass to the function being executed.
11231   * @returns The return value of the executed function.
11232   */
11233
11234
11235  executeFunction(fn, args) {
11236    return fn(...args);
11237  }
11238
11239}
11240/**
11241 * An Angular AST visitor that converts AST nodes into executable JavaScript code.
11242 */
11243
11244
11245class JitEmitterVisitor extends AbstractJsEmitterVisitor {
11246  constructor(refResolver) {
11247    super();
11248    this.refResolver = refResolver;
11249    this._evalArgNames = [];
11250    this._evalArgValues = [];
11251    this._evalExportedVars = [];
11252  }
11253
11254  createReturnStmt(ctx) {
11255    const stmt = new ReturnStatement(new LiteralMapExpr(this._evalExportedVars.map(resultVar => new LiteralMapEntry(resultVar, variable(resultVar), false))));
11256    stmt.visitStatement(this, ctx);
11257  }
11258
11259  getArgs() {
11260    const result = {};
11261
11262    for (let i = 0; i < this._evalArgNames.length; i++) {
11263      result[this._evalArgNames[i]] = this._evalArgValues[i];
11264    }
11265
11266    return result;
11267  }
11268
11269  visitExternalExpr(ast, ctx) {
11270    this._emitReferenceToExternal(ast, this.refResolver.resolveExternalReference(ast.value), ctx);
11271
11272    return null;
11273  }
11274
11275  visitWrappedNodeExpr(ast, ctx) {
11276    this._emitReferenceToExternal(ast, ast.node, ctx);
11277
11278    return null;
11279  }
11280
11281  visitDeclareVarStmt(stmt, ctx) {
11282    if (stmt.hasModifier(StmtModifier.Exported)) {
11283      this._evalExportedVars.push(stmt.name);
11284    }
11285
11286    return super.visitDeclareVarStmt(stmt, ctx);
11287  }
11288
11289  visitDeclareFunctionStmt(stmt, ctx) {
11290    if (stmt.hasModifier(StmtModifier.Exported)) {
11291      this._evalExportedVars.push(stmt.name);
11292    }
11293
11294    return super.visitDeclareFunctionStmt(stmt, ctx);
11295  }
11296
11297  _emitReferenceToExternal(ast, value, ctx) {
11298    let id = this._evalArgValues.indexOf(value);
11299
11300    if (id === -1) {
11301      id = this._evalArgValues.length;
11302
11303      this._evalArgValues.push(value);
11304
11305      const name = identifierName({
11306        reference: value
11307      }) || 'val';
11308
11309      this._evalArgNames.push(`jit_${name}_${id}`);
11310    }
11311
11312    ctx.print(ast, this._evalArgNames[id]);
11313  }
11314
11315}
11316
11317function isUseStrictStatement(statement) {
11318  return statement.isEquivalent(literal('use strict').toStmt());
11319}
11320/**
11321 * @license
11322 * Copyright Google LLC All Rights Reserved.
11323 *
11324 * Use of this source code is governed by an MIT-style license that can be
11325 * found in the LICENSE file at https://angular.io/license
11326 */
11327
11328
11329function compileInjector(meta) {
11330  const definitionMap = new DefinitionMap();
11331
11332  if (meta.providers !== null) {
11333    definitionMap.set('providers', meta.providers);
11334  }
11335
11336  if (meta.imports.length > 0) {
11337    definitionMap.set('imports', literalArr(meta.imports));
11338  }
11339
11340  const expression = importExpr(Identifiers.defineInjector).callFn([definitionMap.toLiteralMap()], undefined, true);
11341  const type = createInjectorType(meta);
11342  return {
11343    expression,
11344    type,
11345    statements: []
11346  };
11347}
11348
11349function createInjectorType(meta) {
11350  return new ExpressionType(importExpr(Identifiers.InjectorDeclaration, [new ExpressionType(meta.type.type)]));
11351}
11352/**
11353 * @license
11354 * Copyright Google LLC All Rights Reserved.
11355 *
11356 * Use of this source code is governed by an MIT-style license that can be
11357 * found in the LICENSE file at https://angular.io/license
11358 */
11359
11360/**
11361 * Implementation of `CompileReflector` which resolves references to @angular/core
11362 * symbols at runtime, according to a consumer-provided mapping.
11363 *
11364 * Only supports `resolveExternalReference`, all other methods throw.
11365 */
11366
11367
11368class R3JitReflector {
11369  constructor(context) {
11370    this.context = context;
11371  }
11372
11373  resolveExternalReference(ref) {
11374    // This reflector only handles @angular/core imports.
11375    if (ref.moduleName !== '@angular/core') {
11376      throw new Error(`Cannot resolve external reference to ${ref.moduleName}, only references to @angular/core are supported.`);
11377    }
11378
11379    if (!this.context.hasOwnProperty(ref.name)) {
11380      throw new Error(`No value provided for @angular/core symbol '${ref.name}'.`);
11381    }
11382
11383    return this.context[ref.name];
11384  }
11385
11386}
11387/**
11388 * @license
11389 * Copyright Google LLC All Rights Reserved.
11390 *
11391 * Use of this source code is governed by an MIT-style license that can be
11392 * found in the LICENSE file at https://angular.io/license
11393 */
11394
11395/**
11396 * How the selector scope of an NgModule (its declarations, imports, and exports) should be emitted
11397 * as a part of the NgModule definition.
11398 */
11399
11400
11401var R3SelectorScopeMode;
11402
11403(function (R3SelectorScopeMode) {
11404  /**
11405   * Emit the declarations inline into the module definition.
11406   *
11407   * This option is useful in certain contexts where it's known that JIT support is required. The
11408   * tradeoff here is that this emit style prevents directives and pipes from being tree-shaken if
11409   * they are unused, but the NgModule is used.
11410   */
11411  R3SelectorScopeMode[R3SelectorScopeMode["Inline"] = 0] = "Inline";
11412  /**
11413   * Emit the declarations using a side effectful function call, `ɵɵsetNgModuleScope`, that is
11414   * guarded with the `ngJitMode` flag.
11415   *
11416   * This form of emit supports JIT and can be optimized away if the `ngJitMode` flag is set to
11417   * false, which allows unused directives and pipes to be tree-shaken.
11418   */
11419
11420  R3SelectorScopeMode[R3SelectorScopeMode["SideEffect"] = 1] = "SideEffect";
11421  /**
11422   * Don't generate selector scopes at all.
11423   *
11424   * This is useful for contexts where JIT support is known to be unnecessary.
11425   */
11426
11427  R3SelectorScopeMode[R3SelectorScopeMode["Omit"] = 2] = "Omit";
11428})(R3SelectorScopeMode || (R3SelectorScopeMode = {}));
11429/**
11430 * Construct an `R3NgModuleDef` for the given `R3NgModuleMetadata`.
11431 */
11432
11433
11434function compileNgModule(meta) {
11435  const {
11436    adjacentType,
11437    internalType,
11438    bootstrap,
11439    declarations,
11440    imports,
11441    exports,
11442    schemas,
11443    containsForwardDecls,
11444    selectorScopeMode,
11445    id
11446  } = meta;
11447  const statements = [];
11448  const definitionMap = new DefinitionMap();
11449  definitionMap.set('type', internalType);
11450
11451  if (bootstrap.length > 0) {
11452    definitionMap.set('bootstrap', refsToArray(bootstrap, containsForwardDecls));
11453  }
11454
11455  if (selectorScopeMode === R3SelectorScopeMode.Inline) {
11456    // If requested to emit scope information inline, pass the `declarations`, `imports` and
11457    // `exports` to the `ɵɵdefineNgModule()` call directly.
11458    if (declarations.length > 0) {
11459      definitionMap.set('declarations', refsToArray(declarations, containsForwardDecls));
11460    }
11461
11462    if (imports.length > 0) {
11463      definitionMap.set('imports', refsToArray(imports, containsForwardDecls));
11464    }
11465
11466    if (exports.length > 0) {
11467      definitionMap.set('exports', refsToArray(exports, containsForwardDecls));
11468    }
11469  } else if (selectorScopeMode === R3SelectorScopeMode.SideEffect) {
11470    // In this mode, scope information is not passed into `ɵɵdefineNgModule` as it
11471    // would prevent tree-shaking of the declarations, imports and exports references. Instead, it's
11472    // patched onto the NgModule definition with a `ɵɵsetNgModuleScope` call that's guarded by the
11473    // `ngJitMode` flag.
11474    const setNgModuleScopeCall = generateSetNgModuleScopeCall(meta);
11475
11476    if (setNgModuleScopeCall !== null) {
11477      statements.push(setNgModuleScopeCall);
11478    }
11479  } else {// Selector scope emit was not requested, so skip it.
11480  }
11481
11482  if (schemas !== null && schemas.length > 0) {
11483    definitionMap.set('schemas', literalArr(schemas.map(ref => ref.value)));
11484  }
11485
11486  if (id !== null) {
11487    definitionMap.set('id', id); // Generate a side-effectful call to register this NgModule by its id, as per the semantics of
11488    // NgModule ids.
11489
11490    statements.push(importExpr(Identifiers.registerNgModuleType).callFn([adjacentType, id]).toStmt());
11491  }
11492
11493  const expression = importExpr(Identifiers.defineNgModule).callFn([definitionMap.toLiteralMap()], undefined, true);
11494  const type = createNgModuleType(meta);
11495  return {
11496    expression,
11497    type,
11498    statements
11499  };
11500}
11501/**
11502 * This function is used in JIT mode to generate the call to `ɵɵdefineNgModule()` from a call to
11503 * `ɵɵngDeclareNgModule()`.
11504 */
11505
11506
11507function compileNgModuleDeclarationExpression(meta) {
11508  const definitionMap = new DefinitionMap();
11509  definitionMap.set('type', new WrappedNodeExpr(meta.type));
11510
11511  if (meta.bootstrap !== undefined) {
11512    definitionMap.set('bootstrap', new WrappedNodeExpr(meta.bootstrap));
11513  }
11514
11515  if (meta.declarations !== undefined) {
11516    definitionMap.set('declarations', new WrappedNodeExpr(meta.declarations));
11517  }
11518
11519  if (meta.imports !== undefined) {
11520    definitionMap.set('imports', new WrappedNodeExpr(meta.imports));
11521  }
11522
11523  if (meta.exports !== undefined) {
11524    definitionMap.set('exports', new WrappedNodeExpr(meta.exports));
11525  }
11526
11527  if (meta.schemas !== undefined) {
11528    definitionMap.set('schemas', new WrappedNodeExpr(meta.schemas));
11529  }
11530
11531  if (meta.id !== undefined) {
11532    definitionMap.set('id', new WrappedNodeExpr(meta.id));
11533  }
11534
11535  return importExpr(Identifiers.defineNgModule).callFn([definitionMap.toLiteralMap()]);
11536}
11537
11538function createNgModuleType({
11539  type: moduleType,
11540  declarations,
11541  exports,
11542  imports,
11543  includeImportTypes,
11544  publicDeclarationTypes
11545}) {
11546  return new ExpressionType(importExpr(Identifiers.NgModuleDeclaration, [new ExpressionType(moduleType.type), publicDeclarationTypes === null ? tupleTypeOf(declarations) : tupleOfTypes(publicDeclarationTypes), includeImportTypes ? tupleTypeOf(imports) : NONE_TYPE, tupleTypeOf(exports)]));
11547}
11548/**
11549 * Generates a function call to `ɵɵsetNgModuleScope` with all necessary information so that the
11550 * transitive module scope can be computed during runtime in JIT mode. This call is marked pure
11551 * such that the references to declarations, imports and exports may be elided causing these
11552 * symbols to become tree-shakeable.
11553 */
11554
11555
11556function generateSetNgModuleScopeCall(meta) {
11557  const {
11558    adjacentType: moduleType,
11559    declarations,
11560    imports,
11561    exports,
11562    containsForwardDecls
11563  } = meta;
11564  const scopeMap = new DefinitionMap();
11565
11566  if (declarations.length > 0) {
11567    scopeMap.set('declarations', refsToArray(declarations, containsForwardDecls));
11568  }
11569
11570  if (imports.length > 0) {
11571    scopeMap.set('imports', refsToArray(imports, containsForwardDecls));
11572  }
11573
11574  if (exports.length > 0) {
11575    scopeMap.set('exports', refsToArray(exports, containsForwardDecls));
11576  }
11577
11578  if (Object.keys(scopeMap.values).length === 0) {
11579    return null;
11580  } // setNgModuleScope(...)
11581
11582
11583  const fnCall = new InvokeFunctionExpr(
11584  /* fn */
11585  importExpr(Identifiers.setNgModuleScope),
11586  /* args */
11587  [moduleType, scopeMap.toLiteralMap()]); // (ngJitMode guard) && setNgModuleScope(...)
11588
11589  const guardedCall = jitOnlyGuardedExpression(fnCall); // function() { (ngJitMode guard) && setNgModuleScope(...); }
11590
11591  const iife = new FunctionExpr(
11592  /* params */
11593  [],
11594  /* statements */
11595  [guardedCall.toStmt()]); // (function() { (ngJitMode guard) && setNgModuleScope(...); })()
11596
11597  const iifeCall = new InvokeFunctionExpr(
11598  /* fn */
11599  iife,
11600  /* args */
11601  []);
11602  return iifeCall.toStmt();
11603}
11604
11605function tupleTypeOf(exp) {
11606  const types = exp.map(ref => typeofExpr(ref.type));
11607  return exp.length > 0 ? expressionType(literalArr(types)) : NONE_TYPE;
11608}
11609
11610function tupleOfTypes(types) {
11611  const typeofTypes = types.map(type => typeofExpr(type));
11612  return types.length > 0 ? expressionType(literalArr(typeofTypes)) : NONE_TYPE;
11613}
11614/**
11615 * @license
11616 * Copyright Google LLC All Rights Reserved.
11617 *
11618 * Use of this source code is governed by an MIT-style license that can be
11619 * found in the LICENSE file at https://angular.io/license
11620 */
11621
11622
11623function compilePipeFromMetadata(metadata) {
11624  const definitionMapValues = []; // e.g. `name: 'myPipe'`
11625
11626  definitionMapValues.push({
11627    key: 'name',
11628    value: literal(metadata.pipeName),
11629    quoted: false
11630  }); // e.g. `type: MyPipe`
11631
11632  definitionMapValues.push({
11633    key: 'type',
11634    value: metadata.type.value,
11635    quoted: false
11636  }); // e.g. `pure: true`
11637
11638  definitionMapValues.push({
11639    key: 'pure',
11640    value: literal(metadata.pure),
11641    quoted: false
11642  });
11643
11644  if (metadata.isStandalone) {
11645    definitionMapValues.push({
11646      key: 'standalone',
11647      value: literal(true),
11648      quoted: false
11649    });
11650  }
11651
11652  const expression = importExpr(Identifiers.definePipe).callFn([literalMap(definitionMapValues)], undefined, true);
11653  const type = createPipeType(metadata);
11654  return {
11655    expression,
11656    type,
11657    statements: []
11658  };
11659}
11660
11661function createPipeType(metadata) {
11662  return new ExpressionType(importExpr(Identifiers.PipeDeclaration, [typeWithParameters(metadata.type.type, metadata.typeArgumentCount), new ExpressionType(new LiteralExpr(metadata.pipeName)), new ExpressionType(new LiteralExpr(metadata.isStandalone))]));
11663}
11664/**
11665 * @license
11666 * Copyright Google LLC All Rights Reserved.
11667 *
11668 * Use of this source code is governed by an MIT-style license that can be
11669 * found in the LICENSE file at https://angular.io/license
11670 */
11671
11672
11673var R3TemplateDependencyKind;
11674
11675(function (R3TemplateDependencyKind) {
11676  R3TemplateDependencyKind[R3TemplateDependencyKind["Directive"] = 0] = "Directive";
11677  R3TemplateDependencyKind[R3TemplateDependencyKind["Pipe"] = 1] = "Pipe";
11678  R3TemplateDependencyKind[R3TemplateDependencyKind["NgModule"] = 2] = "NgModule";
11679})(R3TemplateDependencyKind || (R3TemplateDependencyKind = {}));
11680/**
11681 * @license
11682 * Copyright Google LLC All Rights Reserved.
11683 *
11684 * Use of this source code is governed by an MIT-style license that can be
11685 * found in the LICENSE file at https://angular.io/license
11686 */
11687
11688
11689class ParserError {
11690  constructor(message, input, errLocation, ctxLocation) {
11691    this.input = input;
11692    this.errLocation = errLocation;
11693    this.ctxLocation = ctxLocation;
11694    this.message = `Parser Error: ${message} ${errLocation} [${input}] in ${ctxLocation}`;
11695  }
11696
11697}
11698
11699class ParseSpan {
11700  constructor(start, end) {
11701    this.start = start;
11702    this.end = end;
11703  }
11704
11705  toAbsolute(absoluteOffset) {
11706    return new AbsoluteSourceSpan(absoluteOffset + this.start, absoluteOffset + this.end);
11707  }
11708
11709}
11710
11711class AST {
11712  constructor(span,
11713  /**
11714   * Absolute location of the expression AST in a source code file.
11715   */
11716  sourceSpan) {
11717    this.span = span;
11718    this.sourceSpan = sourceSpan;
11719  }
11720
11721  toString() {
11722    return 'AST';
11723  }
11724
11725}
11726
11727class ASTWithName extends AST {
11728  constructor(span, sourceSpan, nameSpan) {
11729    super(span, sourceSpan);
11730    this.nameSpan = nameSpan;
11731  }
11732
11733}
11734
11735class EmptyExpr extends AST {
11736  visit(visitor, context = null) {// do nothing
11737  }
11738
11739}
11740
11741class ImplicitReceiver extends AST {
11742  visit(visitor, context = null) {
11743    return visitor.visitImplicitReceiver(this, context);
11744  }
11745
11746}
11747/**
11748 * Receiver when something is accessed through `this` (e.g. `this.foo`). Note that this class
11749 * inherits from `ImplicitReceiver`, because accessing something through `this` is treated the
11750 * same as accessing it implicitly inside of an Angular template (e.g. `[attr.title]="this.title"`
11751 * is the same as `[attr.title]="title"`.). Inheriting allows for the `this` accesses to be treated
11752 * the same as implicit ones, except for a couple of exceptions like `$event` and `$any`.
11753 * TODO: we should find a way for this class not to extend from `ImplicitReceiver` in the future.
11754 */
11755
11756
11757class ThisReceiver extends ImplicitReceiver {
11758  visit(visitor, context = null) {
11759    return visitor.visitThisReceiver?.(this, context);
11760  }
11761
11762}
11763/**
11764 * Multiple expressions separated by a semicolon.
11765 */
11766
11767
11768class Chain extends AST {
11769  constructor(span, sourceSpan, expressions) {
11770    super(span, sourceSpan);
11771    this.expressions = expressions;
11772  }
11773
11774  visit(visitor, context = null) {
11775    return visitor.visitChain(this, context);
11776  }
11777
11778}
11779
11780class Conditional extends AST {
11781  constructor(span, sourceSpan, condition, trueExp, falseExp) {
11782    super(span, sourceSpan);
11783    this.condition = condition;
11784    this.trueExp = trueExp;
11785    this.falseExp = falseExp;
11786  }
11787
11788  visit(visitor, context = null) {
11789    return visitor.visitConditional(this, context);
11790  }
11791
11792}
11793
11794class PropertyRead extends ASTWithName {
11795  constructor(span, sourceSpan, nameSpan, receiver, name) {
11796    super(span, sourceSpan, nameSpan);
11797    this.receiver = receiver;
11798    this.name = name;
11799  }
11800
11801  visit(visitor, context = null) {
11802    return visitor.visitPropertyRead(this, context);
11803  }
11804
11805}
11806
11807class PropertyWrite extends ASTWithName {
11808  constructor(span, sourceSpan, nameSpan, receiver, name, value) {
11809    super(span, sourceSpan, nameSpan);
11810    this.receiver = receiver;
11811    this.name = name;
11812    this.value = value;
11813  }
11814
11815  visit(visitor, context = null) {
11816    return visitor.visitPropertyWrite(this, context);
11817  }
11818
11819}
11820
11821class SafePropertyRead extends ASTWithName {
11822  constructor(span, sourceSpan, nameSpan, receiver, name) {
11823    super(span, sourceSpan, nameSpan);
11824    this.receiver = receiver;
11825    this.name = name;
11826  }
11827
11828  visit(visitor, context = null) {
11829    return visitor.visitSafePropertyRead(this, context);
11830  }
11831
11832}
11833
11834class KeyedRead extends AST {
11835  constructor(span, sourceSpan, receiver, key) {
11836    super(span, sourceSpan);
11837    this.receiver = receiver;
11838    this.key = key;
11839  }
11840
11841  visit(visitor, context = null) {
11842    return visitor.visitKeyedRead(this, context);
11843  }
11844
11845}
11846
11847class SafeKeyedRead extends AST {
11848  constructor(span, sourceSpan, receiver, key) {
11849    super(span, sourceSpan);
11850    this.receiver = receiver;
11851    this.key = key;
11852  }
11853
11854  visit(visitor, context = null) {
11855    return visitor.visitSafeKeyedRead(this, context);
11856  }
11857
11858}
11859
11860class KeyedWrite extends AST {
11861  constructor(span, sourceSpan, receiver, key, value) {
11862    super(span, sourceSpan);
11863    this.receiver = receiver;
11864    this.key = key;
11865    this.value = value;
11866  }
11867
11868  visit(visitor, context = null) {
11869    return visitor.visitKeyedWrite(this, context);
11870  }
11871
11872}
11873
11874class BindingPipe extends ASTWithName {
11875  constructor(span, sourceSpan, exp, name, args, nameSpan) {
11876    super(span, sourceSpan, nameSpan);
11877    this.exp = exp;
11878    this.name = name;
11879    this.args = args;
11880  }
11881
11882  visit(visitor, context = null) {
11883    return visitor.visitPipe(this, context);
11884  }
11885
11886}
11887
11888class LiteralPrimitive extends AST {
11889  constructor(span, sourceSpan, value) {
11890    super(span, sourceSpan);
11891    this.value = value;
11892  }
11893
11894  visit(visitor, context = null) {
11895    return visitor.visitLiteralPrimitive(this, context);
11896  }
11897
11898}
11899
11900class LiteralArray extends AST {
11901  constructor(span, sourceSpan, expressions) {
11902    super(span, sourceSpan);
11903    this.expressions = expressions;
11904  }
11905
11906  visit(visitor, context = null) {
11907    return visitor.visitLiteralArray(this, context);
11908  }
11909
11910}
11911
11912class LiteralMap extends AST {
11913  constructor(span, sourceSpan, keys, values) {
11914    super(span, sourceSpan);
11915    this.keys = keys;
11916    this.values = values;
11917  }
11918
11919  visit(visitor, context = null) {
11920    return visitor.visitLiteralMap(this, context);
11921  }
11922
11923}
11924
11925class Interpolation extends AST {
11926  constructor(span, sourceSpan, strings, expressions) {
11927    super(span, sourceSpan);
11928    this.strings = strings;
11929    this.expressions = expressions;
11930  }
11931
11932  visit(visitor, context = null) {
11933    return visitor.visitInterpolation(this, context);
11934  }
11935
11936}
11937
11938class Binary extends AST {
11939  constructor(span, sourceSpan, operation, left, right) {
11940    super(span, sourceSpan);
11941    this.operation = operation;
11942    this.left = left;
11943    this.right = right;
11944  }
11945
11946  visit(visitor, context = null) {
11947    return visitor.visitBinary(this, context);
11948  }
11949
11950}
11951/**
11952 * For backwards compatibility reasons, `Unary` inherits from `Binary` and mimics the binary AST
11953 * node that was originally used. This inheritance relation can be deleted in some future major,
11954 * after consumers have been given a chance to fully support Unary.
11955 */
11956
11957
11958class Unary extends Binary {
11959  /**
11960   * During the deprecation period this constructor is private, to avoid consumers from creating
11961   * a `Unary` with the fallback properties for `Binary`.
11962   */
11963  constructor(span, sourceSpan, operator, expr, binaryOp, binaryLeft, binaryRight) {
11964    super(span, sourceSpan, binaryOp, binaryLeft, binaryRight);
11965    this.operator = operator;
11966    this.expr = expr; // Redeclare the properties that are inherited from `Binary` as `never`, as consumers should not
11967    // depend on these fields when operating on `Unary`.
11968
11969    this.left = null;
11970    this.right = null;
11971    this.operation = null;
11972  }
11973  /**
11974   * Creates a unary minus expression "-x", represented as `Binary` using "0 - x".
11975   */
11976
11977
11978  static createMinus(span, sourceSpan, expr) {
11979    return new Unary(span, sourceSpan, '-', expr, '-', new LiteralPrimitive(span, sourceSpan, 0), expr);
11980  }
11981  /**
11982   * Creates a unary plus expression "+x", represented as `Binary` using "x - 0".
11983   */
11984
11985
11986  static createPlus(span, sourceSpan, expr) {
11987    return new Unary(span, sourceSpan, '+', expr, '-', expr, new LiteralPrimitive(span, sourceSpan, 0));
11988  }
11989
11990  visit(visitor, context = null) {
11991    if (visitor.visitUnary !== undefined) {
11992      return visitor.visitUnary(this, context);
11993    }
11994
11995    return visitor.visitBinary(this, context);
11996  }
11997
11998}
11999
12000class PrefixNot extends AST {
12001  constructor(span, sourceSpan, expression) {
12002    super(span, sourceSpan);
12003    this.expression = expression;
12004  }
12005
12006  visit(visitor, context = null) {
12007    return visitor.visitPrefixNot(this, context);
12008  }
12009
12010}
12011
12012class NonNullAssert extends AST {
12013  constructor(span, sourceSpan, expression) {
12014    super(span, sourceSpan);
12015    this.expression = expression;
12016  }
12017
12018  visit(visitor, context = null) {
12019    return visitor.visitNonNullAssert(this, context);
12020  }
12021
12022}
12023
12024class Call extends AST {
12025  constructor(span, sourceSpan, receiver, args, argumentSpan) {
12026    super(span, sourceSpan);
12027    this.receiver = receiver;
12028    this.args = args;
12029    this.argumentSpan = argumentSpan;
12030  }
12031
12032  visit(visitor, context = null) {
12033    return visitor.visitCall(this, context);
12034  }
12035
12036}
12037
12038class SafeCall extends AST {
12039  constructor(span, sourceSpan, receiver, args, argumentSpan) {
12040    super(span, sourceSpan);
12041    this.receiver = receiver;
12042    this.args = args;
12043    this.argumentSpan = argumentSpan;
12044  }
12045
12046  visit(visitor, context = null) {
12047    return visitor.visitSafeCall(this, context);
12048  }
12049
12050}
12051/**
12052 * Records the absolute position of a text span in a source file, where `start` and `end` are the
12053 * starting and ending byte offsets, respectively, of the text span in a source file.
12054 */
12055
12056
12057class AbsoluteSourceSpan {
12058  constructor(start, end) {
12059    this.start = start;
12060    this.end = end;
12061  }
12062
12063}
12064
12065class ASTWithSource extends AST {
12066  constructor(ast, source, location, absoluteOffset, errors) {
12067    super(new ParseSpan(0, source === null ? 0 : source.length), new AbsoluteSourceSpan(absoluteOffset, source === null ? absoluteOffset : absoluteOffset + source.length));
12068    this.ast = ast;
12069    this.source = source;
12070    this.location = location;
12071    this.errors = errors;
12072  }
12073
12074  visit(visitor, context = null) {
12075    if (visitor.visitASTWithSource) {
12076      return visitor.visitASTWithSource(this, context);
12077    }
12078
12079    return this.ast.visit(visitor, context);
12080  }
12081
12082  toString() {
12083    return `${this.source} in ${this.location}`;
12084  }
12085
12086}
12087
12088class VariableBinding {
12089  /**
12090   * @param sourceSpan entire span of the binding.
12091   * @param key name of the LHS along with its span.
12092   * @param value optional value for the RHS along with its span.
12093   */
12094  constructor(sourceSpan, key, value) {
12095    this.sourceSpan = sourceSpan;
12096    this.key = key;
12097    this.value = value;
12098  }
12099
12100}
12101
12102class ExpressionBinding {
12103  /**
12104   * @param sourceSpan entire span of the binding.
12105   * @param key binding name, like ngForOf, ngForTrackBy, ngIf, along with its
12106   * span. Note that the length of the span may not be the same as
12107   * `key.source.length`. For example,
12108   * 1. key.source = ngFor, key.span is for "ngFor"
12109   * 2. key.source = ngForOf, key.span is for "of"
12110   * 3. key.source = ngForTrackBy, key.span is for "trackBy"
12111   * @param value optional expression for the RHS.
12112   */
12113  constructor(sourceSpan, key, value) {
12114    this.sourceSpan = sourceSpan;
12115    this.key = key;
12116    this.value = value;
12117  }
12118
12119}
12120
12121class RecursiveAstVisitor {
12122  visit(ast, context) {
12123    // The default implementation just visits every node.
12124    // Classes that extend RecursiveAstVisitor should override this function
12125    // to selectively visit the specified node.
12126    ast.visit(this, context);
12127  }
12128
12129  visitUnary(ast, context) {
12130    this.visit(ast.expr, context);
12131  }
12132
12133  visitBinary(ast, context) {
12134    this.visit(ast.left, context);
12135    this.visit(ast.right, context);
12136  }
12137
12138  visitChain(ast, context) {
12139    this.visitAll(ast.expressions, context);
12140  }
12141
12142  visitConditional(ast, context) {
12143    this.visit(ast.condition, context);
12144    this.visit(ast.trueExp, context);
12145    this.visit(ast.falseExp, context);
12146  }
12147
12148  visitPipe(ast, context) {
12149    this.visit(ast.exp, context);
12150    this.visitAll(ast.args, context);
12151  }
12152
12153  visitImplicitReceiver(ast, context) {}
12154
12155  visitThisReceiver(ast, context) {}
12156
12157  visitInterpolation(ast, context) {
12158    this.visitAll(ast.expressions, context);
12159  }
12160
12161  visitKeyedRead(ast, context) {
12162    this.visit(ast.receiver, context);
12163    this.visit(ast.key, context);
12164  }
12165
12166  visitKeyedWrite(ast, context) {
12167    this.visit(ast.receiver, context);
12168    this.visit(ast.key, context);
12169    this.visit(ast.value, context);
12170  }
12171
12172  visitLiteralArray(ast, context) {
12173    this.visitAll(ast.expressions, context);
12174  }
12175
12176  visitLiteralMap(ast, context) {
12177    this.visitAll(ast.values, context);
12178  }
12179
12180  visitLiteralPrimitive(ast, context) {}
12181
12182  visitPrefixNot(ast, context) {
12183    this.visit(ast.expression, context);
12184  }
12185
12186  visitNonNullAssert(ast, context) {
12187    this.visit(ast.expression, context);
12188  }
12189
12190  visitPropertyRead(ast, context) {
12191    this.visit(ast.receiver, context);
12192  }
12193
12194  visitPropertyWrite(ast, context) {
12195    this.visit(ast.receiver, context);
12196    this.visit(ast.value, context);
12197  }
12198
12199  visitSafePropertyRead(ast, context) {
12200    this.visit(ast.receiver, context);
12201  }
12202
12203  visitSafeKeyedRead(ast, context) {
12204    this.visit(ast.receiver, context);
12205    this.visit(ast.key, context);
12206  }
12207
12208  visitCall(ast, context) {
12209    this.visit(ast.receiver, context);
12210    this.visitAll(ast.args, context);
12211  }
12212
12213  visitSafeCall(ast, context) {
12214    this.visit(ast.receiver, context);
12215    this.visitAll(ast.args, context);
12216  } // This is not part of the AstVisitor interface, just a helper method
12217
12218
12219  visitAll(asts, context) {
12220    for (const ast of asts) {
12221      this.visit(ast, context);
12222    }
12223  }
12224
12225}
12226
12227class AstTransformer {
12228  visitImplicitReceiver(ast, context) {
12229    return ast;
12230  }
12231
12232  visitThisReceiver(ast, context) {
12233    return ast;
12234  }
12235
12236  visitInterpolation(ast, context) {
12237    return new Interpolation(ast.span, ast.sourceSpan, ast.strings, this.visitAll(ast.expressions));
12238  }
12239
12240  visitLiteralPrimitive(ast, context) {
12241    return new LiteralPrimitive(ast.span, ast.sourceSpan, ast.value);
12242  }
12243
12244  visitPropertyRead(ast, context) {
12245    return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name);
12246  }
12247
12248  visitPropertyWrite(ast, context) {
12249    return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name, ast.value.visit(this));
12250  }
12251
12252  visitSafePropertyRead(ast, context) {
12253    return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, ast.receiver.visit(this), ast.name);
12254  }
12255
12256  visitLiteralArray(ast, context) {
12257    return new LiteralArray(ast.span, ast.sourceSpan, this.visitAll(ast.expressions));
12258  }
12259
12260  visitLiteralMap(ast, context) {
12261    return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, this.visitAll(ast.values));
12262  }
12263
12264  visitUnary(ast, context) {
12265    switch (ast.operator) {
12266      case '+':
12267        return Unary.createPlus(ast.span, ast.sourceSpan, ast.expr.visit(this));
12268
12269      case '-':
12270        return Unary.createMinus(ast.span, ast.sourceSpan, ast.expr.visit(this));
12271
12272      default:
12273        throw new Error(`Unknown unary operator ${ast.operator}`);
12274    }
12275  }
12276
12277  visitBinary(ast, context) {
12278    return new Binary(ast.span, ast.sourceSpan, ast.operation, ast.left.visit(this), ast.right.visit(this));
12279  }
12280
12281  visitPrefixNot(ast, context) {
12282    return new PrefixNot(ast.span, ast.sourceSpan, ast.expression.visit(this));
12283  }
12284
12285  visitNonNullAssert(ast, context) {
12286    return new NonNullAssert(ast.span, ast.sourceSpan, ast.expression.visit(this));
12287  }
12288
12289  visitConditional(ast, context) {
12290    return new Conditional(ast.span, ast.sourceSpan, ast.condition.visit(this), ast.trueExp.visit(this), ast.falseExp.visit(this));
12291  }
12292
12293  visitPipe(ast, context) {
12294    return new BindingPipe(ast.span, ast.sourceSpan, ast.exp.visit(this), ast.name, this.visitAll(ast.args), ast.nameSpan);
12295  }
12296
12297  visitKeyedRead(ast, context) {
12298    return new KeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this));
12299  }
12300
12301  visitKeyedWrite(ast, context) {
12302    return new KeyedWrite(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this), ast.value.visit(this));
12303  }
12304
12305  visitCall(ast, context) {
12306    return new Call(ast.span, ast.sourceSpan, ast.receiver.visit(this), this.visitAll(ast.args), ast.argumentSpan);
12307  }
12308
12309  visitSafeCall(ast, context) {
12310    return new SafeCall(ast.span, ast.sourceSpan, ast.receiver.visit(this), this.visitAll(ast.args), ast.argumentSpan);
12311  }
12312
12313  visitAll(asts) {
12314    const res = [];
12315
12316    for (let i = 0; i < asts.length; ++i) {
12317      res[i] = asts[i].visit(this);
12318    }
12319
12320    return res;
12321  }
12322
12323  visitChain(ast, context) {
12324    return new Chain(ast.span, ast.sourceSpan, this.visitAll(ast.expressions));
12325  }
12326
12327  visitSafeKeyedRead(ast, context) {
12328    return new SafeKeyedRead(ast.span, ast.sourceSpan, ast.receiver.visit(this), ast.key.visit(this));
12329  }
12330
12331} // A transformer that only creates new nodes if the transformer makes a change or
12332// a change is made a child node.
12333
12334
12335class AstMemoryEfficientTransformer {
12336  visitImplicitReceiver(ast, context) {
12337    return ast;
12338  }
12339
12340  visitThisReceiver(ast, context) {
12341    return ast;
12342  }
12343
12344  visitInterpolation(ast, context) {
12345    const expressions = this.visitAll(ast.expressions);
12346    if (expressions !== ast.expressions) return new Interpolation(ast.span, ast.sourceSpan, ast.strings, expressions);
12347    return ast;
12348  }
12349
12350  visitLiteralPrimitive(ast, context) {
12351    return ast;
12352  }
12353
12354  visitPropertyRead(ast, context) {
12355    const receiver = ast.receiver.visit(this);
12356
12357    if (receiver !== ast.receiver) {
12358      return new PropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name);
12359    }
12360
12361    return ast;
12362  }
12363
12364  visitPropertyWrite(ast, context) {
12365    const receiver = ast.receiver.visit(this);
12366    const value = ast.value.visit(this);
12367
12368    if (receiver !== ast.receiver || value !== ast.value) {
12369      return new PropertyWrite(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name, value);
12370    }
12371
12372    return ast;
12373  }
12374
12375  visitSafePropertyRead(ast, context) {
12376    const receiver = ast.receiver.visit(this);
12377
12378    if (receiver !== ast.receiver) {
12379      return new SafePropertyRead(ast.span, ast.sourceSpan, ast.nameSpan, receiver, ast.name);
12380    }
12381
12382    return ast;
12383  }
12384
12385  visitLiteralArray(ast, context) {
12386    const expressions = this.visitAll(ast.expressions);
12387
12388    if (expressions !== ast.expressions) {
12389      return new LiteralArray(ast.span, ast.sourceSpan, expressions);
12390    }
12391
12392    return ast;
12393  }
12394
12395  visitLiteralMap(ast, context) {
12396    const values = this.visitAll(ast.values);
12397
12398    if (values !== ast.values) {
12399      return new LiteralMap(ast.span, ast.sourceSpan, ast.keys, values);
12400    }
12401
12402    return ast;
12403  }
12404
12405  visitUnary(ast, context) {
12406    const expr = ast.expr.visit(this);
12407
12408    if (expr !== ast.expr) {
12409      switch (ast.operator) {
12410        case '+':
12411          return Unary.createPlus(ast.span, ast.sourceSpan, expr);
12412
12413        case '-':
12414          return Unary.createMinus(ast.span, ast.sourceSpan, expr);
12415
12416        default:
12417          throw new Error(`Unknown unary operator ${ast.operator}`);
12418      }
12419    }
12420
12421    return ast;
12422  }
12423
12424  visitBinary(ast, context) {
12425    const left = ast.left.visit(this);
12426    const right = ast.right.visit(this);
12427
12428    if (left !== ast.left || right !== ast.right) {
12429      return new Binary(ast.span, ast.sourceSpan, ast.operation, left, right);
12430    }
12431
12432    return ast;
12433  }
12434
12435  visitPrefixNot(ast, context) {
12436    const expression = ast.expression.visit(this);
12437
12438    if (expression !== ast.expression) {
12439      return new PrefixNot(ast.span, ast.sourceSpan, expression);
12440    }
12441
12442    return ast;
12443  }
12444
12445  visitNonNullAssert(ast, context) {
12446    const expression = ast.expression.visit(this);
12447
12448    if (expression !== ast.expression) {
12449      return new NonNullAssert(ast.span, ast.sourceSpan, expression);
12450    }
12451
12452    return ast;
12453  }
12454
12455  visitConditional(ast, context) {
12456    const condition = ast.condition.visit(this);
12457    const trueExp = ast.trueExp.visit(this);
12458    const falseExp = ast.falseExp.visit(this);
12459
12460    if (condition !== ast.condition || trueExp !== ast.trueExp || falseExp !== ast.falseExp) {
12461      return new Conditional(ast.span, ast.sourceSpan, condition, trueExp, falseExp);
12462    }
12463
12464    return ast;
12465  }
12466
12467  visitPipe(ast, context) {
12468    const exp = ast.exp.visit(this);
12469    const args = this.visitAll(ast.args);
12470
12471    if (exp !== ast.exp || args !== ast.args) {
12472      return new BindingPipe(ast.span, ast.sourceSpan, exp, ast.name, args, ast.nameSpan);
12473    }
12474
12475    return ast;
12476  }
12477
12478  visitKeyedRead(ast, context) {
12479    const obj = ast.receiver.visit(this);
12480    const key = ast.key.visit(this);
12481
12482    if (obj !== ast.receiver || key !== ast.key) {
12483      return new KeyedRead(ast.span, ast.sourceSpan, obj, key);
12484    }
12485
12486    return ast;
12487  }
12488
12489  visitKeyedWrite(ast, context) {
12490    const obj = ast.receiver.visit(this);
12491    const key = ast.key.visit(this);
12492    const value = ast.value.visit(this);
12493
12494    if (obj !== ast.receiver || key !== ast.key || value !== ast.value) {
12495      return new KeyedWrite(ast.span, ast.sourceSpan, obj, key, value);
12496    }
12497
12498    return ast;
12499  }
12500
12501  visitAll(asts) {
12502    const res = [];
12503    let modified = false;
12504
12505    for (let i = 0; i < asts.length; ++i) {
12506      const original = asts[i];
12507      const value = original.visit(this);
12508      res[i] = value;
12509      modified = modified || value !== original;
12510    }
12511
12512    return modified ? res : asts;
12513  }
12514
12515  visitChain(ast, context) {
12516    const expressions = this.visitAll(ast.expressions);
12517
12518    if (expressions !== ast.expressions) {
12519      return new Chain(ast.span, ast.sourceSpan, expressions);
12520    }
12521
12522    return ast;
12523  }
12524
12525  visitCall(ast, context) {
12526    const receiver = ast.receiver.visit(this);
12527    const args = this.visitAll(ast.args);
12528
12529    if (receiver !== ast.receiver || args !== ast.args) {
12530      return new Call(ast.span, ast.sourceSpan, receiver, args, ast.argumentSpan);
12531    }
12532
12533    return ast;
12534  }
12535
12536  visitSafeCall(ast, context) {
12537    const receiver = ast.receiver.visit(this);
12538    const args = this.visitAll(ast.args);
12539
12540    if (receiver !== ast.receiver || args !== ast.args) {
12541      return new SafeCall(ast.span, ast.sourceSpan, receiver, args, ast.argumentSpan);
12542    }
12543
12544    return ast;
12545  }
12546
12547  visitSafeKeyedRead(ast, context) {
12548    const obj = ast.receiver.visit(this);
12549    const key = ast.key.visit(this);
12550
12551    if (obj !== ast.receiver || key !== ast.key) {
12552      return new SafeKeyedRead(ast.span, ast.sourceSpan, obj, key);
12553    }
12554
12555    return ast;
12556  }
12557
12558} // Bindings
12559
12560
12561class ParsedProperty {
12562  constructor(name, expression, type, sourceSpan, keySpan, valueSpan) {
12563    this.name = name;
12564    this.expression = expression;
12565    this.type = type;
12566    this.sourceSpan = sourceSpan;
12567    this.keySpan = keySpan;
12568    this.valueSpan = valueSpan;
12569    this.isLiteral = this.type === ParsedPropertyType.LITERAL_ATTR;
12570    this.isAnimation = this.type === ParsedPropertyType.ANIMATION;
12571  }
12572
12573}
12574
12575var ParsedPropertyType;
12576
12577(function (ParsedPropertyType) {
12578  ParsedPropertyType[ParsedPropertyType["DEFAULT"] = 0] = "DEFAULT";
12579  ParsedPropertyType[ParsedPropertyType["LITERAL_ATTR"] = 1] = "LITERAL_ATTR";
12580  ParsedPropertyType[ParsedPropertyType["ANIMATION"] = 2] = "ANIMATION";
12581})(ParsedPropertyType || (ParsedPropertyType = {}));
12582
12583class ParsedEvent {
12584  // Regular events have a target
12585  // Animation events have a phase
12586  constructor(name, targetOrPhase, type, handler, sourceSpan, handlerSpan, keySpan) {
12587    this.name = name;
12588    this.targetOrPhase = targetOrPhase;
12589    this.type = type;
12590    this.handler = handler;
12591    this.sourceSpan = sourceSpan;
12592    this.handlerSpan = handlerSpan;
12593    this.keySpan = keySpan;
12594  }
12595
12596}
12597/**
12598 * ParsedVariable represents a variable declaration in a microsyntax expression.
12599 */
12600
12601
12602class ParsedVariable {
12603  constructor(name, value, sourceSpan, keySpan, valueSpan) {
12604    this.name = name;
12605    this.value = value;
12606    this.sourceSpan = sourceSpan;
12607    this.keySpan = keySpan;
12608    this.valueSpan = valueSpan;
12609  }
12610
12611}
12612
12613class BoundElementProperty {
12614  constructor(name, type, securityContext, value, unit, sourceSpan, keySpan, valueSpan) {
12615    this.name = name;
12616    this.type = type;
12617    this.securityContext = securityContext;
12618    this.value = value;
12619    this.unit = unit;
12620    this.sourceSpan = sourceSpan;
12621    this.keySpan = keySpan;
12622    this.valueSpan = valueSpan;
12623  }
12624
12625}
12626/**
12627 * @license
12628 * Copyright Google LLC All Rights Reserved.
12629 *
12630 * Use of this source code is governed by an MIT-style license that can be
12631 * found in the LICENSE file at https://angular.io/license
12632 */
12633
12634
12635class EventHandlerVars {}
12636
12637EventHandlerVars.event = variable('$event');
12638/**
12639 * Converts the given expression AST into an executable output AST, assuming the expression is
12640 * used in an action binding (e.g. an event handler).
12641 */
12642
12643function convertActionBinding(localResolver, implicitReceiver, action, bindingId, baseSourceSpan, implicitReceiverAccesses, globals) {
12644  if (!localResolver) {
12645    localResolver = new DefaultLocalResolver(globals);
12646  }
12647
12648  const actionWithoutBuiltins = convertPropertyBindingBuiltins({
12649    createLiteralArrayConverter: argCount => {
12650      // Note: no caching for literal arrays in actions.
12651      return args => literalArr(args);
12652    },
12653    createLiteralMapConverter: keys => {
12654      // Note: no caching for literal maps in actions.
12655      return values => {
12656        const entries = keys.map((k, i) => ({
12657          key: k.key,
12658          value: values[i],
12659          quoted: k.quoted
12660        }));
12661        return literalMap(entries);
12662      };
12663    },
12664    createPipeConverter: name => {
12665      throw new Error(`Illegal State: Actions are not allowed to contain pipes. Pipe: ${name}`);
12666    }
12667  }, action);
12668  const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId,
12669  /* supportsInterpolation */
12670  false, baseSourceSpan, implicitReceiverAccesses);
12671  const actionStmts = [];
12672  flattenStatements(actionWithoutBuiltins.visit(visitor, _Mode.Statement), actionStmts);
12673  prependTemporaryDecls(visitor.temporaryCount, bindingId, actionStmts);
12674
12675  if (visitor.usesImplicitReceiver) {
12676    localResolver.notifyImplicitReceiverUse();
12677  }
12678
12679  const lastIndex = actionStmts.length - 1;
12680
12681  if (lastIndex >= 0) {
12682    const lastStatement = actionStmts[lastIndex]; // Ensure that the value of the last expression statement is returned
12683
12684    if (lastStatement instanceof ExpressionStatement) {
12685      actionStmts[lastIndex] = new ReturnStatement(lastStatement.expr);
12686    }
12687  }
12688
12689  return actionStmts;
12690}
12691
12692function convertPropertyBindingBuiltins(converterFactory, ast) {
12693  return convertBuiltins(converterFactory, ast);
12694}
12695
12696class ConvertPropertyBindingResult {
12697  constructor(stmts, currValExpr) {
12698    this.stmts = stmts;
12699    this.currValExpr = currValExpr;
12700  }
12701
12702}
12703/**
12704 * Converts the given expression AST into an executable output AST, assuming the expression
12705 * is used in property binding. The expression has to be preprocessed via
12706 * `convertPropertyBindingBuiltins`.
12707 */
12708
12709
12710function convertPropertyBinding(localResolver, implicitReceiver, expressionWithoutBuiltins, bindingId) {
12711  if (!localResolver) {
12712    localResolver = new DefaultLocalResolver();
12713  }
12714
12715  const visitor = new _AstToIrVisitor(localResolver, implicitReceiver, bindingId,
12716  /* supportsInterpolation */
12717  false);
12718  const outputExpr = expressionWithoutBuiltins.visit(visitor, _Mode.Expression);
12719  const stmts = getStatementsFromVisitor(visitor, bindingId);
12720
12721  if (visitor.usesImplicitReceiver) {
12722    localResolver.notifyImplicitReceiverUse();
12723  }
12724
12725  return new ConvertPropertyBindingResult(stmts, outputExpr);
12726}
12727/**
12728 * Given some expression, such as a binding or interpolation expression, and a context expression to
12729 * look values up on, visit each facet of the given expression resolving values from the context
12730 * expression such that a list of arguments can be derived from the found values that can be used as
12731 * arguments to an external update instruction.
12732 *
12733 * @param localResolver The resolver to use to look up expressions by name appropriately
12734 * @param contextVariableExpression The expression representing the context variable used to create
12735 * the final argument expressions
12736 * @param expressionWithArgumentsToExtract The expression to visit to figure out what values need to
12737 * be resolved and what arguments list to build.
12738 * @param bindingId A name prefix used to create temporary variable names if they're needed for the
12739 * arguments generated
12740 * @returns An array of expressions that can be passed as arguments to instruction expressions like
12741 * `o.importExpr(R3.propertyInterpolate).callFn(result)`
12742 */
12743
12744
12745function convertUpdateArguments(localResolver, contextVariableExpression, expressionWithArgumentsToExtract, bindingId) {
12746  const visitor = new _AstToIrVisitor(localResolver, contextVariableExpression, bindingId,
12747  /* supportsInterpolation */
12748  true);
12749  const outputExpr = visitor.visitInterpolation(expressionWithArgumentsToExtract, _Mode.Expression);
12750
12751  if (visitor.usesImplicitReceiver) {
12752    localResolver.notifyImplicitReceiverUse();
12753  }
12754
12755  const stmts = getStatementsFromVisitor(visitor, bindingId);
12756  const args = outputExpr.args;
12757  return {
12758    stmts,
12759    args
12760  };
12761}
12762
12763function getStatementsFromVisitor(visitor, bindingId) {
12764  const stmts = [];
12765
12766  for (let i = 0; i < visitor.temporaryCount; i++) {
12767    stmts.push(temporaryDeclaration(bindingId, i));
12768  }
12769
12770  return stmts;
12771}
12772
12773function convertBuiltins(converterFactory, ast) {
12774  const visitor = new _BuiltinAstConverter(converterFactory);
12775  return ast.visit(visitor);
12776}
12777
12778function temporaryName(bindingId, temporaryNumber) {
12779  return `tmp_${bindingId}_${temporaryNumber}`;
12780}
12781
12782function temporaryDeclaration(bindingId, temporaryNumber) {
12783  return new DeclareVarStmt(temporaryName(bindingId, temporaryNumber));
12784}
12785
12786function prependTemporaryDecls(temporaryCount, bindingId, statements) {
12787  for (let i = temporaryCount - 1; i >= 0; i--) {
12788    statements.unshift(temporaryDeclaration(bindingId, i));
12789  }
12790}
12791
12792var _Mode;
12793
12794(function (_Mode) {
12795  _Mode[_Mode["Statement"] = 0] = "Statement";
12796  _Mode[_Mode["Expression"] = 1] = "Expression";
12797})(_Mode || (_Mode = {}));
12798
12799function ensureStatementMode(mode, ast) {
12800  if (mode !== _Mode.Statement) {
12801    throw new Error(`Expected a statement, but saw ${ast}`);
12802  }
12803}
12804
12805function ensureExpressionMode(mode, ast) {
12806  if (mode !== _Mode.Expression) {
12807    throw new Error(`Expected an expression, but saw ${ast}`);
12808  }
12809}
12810
12811function convertToStatementIfNeeded(mode, expr) {
12812  if (mode === _Mode.Statement) {
12813    return expr.toStmt();
12814  } else {
12815    return expr;
12816  }
12817}
12818
12819class _BuiltinAstConverter extends AstTransformer {
12820  constructor(_converterFactory) {
12821    super();
12822    this._converterFactory = _converterFactory;
12823  }
12824
12825  visitPipe(ast, context) {
12826    const args = [ast.exp, ...ast.args].map(ast => ast.visit(this, context));
12827    return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createPipeConverter(ast.name, args.length));
12828  }
12829
12830  visitLiteralArray(ast, context) {
12831    const args = ast.expressions.map(ast => ast.visit(this, context));
12832    return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralArrayConverter(ast.expressions.length));
12833  }
12834
12835  visitLiteralMap(ast, context) {
12836    const args = ast.values.map(ast => ast.visit(this, context));
12837    return new BuiltinFunctionCall(ast.span, ast.sourceSpan, args, this._converterFactory.createLiteralMapConverter(ast.keys));
12838  }
12839
12840}
12841
12842class _AstToIrVisitor {
12843  constructor(_localResolver, _implicitReceiver, bindingId, supportsInterpolation, baseSourceSpan, implicitReceiverAccesses) {
12844    this._localResolver = _localResolver;
12845    this._implicitReceiver = _implicitReceiver;
12846    this.bindingId = bindingId;
12847    this.supportsInterpolation = supportsInterpolation;
12848    this.baseSourceSpan = baseSourceSpan;
12849    this.implicitReceiverAccesses = implicitReceiverAccesses;
12850    this._nodeMap = new Map();
12851    this._resultMap = new Map();
12852    this._currentTemporary = 0;
12853    this.temporaryCount = 0;
12854    this.usesImplicitReceiver = false;
12855  }
12856
12857  visitUnary(ast, mode) {
12858    let op;
12859
12860    switch (ast.operator) {
12861      case '+':
12862        op = UnaryOperator.Plus;
12863        break;
12864
12865      case '-':
12866        op = UnaryOperator.Minus;
12867        break;
12868
12869      default:
12870        throw new Error(`Unsupported operator ${ast.operator}`);
12871    }
12872
12873    return convertToStatementIfNeeded(mode, new UnaryOperatorExpr(op, this._visit(ast.expr, _Mode.Expression), undefined, this.convertSourceSpan(ast.span)));
12874  }
12875
12876  visitBinary(ast, mode) {
12877    let op;
12878
12879    switch (ast.operation) {
12880      case '+':
12881        op = BinaryOperator.Plus;
12882        break;
12883
12884      case '-':
12885        op = BinaryOperator.Minus;
12886        break;
12887
12888      case '*':
12889        op = BinaryOperator.Multiply;
12890        break;
12891
12892      case '/':
12893        op = BinaryOperator.Divide;
12894        break;
12895
12896      case '%':
12897        op = BinaryOperator.Modulo;
12898        break;
12899
12900      case '&&':
12901        op = BinaryOperator.And;
12902        break;
12903
12904      case '||':
12905        op = BinaryOperator.Or;
12906        break;
12907
12908      case '==':
12909        op = BinaryOperator.Equals;
12910        break;
12911
12912      case '!=':
12913        op = BinaryOperator.NotEquals;
12914        break;
12915
12916      case '===':
12917        op = BinaryOperator.Identical;
12918        break;
12919
12920      case '!==':
12921        op = BinaryOperator.NotIdentical;
12922        break;
12923
12924      case '<':
12925        op = BinaryOperator.Lower;
12926        break;
12927
12928      case '>':
12929        op = BinaryOperator.Bigger;
12930        break;
12931
12932      case '<=':
12933        op = BinaryOperator.LowerEquals;
12934        break;
12935
12936      case '>=':
12937        op = BinaryOperator.BiggerEquals;
12938        break;
12939
12940      case '??':
12941        return this.convertNullishCoalesce(ast, mode);
12942
12943      default:
12944        throw new Error(`Unsupported operation ${ast.operation}`);
12945    }
12946
12947    return convertToStatementIfNeeded(mode, new BinaryOperatorExpr(op, this._visit(ast.left, _Mode.Expression), this._visit(ast.right, _Mode.Expression), undefined, this.convertSourceSpan(ast.span)));
12948  }
12949
12950  visitChain(ast, mode) {
12951    ensureStatementMode(mode, ast);
12952    return this.visitAll(ast.expressions, mode);
12953  }
12954
12955  visitConditional(ast, mode) {
12956    const value = this._visit(ast.condition, _Mode.Expression);
12957
12958    return convertToStatementIfNeeded(mode, value.conditional(this._visit(ast.trueExp, _Mode.Expression), this._visit(ast.falseExp, _Mode.Expression), this.convertSourceSpan(ast.span)));
12959  }
12960
12961  visitPipe(ast, mode) {
12962    throw new Error(`Illegal state: Pipes should have been converted into functions. Pipe: ${ast.name}`);
12963  }
12964
12965  visitImplicitReceiver(ast, mode) {
12966    ensureExpressionMode(mode, ast);
12967    this.usesImplicitReceiver = true;
12968    return this._implicitReceiver;
12969  }
12970
12971  visitThisReceiver(ast, mode) {
12972    return this.visitImplicitReceiver(ast, mode);
12973  }
12974
12975  visitInterpolation(ast, mode) {
12976    if (!this.supportsInterpolation) {
12977      throw new Error('Unexpected interpolation');
12978    }
12979
12980    ensureExpressionMode(mode, ast);
12981    let args = [];
12982
12983    for (let i = 0; i < ast.strings.length - 1; i++) {
12984      args.push(literal(ast.strings[i]));
12985      args.push(this._visit(ast.expressions[i], _Mode.Expression));
12986    }
12987
12988    args.push(literal(ast.strings[ast.strings.length - 1])); // If we're dealing with an interpolation of 1 value with an empty prefix and suffix, reduce the
12989    // args returned to just the value, because we're going to pass it to a special instruction.
12990
12991    const strings = ast.strings;
12992
12993    if (strings.length === 2 && strings[0] === '' && strings[1] === '') {
12994      // Single argument interpolate instructions.
12995      args = [args[1]];
12996    } else if (ast.expressions.length >= 9) {
12997      // 9 or more arguments must be passed to the `interpolateV`-style instructions, which accept
12998      // an array of arguments
12999      args = [literalArr(args)];
13000    }
13001
13002    return new InterpolationExpression(args);
13003  }
13004
13005  visitKeyedRead(ast, mode) {
13006    const leftMostSafe = this.leftMostSafeNode(ast);
13007
13008    if (leftMostSafe) {
13009      return this.convertSafeAccess(ast, leftMostSafe, mode);
13010    } else {
13011      return convertToStatementIfNeeded(mode, this._visit(ast.receiver, _Mode.Expression).key(this._visit(ast.key, _Mode.Expression)));
13012    }
13013  }
13014
13015  visitKeyedWrite(ast, mode) {
13016    const obj = this._visit(ast.receiver, _Mode.Expression);
13017
13018    const key = this._visit(ast.key, _Mode.Expression);
13019
13020    const value = this._visit(ast.value, _Mode.Expression);
13021
13022    if (obj === this._implicitReceiver) {
13023      this._localResolver.maybeRestoreView();
13024    }
13025
13026    return convertToStatementIfNeeded(mode, obj.key(key).set(value));
13027  }
13028
13029  visitLiteralArray(ast, mode) {
13030    throw new Error(`Illegal State: literal arrays should have been converted into functions`);
13031  }
13032
13033  visitLiteralMap(ast, mode) {
13034    throw new Error(`Illegal State: literal maps should have been converted into functions`);
13035  }
13036
13037  visitLiteralPrimitive(ast, mode) {
13038    // For literal values of null, undefined, true, or false allow type interference
13039    // to infer the type.
13040    const type = ast.value === null || ast.value === undefined || ast.value === true || ast.value === true ? INFERRED_TYPE : undefined;
13041    return convertToStatementIfNeeded(mode, literal(ast.value, type, this.convertSourceSpan(ast.span)));
13042  }
13043
13044  _getLocal(name, receiver) {
13045    if (this._localResolver.globals?.has(name) && receiver instanceof ThisReceiver) {
13046      return null;
13047    }
13048
13049    return this._localResolver.getLocal(name);
13050  }
13051
13052  visitPrefixNot(ast, mode) {
13053    return convertToStatementIfNeeded(mode, not(this._visit(ast.expression, _Mode.Expression)));
13054  }
13055
13056  visitNonNullAssert(ast, mode) {
13057    return convertToStatementIfNeeded(mode, this._visit(ast.expression, _Mode.Expression));
13058  }
13059
13060  visitPropertyRead(ast, mode) {
13061    const leftMostSafe = this.leftMostSafeNode(ast);
13062
13063    if (leftMostSafe) {
13064      return this.convertSafeAccess(ast, leftMostSafe, mode);
13065    } else {
13066      let result = null;
13067      const prevUsesImplicitReceiver = this.usesImplicitReceiver;
13068
13069      const receiver = this._visit(ast.receiver, _Mode.Expression);
13070
13071      if (receiver === this._implicitReceiver) {
13072        result = this._getLocal(ast.name, ast.receiver);
13073
13074        if (result) {
13075          // Restore the previous "usesImplicitReceiver" state since the implicit
13076          // receiver has been replaced with a resolved local expression.
13077          this.usesImplicitReceiver = prevUsesImplicitReceiver;
13078          this.addImplicitReceiverAccess(ast.name);
13079        }
13080      }
13081
13082      if (result == null) {
13083        result = receiver.prop(ast.name, this.convertSourceSpan(ast.span));
13084      }
13085
13086      return convertToStatementIfNeeded(mode, result);
13087    }
13088  }
13089
13090  visitPropertyWrite(ast, mode) {
13091    const receiver = this._visit(ast.receiver, _Mode.Expression);
13092
13093    const prevUsesImplicitReceiver = this.usesImplicitReceiver;
13094    let varExpr = null;
13095
13096    if (receiver === this._implicitReceiver) {
13097      const localExpr = this._getLocal(ast.name, ast.receiver);
13098
13099      if (localExpr) {
13100        if (localExpr instanceof ReadPropExpr) {
13101          // If the local variable is a property read expression, it's a reference
13102          // to a 'context.property' value and will be used as the target of the
13103          // write expression.
13104          varExpr = localExpr; // Restore the previous "usesImplicitReceiver" state since the implicit
13105          // receiver has been replaced with a resolved local expression.
13106
13107          this.usesImplicitReceiver = prevUsesImplicitReceiver;
13108          this.addImplicitReceiverAccess(ast.name);
13109        } else {
13110          // Otherwise it's an error.
13111          const receiver = ast.name;
13112          const value = ast.value instanceof PropertyRead ? ast.value.name : undefined;
13113          throw new Error(`Cannot assign value "${value}" to template variable "${receiver}". Template variables are read-only.`);
13114        }
13115      }
13116    } // If no local expression could be produced, use the original receiver's
13117    // property as the target.
13118
13119
13120    if (varExpr === null) {
13121      varExpr = receiver.prop(ast.name, this.convertSourceSpan(ast.span));
13122    }
13123
13124    return convertToStatementIfNeeded(mode, varExpr.set(this._visit(ast.value, _Mode.Expression)));
13125  }
13126
13127  visitSafePropertyRead(ast, mode) {
13128    return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
13129  }
13130
13131  visitSafeKeyedRead(ast, mode) {
13132    return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
13133  }
13134
13135  visitAll(asts, mode) {
13136    return asts.map(ast => this._visit(ast, mode));
13137  }
13138
13139  visitCall(ast, mode) {
13140    const leftMostSafe = this.leftMostSafeNode(ast);
13141
13142    if (leftMostSafe) {
13143      return this.convertSafeAccess(ast, leftMostSafe, mode);
13144    }
13145
13146    const convertedArgs = this.visitAll(ast.args, _Mode.Expression);
13147
13148    if (ast instanceof BuiltinFunctionCall) {
13149      return convertToStatementIfNeeded(mode, ast.converter(convertedArgs));
13150    }
13151
13152    const receiver = ast.receiver;
13153
13154    if (receiver instanceof PropertyRead && receiver.receiver instanceof ImplicitReceiver && !(receiver.receiver instanceof ThisReceiver) && receiver.name === '$any') {
13155      if (convertedArgs.length !== 1) {
13156        throw new Error(`Invalid call to $any, expected 1 argument but received ${convertedArgs.length || 'none'}`);
13157      }
13158
13159      return convertToStatementIfNeeded(mode, convertedArgs[0]);
13160    }
13161
13162    const call = this._visit(receiver, _Mode.Expression).callFn(convertedArgs, this.convertSourceSpan(ast.span));
13163
13164    return convertToStatementIfNeeded(mode, call);
13165  }
13166
13167  visitSafeCall(ast, mode) {
13168    return this.convertSafeAccess(ast, this.leftMostSafeNode(ast), mode);
13169  }
13170
13171  _visit(ast, mode) {
13172    const result = this._resultMap.get(ast);
13173
13174    if (result) return result;
13175    return (this._nodeMap.get(ast) || ast).visit(this, mode);
13176  }
13177
13178  convertSafeAccess(ast, leftMostSafe, mode) {
13179    // If the expression contains a safe access node on the left it needs to be converted to
13180    // an expression that guards the access to the member by checking the receiver for blank. As
13181    // execution proceeds from left to right, the left most part of the expression must be guarded
13182    // first but, because member access is left associative, the right side of the expression is at
13183    // the top of the AST. The desired result requires lifting a copy of the left part of the
13184    // expression up to test it for blank before generating the unguarded version.
13185    // Consider, for example the following expression: a?.b.c?.d.e
13186    // This results in the ast:
13187    //         .
13188    //        / \
13189    //       ?.   e
13190    //      /  \
13191    //     .    d
13192    //    / \
13193    //   ?.  c
13194    //  /  \
13195    // a    b
13196    // The following tree should be generated:
13197    //
13198    //        /---- ? ----\
13199    //       /      |      \
13200    //     a   /--- ? ---\  null
13201    //        /     |     \
13202    //       .      .     null
13203    //      / \    / \
13204    //     .  c   .   e
13205    //    / \    / \
13206    //   a   b  .   d
13207    //         / \
13208    //        .   c
13209    //       / \
13210    //      a   b
13211    //
13212    // Notice that the first guard condition is the left hand of the left most safe access node
13213    // which comes in as leftMostSafe to this routine.
13214    let guardedExpression = this._visit(leftMostSafe.receiver, _Mode.Expression);
13215
13216    let temporary = undefined;
13217
13218    if (this.needsTemporaryInSafeAccess(leftMostSafe.receiver)) {
13219      // If the expression has method calls or pipes then we need to save the result into a
13220      // temporary variable to avoid calling stateful or impure code more than once.
13221      temporary = this.allocateTemporary(); // Preserve the result in the temporary variable
13222
13223      guardedExpression = temporary.set(guardedExpression); // Ensure all further references to the guarded expression refer to the temporary instead.
13224
13225      this._resultMap.set(leftMostSafe.receiver, temporary);
13226    }
13227
13228    const condition = guardedExpression.isBlank(); // Convert the ast to an unguarded access to the receiver's member. The map will substitute
13229    // leftMostNode with its unguarded version in the call to `this.visit()`.
13230
13231    if (leftMostSafe instanceof SafeCall) {
13232      this._nodeMap.set(leftMostSafe, new Call(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.args, leftMostSafe.argumentSpan));
13233    } else if (leftMostSafe instanceof SafeKeyedRead) {
13234      this._nodeMap.set(leftMostSafe, new KeyedRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.receiver, leftMostSafe.key));
13235    } else {
13236      this._nodeMap.set(leftMostSafe, new PropertyRead(leftMostSafe.span, leftMostSafe.sourceSpan, leftMostSafe.nameSpan, leftMostSafe.receiver, leftMostSafe.name));
13237    } // Recursively convert the node now without the guarded member access.
13238
13239
13240    const access = this._visit(ast, _Mode.Expression); // Remove the mapping. This is not strictly required as the converter only traverses each node
13241    // once but is safer if the conversion is changed to traverse the nodes more than once.
13242
13243
13244    this._nodeMap.delete(leftMostSafe); // If we allocated a temporary, release it.
13245
13246
13247    if (temporary) {
13248      this.releaseTemporary(temporary);
13249    } // Produce the conditional
13250
13251
13252    return convertToStatementIfNeeded(mode, condition.conditional(NULL_EXPR, access));
13253  }
13254
13255  convertNullishCoalesce(ast, mode) {
13256    const left = this._visit(ast.left, _Mode.Expression);
13257
13258    const right = this._visit(ast.right, _Mode.Expression);
13259
13260    const temporary = this.allocateTemporary();
13261    this.releaseTemporary(temporary); // Generate the following expression. It is identical to how TS
13262    // transpiles binary expressions with a nullish coalescing operator.
13263    // let temp;
13264    // (temp = a) !== null && temp !== undefined ? temp : b;
13265
13266    return convertToStatementIfNeeded(mode, temporary.set(left).notIdentical(NULL_EXPR).and(temporary.notIdentical(literal(undefined))).conditional(temporary, right));
13267  } // Given an expression of the form a?.b.c?.d.e then the left most safe node is
13268  // the (a?.b). The . and ?. are left associative thus can be rewritten as:
13269  // ((((a?.c).b).c)?.d).e. This returns the most deeply nested safe read or
13270  // safe method call as this needs to be transformed initially to:
13271  //   a == null ? null : a.c.b.c?.d.e
13272  // then to:
13273  //   a == null ? null : a.b.c == null ? null : a.b.c.d.e
13274
13275
13276  leftMostSafeNode(ast) {
13277    const visit = (visitor, ast) => {
13278      return (this._nodeMap.get(ast) || ast).visit(visitor);
13279    };
13280
13281    return ast.visit({
13282      visitUnary(ast) {
13283        return null;
13284      },
13285
13286      visitBinary(ast) {
13287        return null;
13288      },
13289
13290      visitChain(ast) {
13291        return null;
13292      },
13293
13294      visitConditional(ast) {
13295        return null;
13296      },
13297
13298      visitCall(ast) {
13299        return visit(this, ast.receiver);
13300      },
13301
13302      visitSafeCall(ast) {
13303        return visit(this, ast.receiver) || ast;
13304      },
13305
13306      visitImplicitReceiver(ast) {
13307        return null;
13308      },
13309
13310      visitThisReceiver(ast) {
13311        return null;
13312      },
13313
13314      visitInterpolation(ast) {
13315        return null;
13316      },
13317
13318      visitKeyedRead(ast) {
13319        return visit(this, ast.receiver);
13320      },
13321
13322      visitKeyedWrite(ast) {
13323        return null;
13324      },
13325
13326      visitLiteralArray(ast) {
13327        return null;
13328      },
13329
13330      visitLiteralMap(ast) {
13331        return null;
13332      },
13333
13334      visitLiteralPrimitive(ast) {
13335        return null;
13336      },
13337
13338      visitPipe(ast) {
13339        return null;
13340      },
13341
13342      visitPrefixNot(ast) {
13343        return null;
13344      },
13345
13346      visitNonNullAssert(ast) {
13347        return null;
13348      },
13349
13350      visitPropertyRead(ast) {
13351        return visit(this, ast.receiver);
13352      },
13353
13354      visitPropertyWrite(ast) {
13355        return null;
13356      },
13357
13358      visitSafePropertyRead(ast) {
13359        return visit(this, ast.receiver) || ast;
13360      },
13361
13362      visitSafeKeyedRead(ast) {
13363        return visit(this, ast.receiver) || ast;
13364      }
13365
13366    });
13367  } // Returns true of the AST includes a method or a pipe indicating that, if the
13368  // expression is used as the target of a safe property or method access then
13369  // the expression should be stored into a temporary variable.
13370
13371
13372  needsTemporaryInSafeAccess(ast) {
13373    const visit = (visitor, ast) => {
13374      return ast && (this._nodeMap.get(ast) || ast).visit(visitor);
13375    };
13376
13377    const visitSome = (visitor, ast) => {
13378      return ast.some(ast => visit(visitor, ast));
13379    };
13380
13381    return ast.visit({
13382      visitUnary(ast) {
13383        return visit(this, ast.expr);
13384      },
13385
13386      visitBinary(ast) {
13387        return visit(this, ast.left) || visit(this, ast.right);
13388      },
13389
13390      visitChain(ast) {
13391        return false;
13392      },
13393
13394      visitConditional(ast) {
13395        return visit(this, ast.condition) || visit(this, ast.trueExp) || visit(this, ast.falseExp);
13396      },
13397
13398      visitCall(ast) {
13399        return true;
13400      },
13401
13402      visitSafeCall(ast) {
13403        return true;
13404      },
13405
13406      visitImplicitReceiver(ast) {
13407        return false;
13408      },
13409
13410      visitThisReceiver(ast) {
13411        return false;
13412      },
13413
13414      visitInterpolation(ast) {
13415        return visitSome(this, ast.expressions);
13416      },
13417
13418      visitKeyedRead(ast) {
13419        return false;
13420      },
13421
13422      visitKeyedWrite(ast) {
13423        return false;
13424      },
13425
13426      visitLiteralArray(ast) {
13427        return true;
13428      },
13429
13430      visitLiteralMap(ast) {
13431        return true;
13432      },
13433
13434      visitLiteralPrimitive(ast) {
13435        return false;
13436      },
13437
13438      visitPipe(ast) {
13439        return true;
13440      },
13441
13442      visitPrefixNot(ast) {
13443        return visit(this, ast.expression);
13444      },
13445
13446      visitNonNullAssert(ast) {
13447        return visit(this, ast.expression);
13448      },
13449
13450      visitPropertyRead(ast) {
13451        return false;
13452      },
13453
13454      visitPropertyWrite(ast) {
13455        return false;
13456      },
13457
13458      visitSafePropertyRead(ast) {
13459        return false;
13460      },
13461
13462      visitSafeKeyedRead(ast) {
13463        return false;
13464      }
13465
13466    });
13467  }
13468
13469  allocateTemporary() {
13470    const tempNumber = this._currentTemporary++;
13471    this.temporaryCount = Math.max(this._currentTemporary, this.temporaryCount);
13472    return new ReadVarExpr(temporaryName(this.bindingId, tempNumber));
13473  }
13474
13475  releaseTemporary(temporary) {
13476    this._currentTemporary--;
13477
13478    if (temporary.name != temporaryName(this.bindingId, this._currentTemporary)) {
13479      throw new Error(`Temporary ${temporary.name} released out of order`);
13480    }
13481  }
13482  /**
13483   * Creates an absolute `ParseSourceSpan` from the relative `ParseSpan`.
13484   *
13485   * `ParseSpan` objects are relative to the start of the expression.
13486   * This method converts these to full `ParseSourceSpan` objects that
13487   * show where the span is within the overall source file.
13488   *
13489   * @param span the relative span to convert.
13490   * @returns a `ParseSourceSpan` for the given span or null if no
13491   * `baseSourceSpan` was provided to this class.
13492   */
13493
13494
13495  convertSourceSpan(span) {
13496    if (this.baseSourceSpan) {
13497      const start = this.baseSourceSpan.start.moveBy(span.start);
13498      const end = this.baseSourceSpan.start.moveBy(span.end);
13499      const fullStart = this.baseSourceSpan.fullStart.moveBy(span.start);
13500      return new ParseSourceSpan(start, end, fullStart);
13501    } else {
13502      return null;
13503    }
13504  }
13505  /** Adds the name of an AST to the list of implicit receiver accesses. */
13506
13507
13508  addImplicitReceiverAccess(name) {
13509    if (this.implicitReceiverAccesses) {
13510      this.implicitReceiverAccesses.add(name);
13511    }
13512  }
13513
13514}
13515
13516function flattenStatements(arg, output) {
13517  if (Array.isArray(arg)) {
13518    arg.forEach(entry => flattenStatements(entry, output));
13519  } else {
13520    output.push(arg);
13521  }
13522}
13523
13524function unsupported() {
13525  throw new Error('Unsupported operation');
13526}
13527
13528class InterpolationExpression extends Expression {
13529  constructor(args) {
13530    super(null, null);
13531    this.args = args;
13532    this.isConstant = unsupported;
13533    this.isEquivalent = unsupported;
13534    this.visitExpression = unsupported;
13535  }
13536
13537}
13538
13539class DefaultLocalResolver {
13540  constructor(globals) {
13541    this.globals = globals;
13542  }
13543
13544  notifyImplicitReceiverUse() {}
13545
13546  maybeRestoreView() {}
13547
13548  getLocal(name) {
13549    if (name === EventHandlerVars.event.name) {
13550      return EventHandlerVars.event;
13551    }
13552
13553    return null;
13554  }
13555
13556}
13557
13558class BuiltinFunctionCall extends Call {
13559  constructor(span, sourceSpan, args, converter) {
13560    super(span, sourceSpan, new EmptyExpr(span, sourceSpan), args, null);
13561    this.converter = converter;
13562  }
13563
13564}
13565/**
13566 * @license
13567 * Copyright Google LLC All Rights Reserved.
13568 *
13569 * Use of this source code is governed by an MIT-style license that can be
13570 * found in the LICENSE file at https://angular.io/license
13571 */
13572// =================================================================================================
13573// =================================================================================================
13574// =========== S T O P   -  S T O P   -  S T O P   -  S T O P   -  S T O P   -  S T O P  ===========
13575// =================================================================================================
13576// =================================================================================================
13577//
13578//        DO NOT EDIT THIS LIST OF SECURITY SENSITIVE PROPERTIES WITHOUT A SECURITY REVIEW!
13579//                               Reach out to mprobst for details.
13580//
13581// =================================================================================================
13582
13583/** Map from tagName|propertyName to SecurityContext. Properties applying to all tags use '*'. */
13584
13585
13586let _SECURITY_SCHEMA;
13587
13588function SECURITY_SCHEMA() {
13589  if (!_SECURITY_SCHEMA) {
13590    _SECURITY_SCHEMA = {}; // Case is insignificant below, all element and attribute names are lower-cased for lookup.
13591
13592    registerContext(SecurityContext.HTML, ['iframe|srcdoc', '*|innerHTML', '*|outerHTML']);
13593    registerContext(SecurityContext.STYLE, ['*|style']); // NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them.
13594
13595    registerContext(SecurityContext.URL, ['*|formAction', 'area|href', 'area|ping', 'audio|src', 'a|href', 'a|ping', 'blockquote|cite', 'body|background', 'del|cite', 'form|action', 'img|src', 'input|src', 'ins|cite', 'q|cite', 'source|src', 'track|src', 'video|poster', 'video|src']);
13596    registerContext(SecurityContext.RESOURCE_URL, ['applet|code', 'applet|codebase', 'base|href', 'embed|src', 'frame|src', 'head|profile', 'html|manifest', 'iframe|src', 'link|href', 'media|src', 'object|codebase', 'object|data', 'script|src']);
13597  }
13598
13599  return _SECURITY_SCHEMA;
13600}
13601
13602function registerContext(ctx, specs) {
13603  for (const spec of specs) _SECURITY_SCHEMA[spec.toLowerCase()] = ctx;
13604}
13605/**
13606 * The set of security-sensitive attributes of an `<iframe>` that *must* be
13607 * applied as a static attribute only. This ensures that all security-sensitive
13608 * attributes are taken into account while creating an instance of an `<iframe>`
13609 * at runtime.
13610 *
13611 * Note: avoid using this set directly, use the `isIframeSecuritySensitiveAttr` function
13612 * in the code instead.
13613 */
13614
13615
13616const IFRAME_SECURITY_SENSITIVE_ATTRS = new Set(['sandbox', 'allow', 'allowfullscreen', 'referrerpolicy', 'csp', 'fetchpriority']);
13617/**
13618 * Checks whether a given attribute name might represent a security-sensitive
13619 * attribute of an <iframe>.
13620 */
13621
13622function isIframeSecuritySensitiveAttr(attrName) {
13623  // The `setAttribute` DOM API is case-insensitive, so we lowercase the value
13624  // before checking it against a known security-sensitive attributes.
13625  return IFRAME_SECURITY_SENSITIVE_ATTRS.has(attrName.toLowerCase());
13626}
13627/**
13628 * @license
13629 * Copyright Google LLC All Rights Reserved.
13630 *
13631 * Use of this source code is governed by an MIT-style license that can be
13632 * found in the LICENSE file at https://angular.io/license
13633 */
13634
13635/**
13636 * This file is a port of shadowCSS from webcomponents.js to TypeScript.
13637 *
13638 * Please make sure to keep to edits in sync with the source file.
13639 *
13640 * Source:
13641 * https://github.com/webcomponents/webcomponentsjs/blob/4efecd7e0e/src/ShadowCSS/ShadowCSS.js
13642 *
13643 * The original file level comment is reproduced below
13644 */
13645
13646/*
13647  This is a limited shim for ShadowDOM css styling.
13648  https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#styles
13649
13650  The intention here is to support only the styling features which can be
13651  relatively simply implemented. The goal is to allow users to avoid the
13652  most obvious pitfalls and do so without compromising performance significantly.
13653  For ShadowDOM styling that's not covered here, a set of best practices
13654  can be provided that should allow users to accomplish more complex styling.
13655
13656  The following is a list of specific ShadowDOM styling features and a brief
13657  discussion of the approach used to shim.
13658
13659  Shimmed features:
13660
13661  * :host, :host-context: ShadowDOM allows styling of the shadowRoot's host
13662  element using the :host rule. To shim this feature, the :host styles are
13663  reformatted and prefixed with a given scope name and promoted to a
13664  document level stylesheet.
13665  For example, given a scope name of .foo, a rule like this:
13666
13667    :host {
13668        background: red;
13669      }
13670    }
13671
13672  becomes:
13673
13674    .foo {
13675      background: red;
13676    }
13677
13678  * encapsulation: Styles defined within ShadowDOM, apply only to
13679  dom inside the ShadowDOM. Polymer uses one of two techniques to implement
13680  this feature.
13681
13682  By default, rules are prefixed with the host element tag name
13683  as a descendant selector. This ensures styling does not leak out of the 'top'
13684  of the element's ShadowDOM. For example,
13685
13686  div {
13687      font-weight: bold;
13688    }
13689
13690  becomes:
13691
13692  x-foo div {
13693      font-weight: bold;
13694    }
13695
13696  becomes:
13697
13698
13699  Alternatively, if WebComponents.ShadowCSS.strictStyling is set to true then
13700  selectors are scoped by adding an attribute selector suffix to each
13701  simple selector that contains the host element tag name. Each element
13702  in the element's ShadowDOM template is also given the scope attribute.
13703  Thus, these rules match only elements that have the scope attribute.
13704  For example, given a scope name of x-foo, a rule like this:
13705
13706    div {
13707      font-weight: bold;
13708    }
13709
13710  becomes:
13711
13712    div[x-foo] {
13713      font-weight: bold;
13714    }
13715
13716  Note that elements that are dynamically added to a scope must have the scope
13717  selector added to them manually.
13718
13719  * upper/lower bound encapsulation: Styles which are defined outside a
13720  shadowRoot should not cross the ShadowDOM boundary and should not apply
13721  inside a shadowRoot.
13722
13723  This styling behavior is not emulated. Some possible ways to do this that
13724  were rejected due to complexity and/or performance concerns include: (1) reset
13725  every possible property for every possible selector for a given scope name;
13726  (2) re-implement css in javascript.
13727
13728  As an alternative, users should make sure to use selectors
13729  specific to the scope in which they are working.
13730
13731  * ::distributed: This behavior is not emulated. It's often not necessary
13732  to style the contents of a specific insertion point and instead, descendants
13733  of the host element can be styled selectively. Users can also create an
13734  extra node around an insertion point and style that node's contents
13735  via descendent selectors. For example, with a shadowRoot like this:
13736
13737    <style>
13738      ::content(div) {
13739        background: red;
13740      }
13741    </style>
13742    <content></content>
13743
13744  could become:
13745
13746    <style>
13747      / *@polyfill .content-container div * /
13748      ::content(div) {
13749        background: red;
13750      }
13751    </style>
13752    <div class="content-container">
13753      <content></content>
13754    </div>
13755
13756  Note the use of @polyfill in the comment above a ShadowDOM specific style
13757  declaration. This is a directive to the styling shim to use the selector
13758  in comments in lieu of the next selector when running under polyfill.
13759*/
13760
13761
13762class ShadowCss {
13763  constructor() {
13764    this.strictStyling = true;
13765  }
13766  /*
13767   * Shim some cssText with the given selector. Returns cssText that can
13768   * be included in the document via WebComponents.ShadowCSS.addCssToDocument(css).
13769   *
13770   * When strictStyling is true:
13771   * - selector is the attribute added to all elements inside the host,
13772   * - hostSelector is the attribute added to the host itself.
13773   */
13774
13775
13776  shimCssText(cssText, selector, hostSelector = '') {
13777    const commentsWithHash = extractCommentsWithHash(cssText);
13778    cssText = stripComments(cssText);
13779    cssText = this._insertDirectives(cssText);
13780
13781    const scopedCssText = this._scopeCssText(cssText, selector, hostSelector);
13782
13783    return [scopedCssText, ...commentsWithHash].join('\n');
13784  }
13785
13786  _insertDirectives(cssText) {
13787    cssText = this._insertPolyfillDirectivesInCssText(cssText);
13788    return this._insertPolyfillRulesInCssText(cssText);
13789  }
13790  /*
13791   * Process styles to convert native ShadowDOM rules that will trip
13792   * up the css parser; we rely on decorating the stylesheet with inert rules.
13793   *
13794   * For example, we convert this rule:
13795   *
13796   * polyfill-next-selector { content: ':host menu-item'; }
13797   * ::content menu-item {
13798   *
13799   * to this:
13800   *
13801   * scopeName menu-item {
13802   *
13803   **/
13804
13805
13806  _insertPolyfillDirectivesInCssText(cssText) {
13807    // Difference with webcomponents.js: does not handle comments
13808    return cssText.replace(_cssContentNextSelectorRe, function (...m) {
13809      return m[2] + '{';
13810    });
13811  }
13812  /*
13813   * Process styles to add rules which will only apply under the polyfill
13814   *
13815   * For example, we convert this rule:
13816   *
13817   * polyfill-rule {
13818   *   content: ':host menu-item';
13819   * ...
13820   * }
13821   *
13822   * to this:
13823   *
13824   * scopeName menu-item {...}
13825   *
13826   **/
13827
13828
13829  _insertPolyfillRulesInCssText(cssText) {
13830    // Difference with webcomponents.js: does not handle comments
13831    return cssText.replace(_cssContentRuleRe, (...m) => {
13832      const rule = m[0].replace(m[1], '').replace(m[2], '');
13833      return m[4] + rule;
13834    });
13835  }
13836  /* Ensure styles are scoped. Pseudo-scoping takes a rule like:
13837   *
13838   *  .foo {... }
13839   *
13840   *  and converts this to
13841   *
13842   *  scopeName .foo { ... }
13843   */
13844
13845
13846  _scopeCssText(cssText, scopeSelector, hostSelector) {
13847    const unscopedRules = this._extractUnscopedRulesFromCssText(cssText); // replace :host and :host-context -shadowcsshost and -shadowcsshost respectively
13848
13849
13850    cssText = this._insertPolyfillHostInCssText(cssText);
13851    cssText = this._convertColonHost(cssText);
13852    cssText = this._convertColonHostContext(cssText);
13853    cssText = this._convertShadowDOMSelectors(cssText);
13854
13855    if (scopeSelector) {
13856      cssText = this._scopeSelectors(cssText, scopeSelector, hostSelector);
13857    }
13858
13859    cssText = cssText + '\n' + unscopedRules;
13860    return cssText.trim();
13861  }
13862  /*
13863   * Process styles to add rules which will only apply under the polyfill
13864   * and do not process via CSSOM. (CSSOM is destructive to rules on rare
13865   * occasions, e.g. -webkit-calc on Safari.)
13866   * For example, we convert this rule:
13867   *
13868   * @polyfill-unscoped-rule {
13869   *   content: 'menu-item';
13870   * ... }
13871   *
13872   * to this:
13873   *
13874   * menu-item {...}
13875   *
13876   **/
13877
13878
13879  _extractUnscopedRulesFromCssText(cssText) {
13880    // Difference with webcomponents.js: does not handle comments
13881    let r = '';
13882    let m;
13883    _cssContentUnscopedRuleRe.lastIndex = 0;
13884
13885    while ((m = _cssContentUnscopedRuleRe.exec(cssText)) !== null) {
13886      const rule = m[0].replace(m[2], '').replace(m[1], m[4]);
13887      r += rule + '\n\n';
13888    }
13889
13890    return r;
13891  }
13892  /*
13893   * convert a rule like :host(.foo) > .bar { }
13894   *
13895   * to
13896   *
13897   * .foo<scopeName> > .bar
13898   */
13899
13900
13901  _convertColonHost(cssText) {
13902    return cssText.replace(_cssColonHostRe, (_, hostSelectors, otherSelectors) => {
13903      if (hostSelectors) {
13904        const convertedSelectors = [];
13905        const hostSelectorArray = hostSelectors.split(',').map(p => p.trim());
13906
13907        for (const hostSelector of hostSelectorArray) {
13908          if (!hostSelector) break;
13909          const convertedSelector = _polyfillHostNoCombinator + hostSelector.replace(_polyfillHost, '') + otherSelectors;
13910          convertedSelectors.push(convertedSelector);
13911        }
13912
13913        return convertedSelectors.join(',');
13914      } else {
13915        return _polyfillHostNoCombinator + otherSelectors;
13916      }
13917    });
13918  }
13919  /*
13920   * convert a rule like :host-context(.foo) > .bar { }
13921   *
13922   * to
13923   *
13924   * .foo<scopeName> > .bar, .foo <scopeName> > .bar { }
13925   *
13926   * and
13927   *
13928   * :host-context(.foo:host) .bar { ... }
13929   *
13930   * to
13931   *
13932   * .foo<scopeName> .bar { ... }
13933   */
13934
13935
13936  _convertColonHostContext(cssText) {
13937    return cssText.replace(_cssColonHostContextReGlobal, selectorText => {
13938      // We have captured a selector that contains a `:host-context` rule.
13939      // For backward compatibility `:host-context` may contain a comma separated list of selectors.
13940      // Each context selector group will contain a list of host-context selectors that must match
13941      // an ancestor of the host.
13942      // (Normally `contextSelectorGroups` will only contain a single array of context selectors.)
13943      const contextSelectorGroups = [[]]; // There may be more than `:host-context` in this selector so `selectorText` could look like:
13944      // `:host-context(.one):host-context(.two)`.
13945      // Execute `_cssColonHostContextRe` over and over until we have extracted all the
13946      // `:host-context` selectors from this selector.
13947
13948      let match;
13949
13950      while (match = _cssColonHostContextRe.exec(selectorText)) {
13951        // `match` = [':host-context(<selectors>)<rest>', <selectors>, <rest>]
13952        // The `<selectors>` could actually be a comma separated list: `:host-context(.one, .two)`.
13953        const newContextSelectors = (match[1] ?? '').trim().split(',').map(m => m.trim()).filter(m => m !== ''); // We must duplicate the current selector group for each of these new selectors.
13954        // For example if the current groups are:
13955        // ```
13956        // [
13957        //   ['a', 'b', 'c'],
13958        //   ['x', 'y', 'z'],
13959        // ]
13960        // ```
13961        // And we have a new set of comma separated selectors: `:host-context(m,n)` then the new
13962        // groups are:
13963        // ```
13964        // [
13965        //   ['a', 'b', 'c', 'm'],
13966        //   ['x', 'y', 'z', 'm'],
13967        //   ['a', 'b', 'c', 'n'],
13968        //   ['x', 'y', 'z', 'n'],
13969        // ]
13970        // ```
13971
13972        const contextSelectorGroupsLength = contextSelectorGroups.length;
13973        repeatGroups(contextSelectorGroups, newContextSelectors.length);
13974
13975        for (let i = 0; i < newContextSelectors.length; i++) {
13976          for (let j = 0; j < contextSelectorGroupsLength; j++) {
13977            contextSelectorGroups[j + i * contextSelectorGroupsLength].push(newContextSelectors[i]);
13978          }
13979        } // Update the `selectorText` and see repeat to see if there are more `:host-context`s.
13980
13981
13982        selectorText = match[2];
13983      } // The context selectors now must be combined with each other to capture all the possible
13984      // selectors that `:host-context` can match. See `combineHostContextSelectors()` for more
13985      // info about how this is done.
13986
13987
13988      return contextSelectorGroups.map(contextSelectors => combineHostContextSelectors(contextSelectors, selectorText)).join(', ');
13989    });
13990  }
13991  /*
13992   * Convert combinators like ::shadow and pseudo-elements like ::content
13993   * by replacing with space.
13994   */
13995
13996
13997  _convertShadowDOMSelectors(cssText) {
13998    return _shadowDOMSelectorsRe.reduce((result, pattern) => result.replace(pattern, ' '), cssText);
13999  } // change a selector like 'div' to 'name div'
14000
14001
14002  _scopeSelectors(cssText, scopeSelector, hostSelector) {
14003    return processRules(cssText, rule => {
14004      let selector = rule.selector;
14005      let content = rule.content;
14006
14007      if (rule.selector[0] !== '@') {
14008        selector = this._scopeSelector(rule.selector, scopeSelector, hostSelector, this.strictStyling);
14009      } else if (rule.selector.startsWith('@media') || rule.selector.startsWith('@supports') || rule.selector.startsWith('@document') || rule.selector.startsWith('@layer')) {
14010        content = this._scopeSelectors(rule.content, scopeSelector, hostSelector);
14011      } else if (rule.selector.startsWith('@font-face') || rule.selector.startsWith('@page')) {
14012        content = this._stripScopingSelectors(rule.content);
14013      }
14014
14015      return new CssRule(selector, content);
14016    });
14017  }
14018  /**
14019   * Handle a css text that is within a rule that should not contain scope selectors by simply
14020   * removing them! An example of such a rule is `@font-face`.
14021   *
14022   * `@font-face` rules cannot contain nested selectors. Nor can they be nested under a selector.
14023   * Normally this would be a syntax error by the author of the styles. But in some rare cases, such
14024   * as importing styles from a library, and applying `:host ::ng-deep` to the imported styles, we
14025   * can end up with broken css if the imported styles happen to contain @font-face rules.
14026   *
14027   * For example:
14028   *
14029   * ```
14030   * :host ::ng-deep {
14031   *   import 'some/lib/containing/font-face';
14032   * }
14033   *
14034   * Similar logic applies to `@page` rules which can contain a particular set of properties,
14035   * as well as some specific at-rules. Since they can't be encapsulated, we have to strip
14036   * any scoping selectors from them. For more information: https://www.w3.org/TR/css-page-3
14037   * ```
14038   */
14039
14040
14041  _stripScopingSelectors(cssText) {
14042    return processRules(cssText, rule => {
14043      const selector = rule.selector.replace(_shadowDeepSelectors, ' ').replace(_polyfillHostNoCombinatorRe, ' ');
14044      return new CssRule(selector, rule.content);
14045    });
14046  }
14047
14048  _scopeSelector(selector, scopeSelector, hostSelector, strict) {
14049    return selector.split(',').map(part => part.trim().split(_shadowDeepSelectors)).map(deepParts => {
14050      const [shallowPart, ...otherParts] = deepParts;
14051
14052      const applyScope = shallowPart => {
14053        if (this._selectorNeedsScoping(shallowPart, scopeSelector)) {
14054          return strict ? this._applyStrictSelectorScope(shallowPart, scopeSelector, hostSelector) : this._applySelectorScope(shallowPart, scopeSelector, hostSelector);
14055        } else {
14056          return shallowPart;
14057        }
14058      };
14059
14060      return [applyScope(shallowPart), ...otherParts].join(' ');
14061    }).join(', ');
14062  }
14063
14064  _selectorNeedsScoping(selector, scopeSelector) {
14065    const re = this._makeScopeMatcher(scopeSelector);
14066
14067    return !re.test(selector);
14068  }
14069
14070  _makeScopeMatcher(scopeSelector) {
14071    const lre = /\[/g;
14072    const rre = /\]/g;
14073    scopeSelector = scopeSelector.replace(lre, '\\[').replace(rre, '\\]');
14074    return new RegExp('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
14075  }
14076
14077  _applySelectorScope(selector, scopeSelector, hostSelector) {
14078    // Difference from webcomponents.js: scopeSelector could not be an array
14079    return this._applySimpleSelectorScope(selector, scopeSelector, hostSelector);
14080  } // scope via name and [is=name]
14081
14082
14083  _applySimpleSelectorScope(selector, scopeSelector, hostSelector) {
14084    // In Android browser, the lastIndex is not reset when the regex is used in String.replace()
14085    _polyfillHostRe.lastIndex = 0;
14086
14087    if (_polyfillHostRe.test(selector)) {
14088      const replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector;
14089      return selector.replace(_polyfillHostNoCombinatorRe, (hnc, selector) => {
14090        return selector.replace(/([^:]*)(:*)(.*)/, (_, before, colon, after) => {
14091          return before + replaceBy + colon + after;
14092        });
14093      }).replace(_polyfillHostRe, replaceBy + ' ');
14094    }
14095
14096    return scopeSelector + ' ' + selector;
14097  } // return a selector with [name] suffix on each simple selector
14098  // e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name]  /** @internal */
14099
14100
14101  _applyStrictSelectorScope(selector, scopeSelector, hostSelector) {
14102    const isRe = /\[is=([^\]]*)\]/g;
14103    scopeSelector = scopeSelector.replace(isRe, (_, ...parts) => parts[0]);
14104    const attrName = '[' + scopeSelector + ']';
14105
14106    const _scopeSelectorPart = p => {
14107      let scopedP = p.trim();
14108
14109      if (!scopedP) {
14110        return '';
14111      }
14112
14113      if (p.indexOf(_polyfillHostNoCombinator) > -1) {
14114        scopedP = this._applySimpleSelectorScope(p, scopeSelector, hostSelector);
14115      } else {
14116        // remove :host since it should be unnecessary
14117        const t = p.replace(_polyfillHostRe, '');
14118
14119        if (t.length > 0) {
14120          const matches = t.match(/([^:]*)(:*)(.*)/);
14121
14122          if (matches) {
14123            scopedP = matches[1] + attrName + matches[2] + matches[3];
14124          }
14125        }
14126      }
14127
14128      return scopedP;
14129    };
14130
14131    const safeContent = new SafeSelector(selector);
14132    selector = safeContent.content();
14133    let scopedSelector = '';
14134    let startIndex = 0;
14135    let res;
14136    const sep = /( |>|\+|~(?!=))\s*/g; // If a selector appears before :host it should not be shimmed as it
14137    // matches on ancestor elements and not on elements in the host's shadow
14138    // `:host-context(div)` is transformed to
14139    // `-shadowcsshost-no-combinatordiv, div -shadowcsshost-no-combinator`
14140    // the `div` is not part of the component in the 2nd selectors and should not be scoped.
14141    // Historically `component-tag:host` was matching the component so we also want to preserve
14142    // this behavior to avoid breaking legacy apps (it should not match).
14143    // The behavior should be:
14144    // - `tag:host` -> `tag[h]` (this is to avoid breaking legacy apps, should not match anything)
14145    // - `tag :host` -> `tag [h]` (`tag` is not scoped because it's considered part of a
14146    //   `:host-context(tag)`)
14147
14148    const hasHost = selector.indexOf(_polyfillHostNoCombinator) > -1; // Only scope parts after the first `-shadowcsshost-no-combinator` when it is present
14149
14150    let shouldScope = !hasHost;
14151
14152    while ((res = sep.exec(selector)) !== null) {
14153      const separator = res[1];
14154      const part = selector.slice(startIndex, res.index).trim();
14155      shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
14156      const scopedPart = shouldScope ? _scopeSelectorPart(part) : part;
14157      scopedSelector += `${scopedPart} ${separator} `;
14158      startIndex = sep.lastIndex;
14159    }
14160
14161    const part = selector.substring(startIndex);
14162    shouldScope = shouldScope || part.indexOf(_polyfillHostNoCombinator) > -1;
14163    scopedSelector += shouldScope ? _scopeSelectorPart(part) : part; // replace the placeholders with their original values
14164
14165    return safeContent.restore(scopedSelector);
14166  }
14167
14168  _insertPolyfillHostInCssText(selector) {
14169    return selector.replace(_colonHostContextRe, _polyfillHostContext).replace(_colonHostRe, _polyfillHost);
14170  }
14171
14172}
14173
14174class SafeSelector {
14175  constructor(selector) {
14176    this.placeholders = [];
14177    this.index = 0; // Replaces attribute selectors with placeholders.
14178    // The WS in [attr="va lue"] would otherwise be interpreted as a selector separator.
14179
14180    selector = this._escapeRegexMatches(selector, /(\[[^\]]*\])/g); // CSS allows for certain special characters to be used in selectors if they're escaped.
14181    // E.g. `.foo:blue` won't match a class called `foo:blue`, because the colon denotes a
14182    // pseudo-class, but writing `.foo\:blue` will match, because the colon was escaped.
14183    // Replace all escape sequences (`\` followed by a character) with a placeholder so
14184    // that our handling of pseudo-selectors doesn't mess with them.
14185
14186    selector = this._escapeRegexMatches(selector, /(\\.)/g); // Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
14187    // WS and "+" would otherwise be interpreted as selector separators.
14188
14189    this._content = selector.replace(/(:nth-[-\w]+)(\([^)]+\))/g, (_, pseudo, exp) => {
14190      const replaceBy = `__ph-${this.index}__`;
14191      this.placeholders.push(exp);
14192      this.index++;
14193      return pseudo + replaceBy;
14194    });
14195  }
14196
14197  restore(content) {
14198    return content.replace(/__ph-(\d+)__/g, (_ph, index) => this.placeholders[+index]);
14199  }
14200
14201  content() {
14202    return this._content;
14203  }
14204  /**
14205   * Replaces all of the substrings that match a regex within a
14206   * special string (e.g. `__ph-0__`, `__ph-1__`, etc).
14207   */
14208
14209
14210  _escapeRegexMatches(content, pattern) {
14211    return content.replace(pattern, (_, keep) => {
14212      const replaceBy = `__ph-${this.index}__`;
14213      this.placeholders.push(keep);
14214      this.index++;
14215      return replaceBy;
14216    });
14217  }
14218
14219}
14220
14221const _cssContentNextSelectorRe = /polyfill-next-selector[^}]*content:[\s]*?(['"])(.*?)\1[;\s]*}([^{]*?){/gim;
14222const _cssContentRuleRe = /(polyfill-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
14223const _cssContentUnscopedRuleRe = /(polyfill-unscoped-rule)[^}]*(content:[\s]*(['"])(.*?)\3)[;\s]*[^}]*}/gim;
14224const _polyfillHost = '-shadowcsshost'; // note: :host-context pre-processed to -shadowcsshostcontext.
14225
14226const _polyfillHostContext = '-shadowcsscontext';
14227
14228const _parenSuffix = '(?:\\((' + '(?:\\([^)(]*\\)|[^)(]*)+?' + ')\\))?([^,{]*)';
14229
14230const _cssColonHostRe = new RegExp(_polyfillHost + _parenSuffix, 'gim');
14231
14232const _cssColonHostContextReGlobal = new RegExp(_polyfillHostContext + _parenSuffix, 'gim');
14233
14234const _cssColonHostContextRe = new RegExp(_polyfillHostContext + _parenSuffix, 'im');
14235
14236const _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
14237
14238const _polyfillHostNoCombinatorRe = /-shadowcsshost-no-combinator([^\s]*)/;
14239const _shadowDOMSelectorsRe = [/::shadow/g, /::content/g, // Deprecated selectors
14240/\/shadow-deep\//g, /\/shadow\//g]; // The deep combinator is deprecated in the CSS spec
14241// Support for `>>>`, `deep`, `::ng-deep` is then also deprecated and will be removed in the future.
14242// see https://github.com/angular/angular/pull/17677
14243
14244const _shadowDeepSelectors = /(?:>>>)|(?:\/deep\/)|(?:::ng-deep)/g;
14245const _selectorReSuffix = '([>\\s~+[.,{:][\\s\\S]*)?$';
14246const _polyfillHostRe = /-shadowcsshost/gim;
14247const _colonHostRe = /:host/gim;
14248const _colonHostContextRe = /:host-context/gim;
14249const _commentRe = /\/\*[\s\S]*?\*\//g;
14250
14251function stripComments(input) {
14252  return input.replace(_commentRe, '');
14253}
14254
14255const _commentWithHashRe = /\/\*\s*#\s*source(Mapping)?URL=[\s\S]+?\*\//g;
14256
14257function extractCommentsWithHash(input) {
14258  return input.match(_commentWithHashRe) || [];
14259}
14260
14261const BLOCK_PLACEHOLDER = '%BLOCK%';
14262const QUOTE_PLACEHOLDER = '%QUOTED%';
14263const _ruleRe = /(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g;
14264const _quotedRe = /%QUOTED%/g;
14265const CONTENT_PAIRS = new Map([['{', '}']]);
14266const QUOTE_PAIRS = new Map([[`"`, `"`], [`'`, `'`]]);
14267
14268class CssRule {
14269  constructor(selector, content) {
14270    this.selector = selector;
14271    this.content = content;
14272  }
14273
14274}
14275
14276function processRules(input, ruleCallback) {
14277  const inputWithEscapedQuotes = escapeBlocks(input, QUOTE_PAIRS, QUOTE_PLACEHOLDER);
14278  const inputWithEscapedBlocks = escapeBlocks(inputWithEscapedQuotes.escapedString, CONTENT_PAIRS, BLOCK_PLACEHOLDER);
14279  let nextBlockIndex = 0;
14280  let nextQuoteIndex = 0;
14281  return inputWithEscapedBlocks.escapedString.replace(_ruleRe, (...m) => {
14282    const selector = m[2];
14283    let content = '';
14284    let suffix = m[4];
14285    let contentPrefix = '';
14286
14287    if (suffix && suffix.startsWith('{' + BLOCK_PLACEHOLDER)) {
14288      content = inputWithEscapedBlocks.blocks[nextBlockIndex++];
14289      suffix = suffix.substring(BLOCK_PLACEHOLDER.length + 1);
14290      contentPrefix = '{';
14291    }
14292
14293    const rule = ruleCallback(new CssRule(selector, content));
14294    return `${m[1]}${rule.selector}${m[3]}${contentPrefix}${rule.content}${suffix}`;
14295  }).replace(_quotedRe, () => inputWithEscapedQuotes.blocks[nextQuoteIndex++]);
14296}
14297
14298class StringWithEscapedBlocks {
14299  constructor(escapedString, blocks) {
14300    this.escapedString = escapedString;
14301    this.blocks = blocks;
14302  }
14303
14304}
14305
14306function escapeBlocks(input, charPairs, placeholder) {
14307  const resultParts = [];
14308  const escapedBlocks = [];
14309  let openCharCount = 0;
14310  let nonBlockStartIndex = 0;
14311  let blockStartIndex = -1;
14312  let openChar;
14313  let closeChar;
14314
14315  for (let i = 0; i < input.length; i++) {
14316    const char = input[i];
14317
14318    if (char === '\\') {
14319      i++;
14320    } else if (char === closeChar) {
14321      openCharCount--;
14322
14323      if (openCharCount === 0) {
14324        escapedBlocks.push(input.substring(blockStartIndex, i));
14325        resultParts.push(placeholder);
14326        nonBlockStartIndex = i;
14327        blockStartIndex = -1;
14328        openChar = closeChar = undefined;
14329      }
14330    } else if (char === openChar) {
14331      openCharCount++;
14332    } else if (openCharCount === 0 && charPairs.has(char)) {
14333      openChar = char;
14334      closeChar = charPairs.get(char);
14335      openCharCount = 1;
14336      blockStartIndex = i + 1;
14337      resultParts.push(input.substring(nonBlockStartIndex, blockStartIndex));
14338    }
14339  }
14340
14341  if (blockStartIndex !== -1) {
14342    escapedBlocks.push(input.substring(blockStartIndex));
14343    resultParts.push(placeholder);
14344  } else {
14345    resultParts.push(input.substring(nonBlockStartIndex));
14346  }
14347
14348  return new StringWithEscapedBlocks(resultParts.join(''), escapedBlocks);
14349}
14350/**
14351 * Combine the `contextSelectors` with the `hostMarker` and the `otherSelectors`
14352 * to create a selector that matches the same as `:host-context()`.
14353 *
14354 * Given a single context selector `A` we need to output selectors that match on the host and as an
14355 * ancestor of the host:
14356 *
14357 * ```
14358 * A <hostMarker>, A<hostMarker> {}
14359 * ```
14360 *
14361 * When there is more than one context selector we also have to create combinations of those
14362 * selectors with each other. For example if there are `A` and `B` selectors the output is:
14363 *
14364 * ```
14365 * AB<hostMarker>, AB <hostMarker>, A B<hostMarker>,
14366 * B A<hostMarker>, A B <hostMarker>, B A <hostMarker> {}
14367 * ```
14368 *
14369 * And so on...
14370 *
14371 * @param hostMarker the string that selects the host element.
14372 * @param contextSelectors an array of context selectors that will be combined.
14373 * @param otherSelectors the rest of the selectors that are not context selectors.
14374 */
14375
14376
14377function combineHostContextSelectors(contextSelectors, otherSelectors) {
14378  const hostMarker = _polyfillHostNoCombinator;
14379  _polyfillHostRe.lastIndex = 0; // reset the regex to ensure we get an accurate test
14380
14381  const otherSelectorsHasHost = _polyfillHostRe.test(otherSelectors); // If there are no context selectors then just output a host marker
14382
14383
14384  if (contextSelectors.length === 0) {
14385    return hostMarker + otherSelectors;
14386  }
14387
14388  const combined = [contextSelectors.pop() || ''];
14389
14390  while (contextSelectors.length > 0) {
14391    const length = combined.length;
14392    const contextSelector = contextSelectors.pop();
14393
14394    for (let i = 0; i < length; i++) {
14395      const previousSelectors = combined[i]; // Add the new selector as a descendant of the previous selectors
14396
14397      combined[length * 2 + i] = previousSelectors + ' ' + contextSelector; // Add the new selector as an ancestor of the previous selectors
14398
14399      combined[length + i] = contextSelector + ' ' + previousSelectors; // Add the new selector to act on the same element as the previous selectors
14400
14401      combined[i] = contextSelector + previousSelectors;
14402    }
14403  } // Finally connect the selector to the `hostMarker`s: either acting directly on the host
14404  // (A<hostMarker>) or as an ancestor (A <hostMarker>).
14405
14406
14407  return combined.map(s => otherSelectorsHasHost ? `${s}${otherSelectors}` : `${s}${hostMarker}${otherSelectors}, ${s} ${hostMarker}${otherSelectors}`).join(',');
14408}
14409/**
14410 * Mutate the given `groups` array so that there are `multiples` clones of the original array
14411 * stored.
14412 *
14413 * For example `repeatGroups([a, b], 3)` will result in `[a, b, a, b, a, b]` - but importantly the
14414 * newly added groups will be clones of the original.
14415 *
14416 * @param groups An array of groups of strings that will be repeated. This array is mutated
14417 *     in-place.
14418 * @param multiples The number of times the current groups should appear.
14419 */
14420
14421
14422function repeatGroups(groups, multiples) {
14423  const length = groups.length;
14424
14425  for (let i = 1; i < multiples; i++) {
14426    for (let j = 0; j < length; j++) {
14427      groups[j + i * length] = groups[j].slice(0);
14428    }
14429  }
14430}
14431/**
14432 * @license
14433 * Copyright Google LLC All Rights Reserved.
14434 *
14435 * Use of this source code is governed by an MIT-style license that can be
14436 * found in the LICENSE file at https://angular.io/license
14437 */
14438
14439/**
14440 * Parses string representation of a style and converts it into object literal.
14441 *
14442 * @param value string representation of style as used in the `style` attribute in HTML.
14443 *   Example: `color: red; height: auto`.
14444 * @returns An array of style property name and value pairs, e.g. `['color', 'red', 'height',
14445 * 'auto']`
14446 */
14447
14448
14449function parse(value) {
14450  // we use a string array here instead of a string map
14451  // because a string-map is not guaranteed to retain the
14452  // order of the entries whereas a string array can be
14453  // constructed in a [key, value, key, value] format.
14454  const styles = [];
14455  let i = 0;
14456  let parenDepth = 0;
14457  let quote = 0
14458  /* Char.QuoteNone */
14459  ;
14460  let valueStart = 0;
14461  let propStart = 0;
14462  let currentProp = null;
14463  let valueHasQuotes = false;
14464
14465  while (i < value.length) {
14466    const token = value.charCodeAt(i++);
14467
14468    switch (token) {
14469      case 40
14470      /* Char.OpenParen */
14471      :
14472        parenDepth++;
14473        break;
14474
14475      case 41
14476      /* Char.CloseParen */
14477      :
14478        parenDepth--;
14479        break;
14480
14481      case 39
14482      /* Char.QuoteSingle */
14483      :
14484        // valueStart needs to be there since prop values don't
14485        // have quotes in CSS
14486        valueHasQuotes = valueHasQuotes || valueStart > 0;
14487
14488        if (quote === 0
14489        /* Char.QuoteNone */
14490        ) {
14491          quote = 39
14492          /* Char.QuoteSingle */
14493          ;
14494        } else if (quote === 39
14495        /* Char.QuoteSingle */
14496        && value.charCodeAt(i - 1) !== 92
14497        /* Char.BackSlash */
14498        ) {
14499          quote = 0
14500          /* Char.QuoteNone */
14501          ;
14502        }
14503
14504        break;
14505
14506      case 34
14507      /* Char.QuoteDouble */
14508      :
14509        // same logic as above
14510        valueHasQuotes = valueHasQuotes || valueStart > 0;
14511
14512        if (quote === 0
14513        /* Char.QuoteNone */
14514        ) {
14515          quote = 34
14516          /* Char.QuoteDouble */
14517          ;
14518        } else if (quote === 34
14519        /* Char.QuoteDouble */
14520        && value.charCodeAt(i - 1) !== 92
14521        /* Char.BackSlash */
14522        ) {
14523          quote = 0
14524          /* Char.QuoteNone */
14525          ;
14526        }
14527
14528        break;
14529
14530      case 58
14531      /* Char.Colon */
14532      :
14533        if (!currentProp && parenDepth === 0 && quote === 0
14534        /* Char.QuoteNone */
14535        ) {
14536          currentProp = hyphenate(value.substring(propStart, i - 1).trim());
14537          valueStart = i;
14538        }
14539
14540        break;
14541
14542      case 59
14543      /* Char.Semicolon */
14544      :
14545        if (currentProp && valueStart > 0 && parenDepth === 0 && quote === 0
14546        /* Char.QuoteNone */
14547        ) {
14548          const styleVal = value.substring(valueStart, i - 1).trim();
14549          styles.push(currentProp, valueHasQuotes ? stripUnnecessaryQuotes(styleVal) : styleVal);
14550          propStart = i;
14551          valueStart = 0;
14552          currentProp = null;
14553          valueHasQuotes = false;
14554        }
14555
14556        break;
14557    }
14558  }
14559
14560  if (currentProp && valueStart) {
14561    const styleVal = value.slice(valueStart).trim();
14562    styles.push(currentProp, valueHasQuotes ? stripUnnecessaryQuotes(styleVal) : styleVal);
14563  }
14564
14565  return styles;
14566}
14567
14568function stripUnnecessaryQuotes(value) {
14569  const qS = value.charCodeAt(0);
14570  const qE = value.charCodeAt(value.length - 1);
14571
14572  if (qS == qE && (qS == 39
14573  /* Char.QuoteSingle */
14574  || qS == 34
14575  /* Char.QuoteDouble */
14576  )) {
14577    const tempValue = value.substring(1, value.length - 1); // special case to avoid using a multi-quoted string that was just chomped
14578    // (e.g. `font-family: "Verdana", "sans-serif"`)
14579
14580    if (tempValue.indexOf('\'') == -1 && tempValue.indexOf('"') == -1) {
14581      value = tempValue;
14582    }
14583  }
14584
14585  return value;
14586}
14587
14588function hyphenate(value) {
14589  return value.replace(/[a-z][A-Z]/g, v => {
14590    return v.charAt(0) + '-' + v.charAt(1);
14591  }).toLowerCase();
14592}
14593
14594const IMPORTANT_FLAG = '!important';
14595/**
14596 * Minimum amount of binding slots required in the runtime for style/class bindings.
14597 *
14598 * Styling in Angular uses up two slots in the runtime LView/TData data structures to
14599 * record binding data, property information and metadata.
14600 *
14601 * When a binding is registered it will place the following information in the `LView`:
14602 *
14603 * slot 1) binding value
14604 * slot 2) cached value (all other values collected before it in string form)
14605 *
14606 * When a binding is registered it will place the following information in the `TData`:
14607 *
14608 * slot 1) prop name
14609 * slot 2) binding index that points to the previous style/class binding (and some extra config
14610 * values)
14611 *
14612 * Let's imagine we have a binding that looks like so:
14613 *
14614 * ```
14615 * <div [style.width]="x" [style.height]="y">
14616 * ```
14617 *
14618 * Our `LView` and `TData` data-structures look like so:
14619 *
14620 * ```typescript
14621 * LView = [
14622 *   // ...
14623 *   x, // value of x
14624 *   "width: x",
14625 *
14626 *   y, // value of y
14627 *   "width: x; height: y",
14628 *   // ...
14629 * ];
14630 *
14631 * TData = [
14632 *   // ...
14633 *   "width", // binding slot 20
14634 *   0,
14635 *
14636 *   "height",
14637 *   20,
14638 *   // ...
14639 * ];
14640 * ```
14641 *
14642 * */
14643
14644const MIN_STYLING_BINDING_SLOTS_REQUIRED = 2;
14645/**
14646 * Produces creation/update instructions for all styling bindings (class and style)
14647 *
14648 * It also produces the creation instruction to register all initial styling values
14649 * (which are all the static class="..." and style="..." attribute values that exist
14650 * on an element within a template).
14651 *
14652 * The builder class below handles producing instructions for the following cases:
14653 *
14654 * - Static style/class attributes (style="..." and class="...")
14655 * - Dynamic style/class map bindings ([style]="map" and [class]="map|string")
14656 * - Dynamic style/class property bindings ([style.prop]="exp" and [class.name]="exp")
14657 *
14658 * Due to the complex relationship of all of these cases, the instructions generated
14659 * for these attributes/properties/bindings must be done so in the correct order. The
14660 * order which these must be generated is as follows:
14661 *
14662 * if (createMode) {
14663 *   styling(...)
14664 * }
14665 * if (updateMode) {
14666 *   styleMap(...)
14667 *   classMap(...)
14668 *   styleProp(...)
14669 *   classProp(...)
14670 * }
14671 *
14672 * The creation/update methods within the builder class produce these instructions.
14673 */
14674
14675class StylingBuilder {
14676  constructor(_directiveExpr) {
14677    this._directiveExpr = _directiveExpr;
14678    /** Whether or not there are any static styling values present */
14679
14680    this._hasInitialValues = false;
14681    /**
14682     *  Whether or not there are any styling bindings present
14683     *  (i.e. `[style]`, `[class]`, `[style.prop]` or `[class.name]`)
14684     */
14685
14686    this.hasBindings = false;
14687    this.hasBindingsWithPipes = false;
14688    /** the input for [class] (if it exists) */
14689
14690    this._classMapInput = null;
14691    /** the input for [style] (if it exists) */
14692
14693    this._styleMapInput = null;
14694    /** an array of each [style.prop] input */
14695
14696    this._singleStyleInputs = null;
14697    /** an array of each [class.name] input */
14698
14699    this._singleClassInputs = null;
14700    this._lastStylingInput = null;
14701    this._firstStylingInput = null; // maps are used instead of hash maps because a Map will
14702    // retain the ordering of the keys
14703
14704    /**
14705     * Represents the location of each style binding in the template
14706     * (e.g. `<div [style.width]="w" [style.height]="h">` implies
14707     * that `width=0` and `height=1`)
14708     */
14709
14710    this._stylesIndex = new Map();
14711    /**
14712     * Represents the location of each class binding in the template
14713     * (e.g. `<div [class.big]="b" [class.hidden]="h">` implies
14714     * that `big=0` and `hidden=1`)
14715     */
14716
14717    this._classesIndex = new Map();
14718    this._initialStyleValues = [];
14719    this._initialClassValues = [];
14720  }
14721  /**
14722   * Registers a given input to the styling builder to be later used when producing AOT code.
14723   *
14724   * The code below will only accept the input if it is somehow tied to styling (whether it be
14725   * style/class bindings or static style/class attributes).
14726   */
14727
14728
14729  registerBoundInput(input) {
14730    // [attr.style] or [attr.class] are skipped in the code below,
14731    // they should not be treated as styling-based bindings since
14732    // they are intended to be written directly to the attr and
14733    // will therefore skip all style/class resolution that is present
14734    // with style="", [style]="" and [style.prop]="", class="",
14735    // [class.prop]="". [class]="" assignments
14736    let binding = null;
14737    let name = input.name;
14738
14739    switch (input.type) {
14740      case 0
14741      /* BindingType.Property */
14742      :
14743        binding = this.registerInputBasedOnName(name, input.value, input.sourceSpan);
14744        break;
14745
14746      case 3
14747      /* BindingType.Style */
14748      :
14749        binding = this.registerStyleInput(name, false, input.value, input.sourceSpan, input.unit);
14750        break;
14751
14752      case 2
14753      /* BindingType.Class */
14754      :
14755        binding = this.registerClassInput(name, false, input.value, input.sourceSpan);
14756        break;
14757    }
14758
14759    return binding ? true : false;
14760  }
14761
14762  registerInputBasedOnName(name, expression, sourceSpan) {
14763    let binding = null;
14764    const prefix = name.substring(0, 6);
14765    const isStyle = name === 'style' || prefix === 'style.' || prefix === 'style!';
14766    const isClass = !isStyle && (name === 'class' || prefix === 'class.' || prefix === 'class!');
14767
14768    if (isStyle || isClass) {
14769      const isMapBased = name.charAt(5) !== '.'; // style.prop or class.prop makes this a no
14770
14771      const property = name.slice(isMapBased ? 5 : 6); // the dot explains why there's a +1
14772
14773      if (isStyle) {
14774        binding = this.registerStyleInput(property, isMapBased, expression, sourceSpan);
14775      } else {
14776        binding = this.registerClassInput(property, isMapBased, expression, sourceSpan);
14777      }
14778    }
14779
14780    return binding;
14781  }
14782
14783  registerStyleInput(name, isMapBased, value, sourceSpan, suffix) {
14784    if (isEmptyExpression(value)) {
14785      return null;
14786    } // CSS custom properties are case-sensitive so we shouldn't normalize them.
14787    // See: https://www.w3.org/TR/css-variables-1/#defining-variables
14788
14789
14790    if (!isCssCustomProperty(name)) {
14791      name = hyphenate(name);
14792    }
14793
14794    const {
14795      property,
14796      hasOverrideFlag,
14797      suffix: bindingSuffix
14798    } = parseProperty(name);
14799    suffix = typeof suffix === 'string' && suffix.length !== 0 ? suffix : bindingSuffix;
14800    const entry = {
14801      name: property,
14802      suffix: suffix,
14803      value,
14804      sourceSpan,
14805      hasOverrideFlag
14806    };
14807
14808    if (isMapBased) {
14809      this._styleMapInput = entry;
14810    } else {
14811      (this._singleStyleInputs = this._singleStyleInputs || []).push(entry);
14812      registerIntoMap(this._stylesIndex, property);
14813    }
14814
14815    this._lastStylingInput = entry;
14816    this._firstStylingInput = this._firstStylingInput || entry;
14817
14818    this._checkForPipes(value);
14819
14820    this.hasBindings = true;
14821    return entry;
14822  }
14823
14824  registerClassInput(name, isMapBased, value, sourceSpan) {
14825    if (isEmptyExpression(value)) {
14826      return null;
14827    }
14828
14829    const {
14830      property,
14831      hasOverrideFlag
14832    } = parseProperty(name);
14833    const entry = {
14834      name: property,
14835      value,
14836      sourceSpan,
14837      hasOverrideFlag,
14838      suffix: null
14839    };
14840
14841    if (isMapBased) {
14842      this._classMapInput = entry;
14843    } else {
14844      (this._singleClassInputs = this._singleClassInputs || []).push(entry);
14845      registerIntoMap(this._classesIndex, property);
14846    }
14847
14848    this._lastStylingInput = entry;
14849    this._firstStylingInput = this._firstStylingInput || entry;
14850
14851    this._checkForPipes(value);
14852
14853    this.hasBindings = true;
14854    return entry;
14855  }
14856
14857  _checkForPipes(value) {
14858    if (value instanceof ASTWithSource && value.ast instanceof BindingPipe) {
14859      this.hasBindingsWithPipes = true;
14860    }
14861  }
14862  /**
14863   * Registers the element's static style string value to the builder.
14864   *
14865   * @param value the style string (e.g. `width:100px; height:200px;`)
14866   */
14867
14868
14869  registerStyleAttr(value) {
14870    this._initialStyleValues = parse(value);
14871    this._hasInitialValues = true;
14872  }
14873  /**
14874   * Registers the element's static class string value to the builder.
14875   *
14876   * @param value the className string (e.g. `disabled gold zoom`)
14877   */
14878
14879
14880  registerClassAttr(value) {
14881    this._initialClassValues = value.trim().split(/\s+/g);
14882    this._hasInitialValues = true;
14883  }
14884  /**
14885   * Appends all styling-related expressions to the provided attrs array.
14886   *
14887   * @param attrs an existing array where each of the styling expressions
14888   * will be inserted into.
14889   */
14890
14891
14892  populateInitialStylingAttrs(attrs) {
14893    // [CLASS_MARKER, 'foo', 'bar', 'baz' ...]
14894    if (this._initialClassValues.length) {
14895      attrs.push(literal(1
14896      /* AttributeMarker.Classes */
14897      ));
14898
14899      for (let i = 0; i < this._initialClassValues.length; i++) {
14900        attrs.push(literal(this._initialClassValues[i]));
14901      }
14902    } // [STYLE_MARKER, 'width', '200px', 'height', '100px', ...]
14903
14904
14905    if (this._initialStyleValues.length) {
14906      attrs.push(literal(2
14907      /* AttributeMarker.Styles */
14908      ));
14909
14910      for (let i = 0; i < this._initialStyleValues.length; i += 2) {
14911        attrs.push(literal(this._initialStyleValues[i]), literal(this._initialStyleValues[i + 1])
14911);
14912      }
14913    }
14914  }
14915  /**
14916   * Builds an instruction with all the expressions and parameters for `elementHostAttrs`.
14917   *
14918   * The instruction generation code below is used for producing the AOT statement code which is
14919   * responsible for registering initial styles (within a directive hostBindings' creation block),
14920   * as well as any of the provided attribute values, to the directive host element.
14921   */
14922
14923
14924  assignHostAttrs(attrs, definitionMap) {
14925    if (this._directiveExpr && (attrs.length || this._hasInitialValues)) {
14926      this.populateInitialStylingAttrs(attrs);
14927      definitionMap.set('hostAttrs', literalArr(attrs));
14928    }
14929  }
14930  /**
14931   * Builds an instruction with all the expressions and parameters for `classMap`.
14932   *
14933   * The instruction data will contain all expressions for `classMap` to function
14934   * which includes the `[class]` expression params.
14935   */
14936
14937
14938  buildClassMapInstruction(valueConverter) {
14939    if (this._classMapInput) {
14940      return this._buildMapBasedInstruction(valueConverter, true, this._classMapInput);
14941    }
14942
14943    return null;
14944  }
14945  /**
14946   * Builds an instruction with all the expressions and parameters for `styleMap`.
14947   *
14948   * The instruction data will contain all expressions for `styleMap` to function
14949   * which includes the `[style]` expression params.
14950   */
14951
14952
14953  buildStyleMapInstruction(valueConverter) {
14954    if (this._styleMapInput) {
14955      return this._buildMapBasedInstruction(valueConverter, false, this._styleMapInput);
14956    }
14957
14958    return null;
14959  }
14960
14961  _buildMapBasedInstruction(valueConverter, isClassBased, stylingInput) {
14962    // each styling binding value is stored in the LView
14963    // map-based bindings allocate two slots: one for the
14964    // previous binding value and another for the previous
14965    // className or style attribute value.
14966    let totalBindingSlotsRequired = MIN_STYLING_BINDING_SLOTS_REQUIRED; // these values must be outside of the update block so that they can
14967    // be evaluated (the AST visit call) during creation time so that any
14968    // pipes can be picked up in time before the template is built
14969
14970    const mapValue = stylingInput.value.visit(valueConverter);
14971    let reference;
14972
14973    if (mapValue instanceof Interpolation) {
14974      totalBindingSlotsRequired += mapValue.expressions.length;
14975      reference = isClassBased ? getClassMapInterpolationExpression(mapValue) : getStyleMapInterpolationExpression(mapValue);
14976    } else {
14977      reference = isClassBased ? Identifiers.classMap : Identifiers.styleMap;
14978    }
14979
14980    return {
14981      reference,
14982      calls: [{
14983        supportsInterpolation: true,
14984        sourceSpan: stylingInput.sourceSpan,
14985        allocateBindingSlots: totalBindingSlotsRequired,
14986        params: convertFn => {
14987          const convertResult = convertFn(mapValue);
14988          const params = Array.isArray(convertResult) ? convertResult : [convertResult];
14989          return params;
14990        }
14991      }]
14992    };
14993  }
14994
14995  _buildSingleInputs(reference, inputs, valueConverter, getInterpolationExpressionFn, isClassBased) {
14996    const instructions = [];
14997    inputs.forEach(input => {
14998      const previousInstruction = instructions[instructions.length - 1];
14999      const value = input.value.visit(valueConverter);
15000      let referenceForCall = reference; // each styling binding value is stored in the LView
15001      // but there are two values stored for each binding:
15002      //   1) the value itself
15003      //   2) an intermediate value (concatenation of style up to this point).
15004      //      We need to store the intermediate value so that we don't allocate
15005      //      the strings on each CD.
15006
15007      let totalBindingSlotsRequired = MIN_STYLING_BINDING_SLOTS_REQUIRED;
15008
15009      if (value instanceof Interpolation) {
15010        totalBindingSlotsRequired += value.expressions.length;
15011
15012        if (getInterpolationExpressionFn) {
15013          referenceForCall = getInterpolationExpressionFn(value);
15014        }
15015      }
15016
15017      const call = {
15018        sourceSpan: input.sourceSpan,
15019        allocateBindingSlots: totalBindingSlotsRequired,
15020        supportsInterpolation: !!getInterpolationExpressionFn,
15021        params: convertFn => {
15022          // params =>
15022 stylingProp(propName, value, suffix)
15023          const params = [];
15024          params.push(literal(input.name));
15025          const convertResult = convertFn(value);
15026
15027          if (Array.isArray(convertResult)) {
15028            params.push(...convertResult);
15029          } else {
15030            params.push(convertResult);
15031          } // [style.prop] bindings may use suffix values (e.g. px, em, etc...), therefore,
15032          // if that is detected then we need to pass that in as an optional param.
15033
15034
15035          if (!isClassBased && input.suffix !== null) {
15036            params.push(literal(input.suffix));
15037          }
15038
15039          return params;
15040        }
15041      }; // If we ended up generating a call to the same instruction as the previous styling property
15042      // we can chain the calls together safely to save some bytes, otherwise we have to generate
15043      // a separate instruction call. This is primarily a concern with interpolation instructions
15044      // where we may start off with one `reference`, but end up using another based on the
15045      // number of interpolations.
15046
15047      if (previousInstruction && previousInstruction.reference === referenceForCall) {
15048        previousInstruction.calls.push(call);
15049      } else {
15050        instructions.push({
15051          reference: referenceForCall,
15052          calls: [call]
15053        });
15054      }
15055    });
15056    return instructions;
15057  }
15058
15059  _buildClassInputs(valueConverter) {
15060    if (this._singleClassInputs) {
15061      return this._buildSingleInputs(Identifiers.classProp, this._singleClassInputs, valueConverter, null, true);
15062    }
15063
15064    return [];
15065  }
15066
15067  _buildStyleInputs(valueConverter) {
15068    if (this._singleStyleInputs) {
15069      return this._buildSingleInputs(Identifiers.styleProp, this._singleStyleInputs, valueConverter, getStylePropInterpolationExpression, false);
15070    }
15071
15072    return [];
15073  }
15074  /**
15075   * Constructs all instructions which contain the expressions that will be placed
15076   * into the update block of a template function or a directive hostBindings function.
15077   */
15078
15079
15080  buildUpdateLevelInstructions(valueConverter) {
15081    const instructions = [];
15082
15083    if (this.hasBindings) {
15084      const styleMapInstruction = this.buildStyleMapInstruction(valueConverter);
15085
15086      if (styleMapInstruction) {
15087        instructions.push(styleMapInstruction);
15088      }
15089
15090      const classMapInstruction = this.buildClassMapInstruction(valueConverter);
15091
15092      if (classMapInstruction) {
15093        instructions.push(classMapInstruction);
15094      }
15095
15096      instructions.push(...this._buildStyleInputs(valueConverter));
15097      instructions.push(...this._buildClassInputs(valueConverter));
15098    }
15099
15100    return instructions;
15101  }
15102
15103}
15104
15105function registerIntoMap(map, key) {
15106  if (!map.has(key)) {
15107    map.set(key, map.size);
15108  }
15109}
15110
15111function parseProperty(name) {
15112  let hasOverrideFlag = false;
15113  const overrideIndex = name.indexOf(IMPORTANT_FLAG);
15114
15115  if (overrideIndex !== -1) {
15116    name = overrideIndex > 0 ? name.substring(0, overrideIndex) : '';
15117    hasOverrideFlag = true;
15118  }
15119
15120  let suffix = null;
15121  let property = name;
15122  const unitIndex = name.lastIndexOf('.');
15123
15124  if (unitIndex > 0) {
15125    suffix = name.slice(unitIndex + 1);
15126    property = name.substring(0, unitIndex);
15127  }
15128
15129  return {
15130    property,
15131    suffix,
15132    hasOverrideFlag
15133  };
15134}
15135/**
15136 * Gets the instruction to generate for an interpolated class map.
15137 * @param interpolation An Interpolation AST
15138 */
15139
15140
15141function getClassMapInterpolationExpression(interpolation) {
15142  switch (getInterpolationArgsLength(interpolation)) {
15143    case 1:
15144      return Identifiers.classMap;
15145
15146    case 3:
15147      return Identifiers.classMapInterpolate1;
15148
15149    case 5:
15150      return Identifiers.classMapInterpolate2;
15151
15152    case 7:
15153      return Identifiers.classMapInterpolate3;
15154
15155    case 9:
15156      return Identifiers.classMapInterpolate4;
15157
15158    case 11:
15159      return Identifiers.classMapInterpolate5;
15160
15161    case 13:
15162      return Identifiers.classMapInterpolate6;
15163
15164    case 15:
15165      return Identifiers.classMapInterpolate7;
15166
15167    case 17:
15168      return Identifiers.classMapInterpolate8;
15169
15170    default:
15171      return Identifiers.classMapInterpolateV;
15172  }
15173}
15174/**
15175 * Gets the instruction to generate for an interpolated style map.
15176 * @param interpolation An Interpolation AST
15177 */
15178
15179
15180function getStyleMapInterpolationExpression(interpolation) {
15181  switch (getInterpolationArgsLength(interpolation)) {
15182    case 1:
15183      return Identifiers.styleMap;
15184
15185    case 3:
15186      return Identifiers.styleMapInterpolate1;
15187
15188    case 5:
15189      return Identifiers.styleMapInterpolate2;
15190
15191    case 7:
15192      return Identifiers.styleMapInterpolate3;
15193
15194    case 9:
15195      return Identifiers.styleMapInterpolate4;
15196
15197    case 11:
15198      return Identifiers.styleMapInterpolate5;
15199
15200    case 13:
15201      return Identifiers.styleMapInterpolate6;
15202
15203    case 15:
15204      return Identifiers.styleMapInterpolate7;
15205
15206    case 17:
15207      return Identifiers.styleMapInterpolate8;
15208
15209    default:
15210      return Identifiers.styleMapInterpolateV;
15211  }
15212}
15213/**
15214 * Gets the instruction to generate for an interpolated style prop.
15215 * @param interpolation An Interpolation AST
15216 */
15217
15218
15219function getStylePropInterpolationExpression(interpolation) {
15220  switch (getInterpolationArgsLength(interpolation)) {
15221    case 1:
15222      return Identifiers.styleProp;
15223
15224    case 3:
15225      return Identifiers.stylePropInterpolate1;
15226
15227    case 5:
15228      return Identifiers.stylePropInterpolate2;
15229
15230    case 7:
15231      return Identifiers.stylePropInterpolate3;
15232
15233    case 9:
15234      return Identifiers.stylePropInterpolate4;
15235
15236    case 11:
15237      return Identifiers.stylePropInterpolate5;
15238
15239    case 13:
15240      return Identifiers.stylePropInterpolate6;
15241
15242    case 15:
15243      return Identifiers.stylePropInterpolate7;
15244
15245    case 17:
15246      return Identifiers.stylePropInterpolate8;
15247
15248    default:
15249      return Identifiers.stylePropInterpolateV;
15250  }
15251}
15252/**
15253 * Checks whether property name is a custom CSS property.
15254 * See: https://www.w3.org/TR/css-variables-1
15255 */
15256
15257
15258function isCssCustomProperty(name) {
15259  return name.startsWith('--');
15260}
15261
15262function isEmptyExpression(ast) {
15263  if (ast instanceof ASTWithSource) {
15264    ast = ast.ast;
15265  }
15266
15267  return ast instanceof EmptyExpr;
15268}
15269/**
15270 * @license
15271 * Copyright Google LLC All Rights Reserved.
15272 *
15273 * Use of this source code is governed by an MIT-style license that can be
15274 * found in the LICENSE file at https://angular.io/license
15275 */
15276
15277
15278var TokenType;
15279
15280(function (TokenType) {
15281  TokenType[TokenType["Character"] = 0] = "Character";
15282  TokenType[TokenType["Identifier"] = 1] = "Identifier";
15283  TokenType[TokenType["PrivateIdentifier"] = 2] = "PrivateIdentifier";
15284  TokenType[TokenType["Keyword"] = 3] = "Keyword";
15285  TokenType[TokenType["String"] = 4] = "String";
15286  TokenType[TokenType["Operator"] = 5] = "Operator";
15287  TokenType[TokenType["Number"] = 6] = "Number";
15288  TokenType[TokenType["Error"] = 7] = "Error";
15289})(TokenType || (TokenType = {}));
15290
15291const KEYWORDS = ['var', 'let', 'as', 'null', 'undefined', 'true', 'false', 'if', 'else', 'this'];
15292
15293class Lexer {
15294  tokenize(text) {
15295    const scanner = new _Scanner(text);
15296    const tokens = [];
15297    let token = scanner.scanToken();
15298
15299    while (token != null) {
15300      tokens.push(token);
15301      token = scanner.scanToken();
15302    }
15303
15304    return tokens;
15305  }
15306
15307}
15308
15309class Token {
15310  constructor(index, end, type, numValue, strValue) {
15311    this.index = index;
15312    this.end = end;
15313    this.type = type;
15314    this.numValue = numValue;
15315    this.strValue = strValue;
15316  }
15317
15318  isCharacter(code) {
15319    return this.type == TokenType.Character && this.numValue == code;
15320  }
15321
15322  isNumber() {
15323    return this.type == TokenType.Number;
15324  }
15325
15326  isString() {
15327    return this.type == TokenType.String;
15328  }
15329
15330  isOperator(operator) {
15331    return this.type == TokenType.Operator && this.strValue == operator;
15332  }
15333
15334  isIdentifier() {
15335    return this.type == TokenType.Identifier;
15336  }
15337
15338  isPrivateIdentifier() {
15339    return this.type == TokenType.PrivateIdentifier;
15340  }
15341
15342  isKeyword() {
15343    return this.type == TokenType.Keyword;
15344  }
15345
15346  isKeywordLet() {
15347    return this.type == TokenType.Keyword && this.strValue == 'let';
15348  }
15349
15350  isKeywordAs() {
15351    return this.type == TokenType.Keyword && this.strValue == 'as';
15352  }
15353
15354  isKeywordNull() {
15355    return this.type == TokenType.Keyword && this.strValue == 'null';
15356  }
15357
15358  isKeywordUndefined() {
15359    return this.type == TokenType.Keyword && this.strValue == 'undefined';
15360  }
15361
15362  isKeywordTrue() {
15363    return this.type == TokenType.Keyword && this.strValue == 'true';
15364  }
15365
15366  isKeywordFalse() {
15367    return this.type == TokenType.Keyword && this.strValue == 'false';
15368  }
15369
15370  isKeywordThis() {
15371    return this.type == TokenType.Keyword && this.strValue == 'this';
15372  }
15373
15374  isError() {
15375    return this.type == TokenType.Error;
15376  }
15377
15378  toNumber() {
15379    return this.type == TokenType.Number ? this.numValue : -1;
15380  }
15381
15382  toString() {
15383    switch (this.type) {
15384      case TokenType.Character:
15385      case TokenType.Identifier:
15386      case TokenType.Keyword:
15387      case TokenType.Operator:
15388      case TokenType.PrivateIdentifier:
15389      case TokenType.String:
15390      case TokenType.Error:
15391        return this.strValue;
15392
15393      case TokenType.Number:
15394        return this.numValue.toString();
15395
15396      default:
15397        return null;
15398    }
15399  }
15400
15401}
15402
15403function newCharacterToken(index, end, code) {
15404  return new Token(index, end, TokenType.Character, code, String.fromCharCode(code));
15405}
15406
15407function newIdentifierToken(index, end, text) {
15408  return new Token(index, end, TokenType.Identifier, 0, text);
15409}
15410
15411function newPrivateIdentifierToken(index, end, text) {
15412  return new Token(index, end, TokenType.PrivateIdentifier, 0, text);
15413}
15414
15415function newKeywordToken(index, end, text) {
15416  return new Token(index, end, TokenType.Keyword, 0, text);
15417}
15418
15419function newOperatorToken(index, end, text) {
15420  return new Token(index, end, TokenType.Operator, 0, text);
15421}
15422
15423function newStringToken(index, end, text) {
15424  return new Token(index, end, TokenType.String, 0, text);
15425}
15426
15427function newNumberToken(index, end, n) {
15428  return new Token(index, end, TokenType.Number, n, '');
15429}
15430
15431function newErrorToken(index, end, message) {
15432  return new Token(index, end, TokenType.Error, 0, message);
15433}
15434
15435const EOF = new Token(-1, -1, TokenType.Character, 0, '');
15436
15437class _Scanner {
15438  constructor(input) {
15439    this.input = input;
15440    this.peek = 0;
15441    this.index = -1;
15442    this.length = input.length;
15443    this.advance();
15444  }
15445
15446  advance() {
15447    this.peek = ++this.index >= this.length ? $EOF : this.input.charCodeAt(this.index);
15448  }
15449
15450  scanToken() {
15451    const input = this.input,
15452          length = this.length;
15453    let peek = this.peek,
15454        index = this.index; // Skip whitespace.
15455
15456    while (peek <= $SPACE) {
15457      if (++index >= length) {
15458        peek = $EOF;
15459        break;
15460      } else {
15461        peek = input.charCodeAt(index);
15462      }
15463    }
15464
15465    this.peek = peek;
15466    this.index = index;
15467
15468    if (index >= length) {
15469      return null;
15470    } // Handle identifiers and numbers.
15471
15472
15473    if (isIdentifierStart(peek)) return this.scanIdentifier();
15474    if (isDigit(peek)) return this.scanNumber(index);
15475    const start = index;
15476
15477    switch (peek) {
15478      case $PERIOD:
15479        this.advance();
15480        return isDigit(this.peek) ? this.scanNumber(start) : newCharacterToken(start, this.index, $PERIOD);
15481
15482      case $LPAREN:
15483      case $RPAREN:
15484      case $LBRACE:
15485      case $RBRACE:
15486      case $LBRACKET:
15487      case $RBRACKET:
15488      case $COMMA:
15489      case $COLON:
15490      case $SEMICOLON:
15491        return this.scanCharacter(start, peek);
15492
15493      case $SQ:
15494      case $DQ:
15495        return this.scanString();
15496
15497      case $HASH:
15498        return this.scanPrivateIdentifier();
15499
15500      case $PLUS:
15501      case $MINUS:
15502      case $STAR:
15503      case $SLASH:
15504      case $PERCENT:
15505      case $CARET:
15506        return this.scanOperator(start, String.fromCharCode(peek));
15507
15508      case $QUESTION:
15509        return this.scanQuestion(start);
15510
15511      case $LT:
15512      case $GT:
15513        return this.scanComplexOperator(start, String.fromCharCode(peek), $EQ, '=');
15514
15515      case $BANG:
15516      case $EQ:
15517        return this.scanComplexOperator(start, String.fromCharCode(peek), $EQ, '=', $EQ, '=');
15518
15519      case $AMPERSAND:
15520        return this.scanComplexOperator(start, '&', $AMPERSAND, '&');
15521
15522      case $BAR:
15523        return this.scanComplexOperator(start, '|', $BAR, '|');
15524
15525      case $NBSP:
15526        while (isWhitespace(this.peek)) this.advance();
15527
15528        return this.scanToken();
15529    }
15530
15531    this.advance();
15532    return this.error(`Unexpected character [${String.fromCharCode(peek)}]`, 0);
15533  }
15534
15535  scanCharacter(start, code) {
15536    this.advance();
15537    return newCharacterToken(start, this.index, code);
15538  }
15539
15540  scanOperator(start, str) {
15541    this.advance();
15542    return newOperatorToken(start, this.index, str);
15543  }
15544  /**
15545   * Tokenize a 2/3 char long operator
15546   *
15547   * @param start start index in the expression
15548   * @param one first symbol (always part of the operator)
15549   * @param twoCode code point for the second symbol
15550   * @param two second symbol (part of the operator when the second code point matches)
15551   * @param threeCode code point for the third symbol
15552   * @param three third symbol (part of the operator when provided and matches source expression)
15553   */
15554
15555
15556  scanComplexOperator(start, one, twoCode, two, threeCode, three) {
15557    this.advance();
15558    let str = one;
15559
15560    if (this.peek == twoCode) {
15561      this.advance();
15562      str += two;
15563    }
15564
15565    if (threeCode != null && this.peek == threeCode) {
15566      this.advance();
15567      str += three;
15568    }
15569
15570    return newOperatorToken(start, this.index, str);
15571  }
15572
15573  scanIdentifier() {
15574    const start = this.index;
15575    this.advance();
15576
15577    while (isIdentifierPart(this.peek)) this.advance();
15578
15579    const str = this.input.substring(start, this.index);
15580    return KEYWORDS.indexOf(str) > -1 ? newKeywordToken(start, this.index, str) : newIdentifierToken(start, this.index, str);
15581  }
15582  /** Scans an ECMAScript private identifier. */
15583
15584
15585  scanPrivateIdentifier() {
15586    const start = this.index;
15587    this.advance();
15588
15589    if (!isIdentifierStart(this.peek)) {
15590      return this.error('Invalid character [#]', -1);
15591    }
15592
15593    while (isIdentifierPart(this.peek)) this.advance();
15594
15595    const identifierName = this.input.substring(start, this.index);
15596    return newPrivateIdentifierToken(start, this.index, identifierName);
15597  }
15598
15599  scanNumber(start) {
15600    let simple = this.index === start;
15601    let hasSeparators = false;
15602    this.advance(); // Skip initial digit.
15603
15604    while (true) {
15605      if (isDigit(this.peek)) {// Do nothing.
15606      } else if (this.peek === $_) {
15607        // Separators are only valid when they're surrounded by digits. E.g. `1_0_1` is
15608        // valid while `_101` and `101_` are not. The separator can't be next to the decimal
15609        // point or another separator either. Note that it's unlikely that we'll hit a case where
15610        // the underscore is at the start, because that's a valid identifier and it will be picked
15611        // up earlier in the parsing. We validate for it anyway just in case.
15612        if (!isDigit(this.input.charCodeAt(this.index - 1)) || !isDigit(this.input.charCodeAt(this.index + 1))) {
15613          return this.error('Invalid numeric separator', 0);
15614        }
15615
15616        hasSeparators = true;
15617      } else if (this.peek === $PERIOD) {
15618        simple = false;
15619      } else if (isExponentStart(this.peek)) {
15620        this.advance();
15621        if (isExponentSign(this.peek)) this.advance();
15622        if (!isDigit(this.peek)) return this.error('Invalid exponent', -1);
15623        simple = false;
15624      } else {
15625        break;
15626      }
15627
15628      this.advance();
15629    }
15630
15631    let str = this.input.substring(start, this.index);
15632
15633    if (hasSeparators) {
15634      str = str.replace(/_/g, '');
15635    }
15636
15637    const value = simple ? parseIntAutoRadix(str) : parseFloat(str);
15638    return newNumberToken(start, this.index, value);
15639  }
15640
15641  scanString() {
15642    const start = this.index;
15643    const quote = this.peek;
15644    this.advance(); // Skip initial quote.
15645
15646    let buffer = '';
15647    let marker = this.index;
15648    const input = this.input;
15649
15650    while (this.peek != quote) {
15651      if (this.peek == $BACKSLASH) {
15652        buffer += input.substring(marker, this.index);
15653        this.advance();
15654        let unescapedCode; // Workaround for TS2.1-introduced type strictness
15655
15656        this.peek = this.peek;
15657
15658        if (this.peek == $u) {
15659          // 4 character hex code for unicode character.
15660          const hex = input.substring(this.index + 1, this.index + 5);
15661
15662          if (/^[0-9a-f]+$/i.test(hex)) {
15663            unescapedCode = parseInt(hex, 16);
15664          } else {
15665            return this.error(`Invalid unicode escape [\\u${hex}]`, 0);
15666          }
15667
15668          for (let i = 0; i < 5; i++) {
15669            this.advance();
15670          }
15671        } else {
15672          unescapedCode = unescape(this.peek);
15673          this.advance();
15674        }
15675
15676        buffer += String.fromCharCode(unescapedCode);
15677        marker = this.index;
15678      } else if (this.peek == $EOF) {
15679        return this.error('Unterminated quote', 0);
15680      } else {
15681        this.advance();
15682      }
15683    }
15684
15685    const last = input.substring(marker, this.index);
15686    this.advance(); // Skip terminating quote.
15687
15688    return newStringToken(start, this.index, buffer + last);
15689  }
15690
15691  scanQuestion(start) {
15692    this.advance();
15693    let str = '?'; // Either `a ?? b` or 'a?.b'.
15694
15695    if (this.peek === $QUESTION || this.peek === $PERIOD) {
15696      str += this.peek === $PERIOD ? '.' : '?';
15697      this.advance();
15698    }
15699
15700    return newOperatorToken(start, this.index, str);
15701  }
15702
15703  error(message, offset) {
15704    const position = this.index + offset;
15705    return newErrorToken(position, this.index, `Lexer Error: ${message} at column ${position} in expression [${this.input}]`);
15706  }
15707
15708}
15709
15710function isIdentifierStart(code) {
15711  return $a <= code && code <= $z || $A <= code && code <= $Z || code == $_ || code == $$;
15712}
15713
15714function isIdentifier(input) {
15715  if (input.length == 0) return false;
15716  const scanner = new _Scanner(input);
15717  if (!isIdentifierStart(scanner.peek)) return false;
15718  scanner.advance();
15719
15720  while (scanner.peek !== $EOF) {
15721    if (!isIdentifierPart(scanner.peek)) return false;
15722    scanner.advance();
15723  }
15724
15725  return true;
15726}
15727
15728function isIdentifierPart(code) {
15729  return isAsciiLetter(code) || isDigit(code) || code == $_ || code == $$;
15730}
15731
15732function isExponentStart(code) {
15733  return code == $e || code == $E;
15734}
15735
15736function isExponentSign(code) {
15737  return code == $MINUS || code == $PLUS;
15738}
15739
15740function unescape(code) {
15741  switch (code) {
15742    case $n:
15743      return $LF;
15744
15745    case $f:
15746      return $FF;
15747
15748    case $r:
15749      return $CR;
15750
15751    case $t:
15752      return $TAB;
15753
15754    case $v:
15755      return $VTAB;
15756
15757    default:
15758      return code;
15759  }
15760}
15761
15762function parseIntAutoRadix(text) {
15763  const result = parseInt(text);
15764
15765  if (isNaN(result)) {
15766    throw new Error('Invalid integer literal when parsing ' + text);
15767  }
15768
15769  return result;
15770}
15771/**
15772 * @license
15773 * Copyright Google LLC All Rights Reserved.
15774 *
15775 * Use of this source code is governed by an MIT-style license that can be
15776 * found in the LICENSE file at https://angular.io/license
15777 */
15778
15779
15780class SplitInterpolation {
15781  constructor(strings, expressions, offsets) {
15782    this.strings = strings;
15783    this.expressions = expressions;
15784    this.offsets = offsets;
15785  }
15786
15787}
15788
15789class TemplateBindingParseResult {
15790  constructor(templateBindings, warnings, errors) {
15791    this.templateBindings = templateBindings;
15792    this.warnings = warnings;
15793    this.errors = errors;
15794  }
15795
15796}
15797
15798class Parser$1 {
15799  constructor(_lexer) {
15800    this._lexer = _lexer;
15801    this.errors = [];
15802  }
15803
15804  parseAction(input, isAssignmentEvent, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
15805    this._checkNoInterpolation(input, location, interpolationConfig);
15806
15807    const sourceToLex = this._stripComments(input);
15808
15809    const tokens = this._lexer.tokenize(sourceToLex);
15810
15811    let flags = 1
15812    /* ParseFlags.Action */
15813    ;
15814
15815    if (isAssignmentEvent) {
15816      flags |= 2
15817      /* ParseFlags.AssignmentEvent */
15818      ;
15819    }
15820
15821    const ast = new _ParseAST(input, location, absoluteOffset, tokens, flags, this.errors, 0).parseChain();
15822    return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
15823  }
15824
15825  parseBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
15826    const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig);
15827
15828    return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
15829  }
15830
15831  checkSimpleExpression(ast) {
15832    const checker = new SimpleExpressionChecker();
15833    ast.visit(checker);
15834    return checker.errors;
15835  }
15836
15837  parseSimpleBinding(input, location, absoluteOffset, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
15838    const ast = this._parseBindingAst(input, location, absoluteOffset, interpolationConfig);
15839
15840    const errors = this.checkSimpleExpression(ast);
15841
15842    if (errors.length > 0) {
15843      this._reportError(`Host binding expression cannot contain ${errors.join(' ')}`, input, location);
15844    }
15845
15846    return new ASTWithSource(ast, input, location, absoluteOffset, this.errors);
15847  }
15848
15849  _reportError(message, input, errLocation, ctxLocation) {
15850    this.errors.push(new ParserError(message, input, errLocation, ctxLocation));
15851  }
15852
15853  _parseBindingAst(input, location, absoluteOffset, interpolationConfig) {
15854    this._checkNoInterpolation(input, location, interpolationConfig);
15855
15856    const sourceToLex = this._stripComments(input);
15857
15858    const tokens = this._lexer.tokenize(sourceToLex);
15859
15860    return new _ParseAST(input, location, absoluteOffset, tokens, 0
15861    /* ParseFlags.None */
15862    , this.errors, 0).parseChain();
15863  }
15864  /**
15865   * Parse microsyntax template expression and return a list of bindings or
15866   * parsing errors in case the given expression is invalid.
15867   *
15868   * For example,
15869   * ```
15870   *   <div *ngFor="let item of items">
15871   *         ^      ^ absoluteValueOffset for `templateValue`
15872   *         absoluteKeyOffset for `templateKey`
15873   * ```
15874   * contains three bindings:
15875   * 1. ngFor -> null
15876   * 2. item -> NgForOfContext.$implicit
15877   * 3. ngForOf -> items
15878   *
15879   * This is apparent from the de-sugared template:
15880   * ```
15881   *   <ng-template ngFor let-item [ngForOf]="items">
15882   * ```
15883   *
15884   * @param templateKey name of directive, without the * prefix. For example: ngIf, ngFor
15885   * @param templateValue RHS of the microsyntax attribute
15886   * @param templateUrl template filename if it's external, component filename if it's inline
15887   * @param absoluteKeyOffset start of the `templateKey`
15888   * @param absoluteValueOffset start of the `templateValue`
15889   */
15890
15891
15892  parseTemplateBindings(templateKey, templateValue, templateUrl, absoluteKeyOffset, absoluteValueOffset) {
15893    const tokens = this._lexer.tokenize(templateValue);
15894
15895    const parser = new _ParseAST(templateValue, templateUrl, absoluteValueOffset, tokens, 0
15896    /* ParseFlags.None */
15897    , this.errors, 0
15898    /* relative offset */
15899    );
15900    return parser.parseTemplateBindings({
15901      source: templateKey,
15902      span: new AbsoluteSourceSpan(absoluteKeyOffset, absoluteKeyOffset + templateKey.length)
15903    });
15904  }
15905
15906  parseInterpolation(input, location, absoluteOffset, interpolatedTokens, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
15907    const {
15908      strings,
15909      expressions,
15910      offsets
15911    } = this.splitInterpolation(input, location, interpolatedTokens, interpolationConfig);
15912    if (expressions.length === 0) return null;
15913    const expressionNodes = [];
15914
15915    for (let i = 0; i < expressions.length; ++i) {
15916      const expressionText = expressions[i].text;
15917
15918      const sourceToLex = this._stripComments(expressionText);
15919
15920      const tokens = this._lexer.tokenize(sourceToLex);
15921
15922      const ast = new _ParseAST(input, location, absoluteOffset, tokens, 0
15923      /* ParseFlags.None */
15924      , this.errors, offsets[i]).parseChain();
15925      expressionNodes.push(ast);
15926    }
15927
15928    return this.createInterpolationAst(strings.map(s => s.text), expressionNodes, input, location, absoluteOffset);
15929  }
15930  /**
15931   * Similar to `parseInterpolation`, but treats the provided string as a single expression
15932   * element that would normally appear within the interpolation prefix and suffix (`{{` and `}}`).
15933   * This is used for parsing the switch expression in ICUs.
15934   */
15935
15936
15937  parseInterpolationExpression(expression, location, absoluteOffset) {
15938    const sourceToLex = this._stripComments(expression);
15939
15940    const tokens = this._lexer.tokenize(sourceToLex);
15941
15942    const ast = new _ParseAST(expression, location, absoluteOffset, tokens, 0
15943    /* ParseFlags.None */
15944    , this.errors, 0).parseChain();
15945    const strings = ['', '']; // The prefix and suffix strings are both empty
15946
15947    return this.createInterpolationAst(strings, [ast], expression, location, absoluteOffset);
15948  }
15949
15950  createInterpolationAst(strings, expressions, input, location, absoluteOffset) {
15951    const span = new ParseSpan(0, input.length);
15952    const interpolation = new Interpolation(span, span.toAbsolute(absoluteOffset), strings, expressions);
15953    return new ASTWithSource(interpolation, input, location, absoluteOffset, this.errors);
15954  }
15955  /**
15956   * Splits a string of text into "raw" text segments and expressions present in interpolations in
15957   * the string.
15958   * Returns `null` if there are no interpolations, otherwise a
15959   * `SplitInterpolation` with splits that look like
15960   *   <raw text> <expression> <raw text> ... <raw text> <expression> <raw text>
15961   */
15962
15963
15964  splitInterpolation(input, location, interpolatedTokens, interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
15965    const strings = [];
15966    const expressions = [];
15967    const offsets = [];
15968    const inputToTemplateIndexMap = interpolatedTokens ? getIndexMapForOriginalTemplate(interpolatedTokens) : null;
15969    let i = 0;
15970    let atInterpolation = false;
15971    let extendLastString = false;
15972    let {
15973      start: interpStart,
15974      end: interpEnd
15975    } = interpolationConfig;
15976
15977    while (i < input.length) {
15978      if (!atInterpolation) {
15979        // parse until starting {{
15980        const start = i;
15981        i = input.indexOf(interpStart, i);
15982
15983        if (i === -1) {
15984          i = input.length;
15985        }
15986
15987        const text = input.substring(start, i);
15988        strings.push({
15989          text,
15990          start,
15991          end: i
15992        });
15993        atInterpolation = true;
15994      } else {
15995        // parse from starting {{ to ending }} while ignoring content inside quotes.
15996        const fullStart = i;
15997        const exprStart = fullStart + interpStart.length;
15998
15999        const exprEnd = this._getInterpolationEndIndex(input, interpEnd, exprStart);
16000
16001        if (exprEnd === -1) {
16002          // Could not find the end of the interpolation; do not parse an expression.
16003          // Instead we should extend the content on the last raw string.
16004          atInterpolation = false;
16005          extendLastString = true;
16006          break;
16007        }
16008
16009        const fullEnd = exprEnd + interpEnd.length;
16010        const text = input.substring(exprStart, exprEnd);
16011
16012        if (text.trim().length === 0) {
16013          this._reportError('Blank expressions are not allowed in interpolated strings', input, `at column ${i} in`, location);
16014        }
16015
16016        expressions.push({
16017          text,
16018          start: fullStart,
16019          end: fullEnd
16020        });
16021        const startInOriginalTemplate = inputToTemplateIndexMap?.get(fullStart) ?? fullStart;
16022        const offset = startInOriginalTemplate + interpStart.length;
16023        offsets.push(offset);
16024        i = fullEnd;
16025        atInterpolation = false;
16026      }
16027    }
16028
16029    if (!atInterpolation) {
16030      // If we are now at a text section, add the remaining content as a raw string.
16031      if (extendLastString) {
16032        const piece = strings[strings.length - 1];
16033        piece.text += input.substring(i);
16034        piece.end = input.length;
16035      } else {
16036        strings.push({
16037          text: input.substring(i),
16038          start: i,
16039          end: input.length
16040        });
16041      }
16042    }
16043
16044    return new SplitInterpolation(strings, expressions, offsets);
16045  }
16046
16047  wrapLiteralPrimitive(input, location, absoluteOffset) {
16048    const span = new ParseSpan(0, input == null ? 0 : input.length);
16049    return new ASTWithSource(new LiteralPrimitive(span, span.toAbsolute(absoluteOffset), input), input, location, absoluteOffset, this.errors);
16050  }
16051
16052  _stripComments(input) {
16053    const i = this._commentStart(input);
16054
16055    return i != null ? input.substring(0, i) : input;
16056  }
16057
16058  _commentStart(input) {
16059    let outerQuote = null;
16060
16061    for (let i = 0; i < input.length - 1; i++) {
16062      const char = input.charCodeAt(i);
16063      const nextChar = input.charCodeAt(i + 1);
16064      if (char === $SLASH && nextChar == $SLASH && outerQuote == null) return i;
16065
16066      if (outerQuote === char) {
16067        outerQuote = null;
16068      } else if (outerQuote == null && isQuote(char)) {
16069        outerQuote = char;
16070      }
16071    }
16072
16073    return null;
16074  }
16075
16076  _checkNoInterpolation(input, location, {
16077    start,
16078    end
16079  }) {
16080    let startIndex = -1;
16081    let endIndex = -1;
16082
16083    for (const charIndex of this._forEachUnquotedChar(input, 0)) {
16084      if (startIndex === -1) {
16085        if (input.startsWith(start)) {
16086          startIndex = charIndex;
16087        }
16088      } else {
16089        endIndex = this._getInterpolationEndIndex(input, end, charIndex);
16090
16091        if (endIndex > -1) {
16092          break;
16093        }
16094      }
16095    }
16096
16097    if (startIndex > -1 && endIndex > -1) {
16098      this._reportError(`Got interpolation (${start}${end}) where expression was expected`, input, `at column ${startIndex} in`, location);
16099    }
16100  }
16101  /**
16102   * Finds the index of the end of an interpolation expression
16103   * while ignoring comments and quoted content.
16104   */
16105
16106
16107  _getInterpolationEndIndex(input, expressionEnd, start) {
16108    for (const charIndex of this._forEachUnquotedChar(input, start)) {
16109      if (input.startsWith(expressionEnd, charIndex)) {
16110        return charIndex;
16111      } // Nothing else in the expression matters after we've
16112      // hit a comment so look directly for the end token.
16113
16114
16115      if (input.startsWith('//', charIndex)) {
16116        return input.indexOf(expressionEnd, charIndex);
16117      }
16118    }
16119
16120    return -1;
16121  }
16122  /**
16123   * Generator used to iterate over the character indexes of a string that are outside of quotes.
16124   * @param input String to loop through.
16125   * @param start Index within the string at which to start.
16126   */
16127
16128
16129  *_forEachUnquotedChar(input, start) {
16130    let currentQuote = null;
16131    let escapeCount = 0;
16132
16133    for (let i = start; i < input.length; i++) {
16134      const char = input[i]; // Skip the characters inside quotes. Note that we only care about the outer-most
16135      // quotes matching up and we need to account for escape characters.
16136
16137      if (isQuote(input.charCodeAt(i)) && (currentQuote === null || currentQuote === char) && escapeCount % 2 === 0) {
16138        currentQuote = currentQuote === null ? char : null;
16139      } else if (currentQuote === null) {
16140        yield i;
16141      }
16142
16143      escapeCount = char === '\\' ? escapeCount + 1 : 0;
16144    }
16145  }
16146
16147}
16148/** Describes a stateful context an expression parser is in. */
16149
16150
16151var ParseContextFlags;
16152
16153(function (ParseContextFlags) {
16154  ParseContextFlags[ParseContextFlags["None"] = 0] = "None";
16155  /**
16156   * A Writable context is one in which a value may be written to an lvalue.
16157   * For example, after we see a property access, we may expect a write to the
16158   * property via the "=" operator.
16159   *   prop
16160   *        ^ possible "=" after
16161   */
16162
16163  ParseContextFlags[ParseContextFlags["Writable"] = 1] = "Writable";
16164})(ParseContextFlags || (ParseContextFlags = {}));
16165
16166class _ParseAST {
16167  constructor(input, location, absoluteOffset, tokens, parseFlags, errors, offset) {
16168    this.input = input;
16169    this.location = location;
16170    this.absoluteOffset = absoluteOffset;
16171    this.tokens = tokens;
16172    this.parseFlags = parseFlags;
16173    this.errors = errors;
16174    this.offset = offset;
16175    this.rparensExpected = 0;
16176    this.rbracketsExpected = 0;
16177    this.rbracesExpected = 0;
16178    this.context = ParseContextFlags.None; // Cache of expression start and input indeces to the absolute source span they map to, used to
16179    // prevent creating superfluous source spans in `sourceSpan`.
16180    // A serial of the expression start and input index is used for mapping because both are stateful
16181    // and may change for subsequent expressions visited by the parser.
16182
16183    this.sourceSpanCache = new Map();
16184    this.index = 0;
16185  }
16186
16187  peek(offset) {
16188    const i = this.index + offset;
16189    return i < this.tokens.length ? this.tokens[i] : EOF;
16190  }
16191
16192  get next() {
16193    return this.peek(0);
16194  }
16195  /** Whether all the parser input has been processed. */
16196
16197
16198  get atEOF() {
16199    return this.index >= this.tokens.length;
16200  }
16201  /**
16202   * Index of the next token to be processed, or the end of the last token if all have been
16203   * processed.
16204   */
16205
16206
16207  get inputIndex() {
16208    return this.atEOF ? this.currentEndIndex : this.next.index + this.offset;
16209  }
16210  /**
16211   * End index of the last processed token, or the start of the first token if none have been
16212   * processed.
16213   */
16214
16215
16216  get currentEndIndex() {
16217    if (this.index > 0) {
16218      const curToken = this.peek(-1);
16219      return curToken.end + this.offset;
16220    } // No tokens have been processed yet; return the next token's start or the length of the input
16221    // if there is no token.
16222
16223
16224    if (this.tokens.length === 0) {
16225      return this.input.length + this.offset;
16226    }
16227
16228    return this.next.index + this.offset;
16229  }
16230  /**
16231   * Returns the absolute offset of the start of the current token.
16232   */
16233
16234
16235  get currentAbsoluteOffset() {
16236    return this.absoluteOffset + this.inputIndex;
16237  }
16238  /**
16239   * Retrieve a `ParseSpan` from `start` to the current position (or to `artificialEndIndex` if
16240   * provided).
16241   *
16242   * @param start Position from which the `ParseSpan` will start.
16243   * @param artificialEndIndex Optional ending index to be used if provided (and if greater than the
16244   *     natural ending index)
16245   */
16246
16247
16248  span(start, artificialEndIndex) {
16249    let endIndex = this.currentEndIndex;
16250
16251    if (artificialEndIndex !== undefined && artificialEndIndex > this.currentEndIndex) {
16252      endIndex = artificialEndIndex;
16253    } // In some unusual parsing scenarios (like when certain tokens are missing and an `EmptyExpr` is
16254    // being created), the current token may already be advanced beyond the `currentEndIndex`. This
16255    // appears to be a deep-seated parser bug.
16256    //
16257    // As a workaround for now, swap the start and end indices to ensure a valid `ParseSpan`.
16258    // TODO(alxhub): fix the bug upstream in the parser state, and remove this workaround.
16259
16260
16261    if (start > endIndex) {
16262      const tmp = endIndex;
16263      endIndex = start;
16264      start = tmp;
16265    }
16266
16267    return new ParseSpan(start, endIndex);
16268  }
16269
16270  sourceSpan(start, artificialEndIndex) {
16271    const serial = `${start}@${this.inputIndex}:${artificialEndIndex}`;
16272
16273    if (!this.sourceSpanCache.has(serial)) {
16274      this.sourceSpanCache.set(serial, this.span(start, artificialEndIndex).toAbsolute(this.absoluteOffset));
16275    }
16276
16277    return this.sourceSpanCache.get(serial);
16278  }
16279
16280  advance() {
16281    this.index++;
16282  }
16283  /**
16284   * Executes a callback in the provided context.
16285   */
16286
16287
16288  withContext(context, cb) {
16289    this.context |= context;
16290    const ret = cb();
16291    this.context ^= context;
16292    return ret;
16293  }
16294
16295  consumeOptionalCharacter(code) {
16296    if (this.next.isCharacter(code)) {
16297      this.advance();
16298      return true;
16299    } else {
16300      return false;
16301    }
16302  }
16303
16304  peekKeywordLet() {
16305    return this.next.isKeywordLet();
16306  }
16307
16308  peekKeywordAs() {
16309    return this.next.isKeywordAs();
16310  }
16311  /**
16312   * Consumes an expected character, otherwise emits an error about the missing expected character
16313   * and skips over the token stream until reaching a recoverable point.
16314   *
16315   * See `this.error` and `this.skip` for more details.
16316   */
16317
16318
16319  expectCharacter(code) {
16320    if (this.consumeOptionalCharacter(code)) return;
16321    this.error(`Missing expected ${String.fromCharCode(code)}`);
16322  }
16323
16324  consumeOptionalOperator(op) {
16325    if (this.next.isOperator(op)) {
16326      this.advance();
16327      return true;
16328    } else {
16329      return false;
16330    }
16331  }
16332
16333  expectOperator(operator) {
16334    if (this.consumeOptionalOperator(operator)) return;
16335    this.error(`Missing expected operator ${operator}`);
16336  }
16337
16338  prettyPrintToken(tok) {
16339    return tok === EOF ? 'end of input' : `token ${tok}`;
16340  }
16341
16342  expectIdentifierOrKeyword() {
16343    const n = this.next;
16344
16345    if (!n.isIdentifier() && !n.isKeyword()) {
16346      if (n.isPrivateIdentifier()) {
16347        this._reportErrorForPrivateIdentifier(n, 'expected identifier or keyword');
16348      } else {
16349        this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier or keyword`);
16350      }
16351
16352      return null;
16353    }
16354
16355    this.advance();
16356    return n.toString();
16357  }
16358
16359  expectIdentifierOrKeywordOrString() {
16360    const n = this.next;
16361
16362    if (!n.isIdentifier() && !n.isKeyword() && !n.isString()) {
16363      if (n.isPrivateIdentifier()) {
16364        this._reportErrorForPrivateIdentifier(n, 'expected identifier, keyword or string');
16365      } else {
16366        this.error(`Unexpected ${this.prettyPrintToken(n)}, expected identifier, keyword, or string`);
16367      }
16368
16369      return '';
16370    }
16371
16372    this.advance();
16373    return n.toString();
16374  }
16375
16376  parseChain() {
16377    const exprs = [];
16378    const start = this.inputIndex;
16379
16380    while (this.index < this.tokens.length) {
16381      const expr = this.parsePipe();
16382      exprs.push(expr);
16383
16384      if (this.consumeOptionalCharacter($SEMICOLON)) {
16385        if (!(this.parseFlags & 1
16386        /* ParseFlags.Action */
16387        )) {
16388          this.error('Binding expression cannot contain chained expression');
16389        }
16390
16391        while (this.consumeOptionalCharacter($SEMICOLON)) {} // read all semicolons
16392
16393      } else if (this.index < this.tokens.length) {
16394        const errorIndex = this.index;
16395        this.error(`Unexpected token '${this.next}'`); // The `error` call above will skip ahead to the next recovery point in an attempt to
16396        // recover part of the expression, but that might be the token we started from which will
16397        // lead to an infinite loop. If that's the case, break the loop assuming that we can't
16398        // parse further.
16399
16400        if (this.index === errorIndex) {
16401          break;
16402        }
16403      }
16404    }
16405
16406    if (exprs.length === 0) {
16407      // We have no expressions so create an empty expression that spans the entire input length
16408      const artificialStart = this.offset;
16409      const artificialEnd = this.offset + this.input.length;
16410      return new EmptyExpr(this.span(artificialStart, artificialEnd), this.sourceSpan(artificialStart, artificialEnd));
16411    }
16412
16413    if (exprs.length == 1) return exprs[0];
16414    return new Chain(this.span(start), this.sourceSpan(start), exprs);
16415  }
16416
16417  parsePipe() {
16418    const start = this.inputIndex;
16419    let result = this.parseExpression();
16420
16421    if (this.consumeOptionalOperator('|')) {
16422      if (this.parseFlags & 1
16423      /* ParseFlags.Action */
16424      ) {
16425        this.error('Cannot have a pipe in an action expression');
16426      }
16427
16428      do {
16429        const nameStart = this.inputIndex;
16430        let nameId = this.expectIdentifierOrKeyword();
16431        let nameSpan;
16432        let fullSpanEnd = undefined;
16433
16434        if (nameId !== null) {
16435          nameSpan = this.sourceSpan(nameStart);
16436        } else {
16437          // No valid identifier was found, so we'll assume an empty pipe name ('').
16438          nameId = ''; // However, there may have been whitespace present between the pipe character and the next
16439          // token in the sequence (or the end of input). We want to track this whitespace so that
16440          // the `BindingPipe` we produce covers not just the pipe character, but any trailing
16441          // whitespace beyond it. Another way of thinking about this is that the zero-length name
16442          // is assumed to be at the end of any whitespace beyond the pipe character.
16443          //
16444          // Therefore, we push the end of the `ParseSpan` for this pipe all the way up to the
16445          // beginning of the next token, or until the end of input if the next token is EOF.
16446
16447          fullSpanEnd = this.next.index !== -1 ? this.next.index : this.input.length + this.offset; // The `nameSpan` for an empty pipe name is zero-length at the end of any whitespace
16448          // beyond the pipe character.
16449
16450          nameSpan = new ParseSpan(fullSpanEnd, fullSpanEnd).toAbsolute(this.absoluteOffset);
16451        }
16452
16453        const args = [];
16454
16455        while (this.consumeOptionalCharacter($COLON)) {
16456          args.push(this.parseExpression()); // If there are additional expressions beyond the name, then the artificial end for the
16457          // name is no longer relevant.
16458        }
16459
16460        result = new BindingPipe(this.span(start), this.sourceSpan(start, fullSpanEnd), result, nameId, args, nameSpan);
16461      } while (this.consumeOptionalOperator('|'));
16462    }
16463
16464    return result;
16465  }
16466
16467  parseExpression() {
16468    return this.parseConditional();
16469  }
16470
16471  parseConditional() {
16472    const start = this.inputIndex;
16473    const result = this.parseLogicalOr();
16474
16475    if (this.consumeOptionalOperator('?')) {
16476      const yes = this.parsePipe();
16477      let no;
16478
16479      if (!this.consumeOptionalCharacter($COLON)) {
16480        const end = this.inputIndex;
16481        const expression = this.input.substring(start, end);
16482        this.error(`Conditional expression ${expression} requires all 3 expressions`);
16483        no = new EmptyExpr(this.span(start), this.sourceSpan(start));
16484      } else {
16485        no = this.parsePipe();
16486      }
16487
16488      return new Conditional(this.span(start), this.sourceSpan(start), result, yes, no);
16489    } else {
16490      return result;
16491    }
16492  }
16493
16494  parseLogicalOr() {
16495    // '||'
16496    const start = this.inputIndex;
16497    let result = this.parseLogicalAnd();
16498
16499    while (this.consumeOptionalOperator('||')) {
16500      const right = this.parseLogicalAnd();
16501      result = new Binary(this.span(start), this.sourceSpan(start), '||', result, right);
16502    }
16503
16504    return result;
16505  }
16506
16507  parseLogicalAnd() {
16508    // '&&'
16509    const start = this.inputIndex;
16510    let result = this.parseNullishCoalescing();
16511
16512    while (this.consumeOptionalOperator('&&')) {
16513      const right = this.parseNullishCoalescing();
16514      result = new Binary(this.span(start), this.sourceSpan(start), '&&', result, right);
16515    }
16516
16517    return result;
16518  }
16519
16520  parseNullishCoalescing() {
16521    // '??'
16522    const start = this.inputIndex;
16523    let result = this.parseEquality();
16524
16525    while (this.consumeOptionalOperator('??')) {
16526      const right = this.parseEquality();
16527      result = new Binary(this.span(start), this.sourceSpan(start), '??', result, right);
16528    }
16529
16530    return result;
16531  }
16532
16533  parseEquality() {
16534    // '==','!=','===','!=='
16535    const start = this.inputIndex;
16536    let result = this.parseRelational();
16537
16538    while (this.next.type == TokenType.Operator) {
16539      const operator = this.next.strValue;
16540
16541      switch (operator) {
16542        case '==':
16543        case '===':
16544        case '!=':
16545        case '!==':
16546          this.advance();
16547          const right = this.parseRelational();
16548          result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
16549          continue;
16550      }
16551
16552      break;
16553    }
16554
16555    return result;
16556  }
16557
16558  parseRelational() {
16559    // '<', '>', '<=', '>='
16560    const start = this.inputIndex;
16561    let result = this.parseAdditive();
16562
16563    while (this.next.type == TokenType.Operator) {
16564      const operator = this.next.strValue;
16565
16566      switch (operator) {
16567        case '<':
16568        case '>':
16569        case '<=':
16570        case '>=':
16571          this.advance();
16572          const right = this.parseAdditive();
16573          result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
16574          continue;
16575      }
16576
16577      break;
16578    }
16579
16580    return result;
16581  }
16582
16583  parseAdditive() {
16584    // '+', '-'
16585    const start = this.inputIndex;
16586    let result = this.parseMultiplicative();
16587
16588    while (this.next.type == TokenType.Operator) {
16589      const operator = this.next.strValue;
16590
16591      switch (operator) {
16592        case '+':
16593        case '-':
16594          this.advance();
16595          let right = this.parseMultiplicative();
16596          result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
16597          continue;
16598      }
16599
16600      break;
16601    }
16602
16603    return result;
16604  }
16605
16606  parseMultiplicative() {
16607    // '*', '%', '/'
16608    const start = this.inputIndex;
16609    let result = this.parsePrefix();
16610
16611    while (this.next.type == TokenType.Operator) {
16612      const operator = this.next.strValue;
16613
16614      switch (operator) {
16615        case '*':
16616        case '%':
16617        case '/':
16618          this.advance();
16619          let right = this.parsePrefix();
16620          result = new Binary(this.span(start), this.sourceSpan(start), operator, result, right);
16621          continue;
16622      }
16623
16624      break;
16625    }
16626
16627    return result;
16628  }
16629
16630  parsePrefix() {
16631    if (this.next.type == TokenType.Operator) {
16632      const start = this.inputIndex;
16633      const operator = this.next.strValue;
16634      let result;
16635
16636      switch (operator) {
16637        case '+':
16638          this.advance();
16639          result = this.parsePrefix();
16640          return Unary.createPlus(this.span(start), this.sourceSpan(start), result);
16641
16642        case '-':
16643          this.advance();
16644          result = this.parsePrefix();
16645          return Unary.createMinus(this.span(start), this.sourceSpan(start), result);
16646
16647        case '!':
16648          this.advance();
16649          result = this.parsePrefix();
16650          return new PrefixNot(this.span(start), this.sourceSpan(start), result);
16651      }
16652    }
16653
16654    return this.parseCallChain();
16655  }
16656
16657  parseCallChain() {
16658    const start = this.inputIndex;
16659    let result = this.parsePrimary();
16660
16661    while (true) {
16662      if (this.consumeOptionalCharacter($PERIOD)) {
16663        result = this.parseAccessMember(result, start, false);
16664      } else if (this.consumeOptionalOperator('?.')) {
16665        if (this.consumeOptionalCharacter($LPAREN)) {
16666          result = this.parseCall(result, start, true);
16667        } else {
16668          result = this.consumeOptionalCharacter($LBRACKET) ? this.parseKeyedReadOrWrite(result, start, true) : this.parseAccessMember(result, start, true);
16669        }
16670      } else if (this.consumeOptionalCharacter($LBRACKET)) {
16671        result = this.parseKeyedReadOrWrite(result, start, false);
16672      } else if (this.consumeOptionalCharacter($LPAREN)) {
16673        result = this.parseCall(result, start, false);
16674      } else if (this.consumeOptionalOperator('!')) {
16675        result = new NonNullAssert(this.span(start), this.sourceSpan(start), result);
16676      } else {
16677        return result;
16678      }
16679    }
16680  }
16681
16682  parsePrimary() {
16683    const start = this.inputIndex;
16684
16685    if (this.consumeOptionalCharacter($LPAREN)) {
16686      this.rparensExpected++;
16687      const result = this.parsePipe();
16688      this.rparensExpected--;
16689      this.expectCharacter($RPAREN);
16690      return result;
16691    } else if (this.next.isKeywordNull()) {
16692      this.advance();
16693      return new LiteralPrimitive(this.span(start), this.sourceSpan(start), null);
16694    } else if (this.next.isKeywordUndefined()) {
16695      this.advance();
16696      return new LiteralPrimitive(this.span(start), this.sourceSpan(start), void 0);
16697    } else if (this.next.isKeywordTrue()) {
16698      this.advance();
16699      return new LiteralPrimitive(this.span(start), this.sourceSpan(start), true);
16700    } else if (this.next.isKeywordFalse()) {
16701      this.advance();
16702      return new LiteralPrimitive(this.span(start), this.sourceSpan(start), false);
16703    } else if (this.next.isKeywordThis()) {
16704      this.advance();
16705      return new ThisReceiver(this.span(start), this.sourceSpan(start));
16706    } else if (this.consumeOptionalCharacter($LBRACKET)) {
16707      this.rbracketsExpected++;
16708      const elements = this.parseExpressionList($RBRACKET);
16709      this.rbracketsExpected--;
16710      this.expectCharacter($RBRACKET);
16711      return new LiteralArray(this.span(start), this.sourceSpan(start), elements);
16712    } else if (this.next.isCharacter($LBRACE)) {
16713      return this.parseLiteralMap();
16714    } else if (this.next.isIdentifier()) {
16715      return this.parseAccessMember(new ImplicitReceiver(this.span(start), this.sourceSpan(start)), start, false);
16716    } else if (this.next.isNumber()) {
16717      const value = this.next.toNumber();
16718      this.advance();
16719      return new LiteralPrimitive(this.span(start), this.sourceSpan(start), value);
16720    } else if (this.next.isString()) {
16721      const literalValue = this.next.toString();
16722      this.advance();
16723      return new LiteralPrimitive(this.span(start), this.sourceSpan(start), literalValue);
16724    } else if (this.next.isPrivateIdentifier()) {
16725      this._reportErrorForPrivateIdentifier(this.next, null);
16726
16727      return new EmptyExpr(this.span(start), this.sourceSpan(start));
16728    } else if (this.index >= this.tokens.length) {
16729      this.error(`Unexpected end of expression: ${this.input}`);
16730      return new EmptyExpr(this.span(start), this.sourceSpan(start));
16731    } else {
16732      this.error(`Unexpected token ${this.next}`);
16733      return new EmptyExpr(this.span(start), this.sourceSpan(start));
16734    }
16735  }
16736
16737  parseExpressionList(terminator) {
16738    const result = [];
16739
16740    do {
16741      if (!this.next.isCharacter(terminator)) {
16742        result.push(this.parsePipe());
16743      } else {
16744        break;
16745      }
16746    } while (this.consumeOptionalCharacter($COMMA));
16747
16748    return result;
16749  }
16750
16751  parseLiteralMap() {
16752    const keys = [];
16753    const values = [];
16754    const start = this.inputIndex;
16755    this.expectCharacter($LBRACE);
16756
16757    if (!this.consumeOptionalCharacter($RBRACE)) {
16758      this.rbracesExpected++;
16759
16760      do {
16761        const keyStart = this.inputIndex;
16762        const quoted = this.next.isString();
16763        const key = this.expectIdentifierOrKeywordOrString();
16764        keys.push({
16765          key,
16766          quoted
16767        }); // Properties with quoted keys can't use the shorthand syntax.
16768
16769        if (quoted) {
16770          this.expectCharacter($COLON);
16771          values.push(this.parsePipe());
16772        } else if (this.consumeOptionalCharacter($COLON)) {
16773          values.push(this.parsePipe());
16774        } else {
16775          const span = this.span(keyStart);
16776          const sourceSpan = this.sourceSpan(keyStart);
16777          values.push(new PropertyRead(span, sourceSpan, sourceSpan, new ImplicitReceiver(span, sourceSpan), key));
16778        }
16779      } while (this.consumeOptionalCharacter($COMMA));
16780
16781      this.rbracesExpected--;
16782      this.expectCharacter($RBRACE);
16783    }
16784
16785    return new LiteralMap(this.span(start), this.sourceSpan(start), keys, values);
16786  }
16787
16788  parseAccessMember(readReceiver, start, isSafe) {
16789    const nameStart = this.inputIndex;
16790    const id = this.withContext(ParseContextFlags.Writable, () => {
16791      const id = this.expectIdentifierOrKeyword() ?? '';
16792
16793      if (id.length === 0) {
16794        this.error(`Expected identifier for property access`, readReceiver.span.end);
16795      }
16796
16797      return id;
16798    });
16799    const nameSpan = this.sourceSpan(nameStart);
16800    let receiver;
16801
16802    if (isSafe) {
16803      if (this.consumeOptionalAssignment()) {
16804        this.error('The \'?.\' operator cannot be used in the assignment');
16805        receiver = new EmptyExpr(this.span(start), this.sourceSpan(start));
16806      } else {
16807        receiver = new SafePropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
16808      }
16809    } else {
16810      if (this.consumeOptionalAssignment()) {
16811        if (!(this.parseFlags & 1
16812        /* ParseFlags.Action */
16813        )) {
16814          this.error('Bindings cannot contain assignments');
16815          return new EmptyExpr(this.span(start), this.sourceSpan(start));
16816        }
16817
16818        const value = this.parseConditional();
16819        receiver = new PropertyWrite(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id, value);
16820      } else {
16821        receiver = new PropertyRead(this.span(start), this.sourceSpan(start), nameSpan, readReceiver, id);
16822      }
16823    }
16824
16825    return receiver;
16826  }
16827
16828  parseCall(receiver, start, isSafe) {
16829    const argumentStart = this.inputIndex;
16830    this.rparensExpected++;
16831    const args = this.parseCallArguments();
16832    const argumentSpan = this.span(argumentStart, this.inputIndex).toAbsolute(this.absoluteOffset);
16833    this.expectCharacter($RPAREN);
16834    this.rparensExpected--;
16835    const span = this.span(start);
16836    const sourceSpan = this.sourceSpan(start);
16837    return isSafe ? new SafeCall(span, sourceSpan, receiver, args, argumentSpan) : new Call(span, sourceSpan, receiver, args, argumentSpan);
16838  }
16839
16840  consumeOptionalAssignment() {
16841    // When parsing assignment events (originating from two-way-binding aka banana-in-a-box syntax),
16842    // it is valid for the primary expression to be terminated by the non-null operator. This
16843    // primary expression is substituted as LHS of the assignment operator to achieve
16844    // two-way-binding, such that the LHS could be the non-null operator. The grammar doesn't
16845    // naturally allow for this syntax, so assignment events are parsed specially.
16846    if (this.parseFlags & 2
16847    /* ParseFlags.AssignmentEvent */
16848    && this.next.isOperator('!') && this.peek(1).isOperator('=')) {
16849      // First skip over the ! operator.
16850      this.advance(); // Then skip over the = operator, to fully consume the optional assignment operator.
16851
16852      this.advance();
16853      return true;
16854    }
16855
16856    return this.consumeOptionalOperator('=');
16857  }
16858
16859  parseCallArguments() {
16860    if (this.next.isCharacter($RPAREN)) return [];
16861    const positionals = [];
16862
16863    do {
16864      positionals.push(this.parsePipe());
16865    } while (this.consumeOptionalCharacter($COMMA));
16866
16867    return positionals;
16868  }
16869  /**
16870   * Parses an identifier, a keyword, a string with an optional `-` in between,
16871   * and returns the string along with its absolute source span.
16872   */
16873
16874
16875  expectTemplateBindingKey() {
16876    let result = '';
16877    let operatorFound = false;
16878    const start = this.currentAbsoluteOffset;
16879
16880    do {
16881      result += this.expectIdentifierOrKeywordOrString();
16882      operatorFound = this.consumeOptionalOperator('-');
16883
16884      if (operatorFound) {
16885        result += '-';
16886      }
16887    } while (operatorFound);
16888
16889    return {
16890      source: result,
16891      span: new AbsoluteSourceSpan(start, start + result.length)
16892    };
16893  }
16894  /**
16895   * Parse microsyntax template expression and return a list of bindings or
16896   * parsing errors in case the given expression is invalid.
16897   *
16898   * For example,
16899   * ```
16900   *   <div *ngFor="let item of items; index as i; trackBy: func">
16901   * ```
16902   * contains five bindings:
16903   * 1. ngFor -> null
16904   * 2. item -> NgForOfContext.$implicit
16905   * 3. ngForOf -> items
16906   * 4. i -> NgForOfContext.index
16907   * 5. ngForTrackBy -> func
16908   *
16909   * For a full description of the microsyntax grammar, see
16910   * https://gist.github.com/mhevery/d3530294cff2e4a1b3fe15ff75d08855
16911   *
16912   * @param templateKey name of the microsyntax directive, like ngIf, ngFor,
16913   * without the *, along with its absolute span.
16914   */
16915
16916
16917  parseTemplateBindings(templateKey) {
16918    const bindings = []; // The first binding is for the template key itself
16919    // In *ngFor="let item of items", key = "ngFor", value = null
16920    // In *ngIf="cond | pipe", key = "ngIf", value = "cond | pipe"
16921
16922    bindings.push(...this.parseDirectiveKeywordBindings(templateKey));
16923
16924    while (this.index < this.tokens.length) {
16925      // If it starts with 'let', then this must be variable declaration
16926      const letBinding = this.parseLetBinding();
16927
16928      if (letBinding) {
16929        bindings.push(letBinding);
16930      } else {
16931        // Two possible cases here, either `value "as" key` or
16932        // "directive-keyword expression". We don't know which case, but both
16933        // "value" and "directive-keyword" are template binding key, so consume
16934        // the key first.
16935        const key = this.expectTemplateBindingKey(); // Peek at the next token, if it is "as" then this must be variable
16936        // declaration.
16937
16938        const binding = this.parseAsBinding(key);
16939
16940        if (binding) {
16941          bindings.push(binding);
16942        } else {
16943          // Otherwise the key must be a directive keyword, like "of". Transform
16944          // the key to actual key. Eg. of -> ngForOf, trackBy -> ngForTrackBy
16945          key.source = templateKey.source + key.source.charAt(0).toUpperCase() + key.source.substring(1);
16946          bindings.push(...this.parseDirectiveKeywordBindings(key));
16947        }
16948      }
16949
16950      this.consumeStatementTerminator();
16951    }
16952
16953    return new TemplateBindingParseResult(bindings, []
16954    /* warnings */
16955    , this.errors);
16956  }
16957
16958  parseKeyedReadOrWrite(receiver, start, isSafe) {
16959    return this.withContext(ParseContextFlags.Writable, () => {
16960      this.rbracketsExpected++;
16961      const key = this.parsePipe();
16962
16963      if (key instanceof EmptyExpr) {
16964        this.error(`Key access cannot be empty`);
16965      }
16966
16967      this.rbracketsExpected--;
16968      this.expectCharacter($RBRACKET);
16969
16970      if (this.consumeOptionalOperator('=')) {
16971        if (isSafe) {
16972          this.error('The \'?.\' operator cannot be used in the assignment');
16973        } else {
16974          const value = this.parseConditional();
16975          return new KeyedWrite(this.span(start), this.sourceSpan(start), receiver, key, value);
16976        }
16977      } else {
16978        return isSafe ? new SafeKeyedRead(this.span(start), this.sourceSpan(start), receiver, key) : new KeyedRead(this.span(start), this.sourceSpan(start), receiver, key);
16979      }
16980
16981      return new EmptyExpr(this.span(start), this.sourceSpan(start));
16982    });
16983  }
16984  /**
16985   * Parse a directive keyword, followed by a mandatory expression.
16986   * For example, "of items", "trackBy: func".
16987   * The bindings are: ngForOf -> items, ngForTrackBy -> func
16988   * There could be an optional "as" binding that follows the expression.
16989   * For example,
16990   * ```
16991   *   *ngFor="let item of items | slice:0:1 as collection".
16992   *                    ^^ ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
16993   *               keyword    bound target   optional 'as' binding
16994   * ```
16995   *
16996   * @param key binding key, for example, ngFor, ngIf, ngForOf, along with its
16997   * absolute span.
16998   */
16999
17000
17001  parseDirectiveKeywordBindings(key) {
17002    const bindings = [];
17003    this.consumeOptionalCharacter($COLON); // trackBy: trackByFunction
17004
17005    const value = this.getDirectiveBoundTarget();
17006    let spanEnd = this.currentAbsoluteOffset; // The binding could optionally be followed by "as". For example,
17007    // *ngIf="cond | pipe as x". In this case, the key in the "as" binding
17008    // is "x" and the value is the template key itself ("ngIf"). Note that the
17009    // 'key' in the current context now becomes the "value" in the next binding.
17010
17011    const asBinding = this.parseAsBinding(key);
17012
17013    if (!asBinding) {
17014      this.consumeStatementTerminator();
17015      spanEnd = this.currentAbsoluteOffset;
17016    }
17017
17018    const sourceSpan = new AbsoluteSourceSpan(key.span.start, spanEnd);
17019    bindings.push(new ExpressionBinding(sourceSpan, key, value));
17020
17021    if (asBinding) {
17022      bindings.push(asBinding);
17023    }
17024
17025    return bindings;
17026  }
17027  /**
17028   * Return the expression AST for the bound target of a directive keyword
17029   * binding. For example,
17030   * ```
17031   *   *ngIf="condition | pipe"
17032   *          ^^^^^^^^^^^^^^^^ bound target for "ngIf"
17033   *   *ngFor="let item of items"
17034   *                       ^^^^^ bound target for "ngForOf"
17035   * ```
17036   */
17037
17038
17039  getDirectiveBoundTarget() {
17040    if (this.next === EOF || this.peekKeywordAs() || this.peekKeywordLet()) {
17041      return null;
17042    }
17043
17044    const ast = this.parsePipe(); // example: "condition | async"
17045
17046    const {
17047      start,
17048      end
17049    } = ast.span;
17050    const value = this.input.substring(start, end);
17051    return new ASTWithSource(ast, value, this.location, this.absoluteOffset + start, this.errors);
17052  }
17053  /**
17054   * Return the binding for a variable declared using `as`. Note that the order
17055   * of the key-value pair in this declaration is reversed. For example,
17056   * ```
17057   *   *ngFor="let item of items; index as i"
17058   *                              ^^^^^    ^
17059   *                              value    key
17060   * ```
17061   *
17062   * @param value name of the value in the declaration, "ngIf" in the example
17063   * above, along with its absolute span.
17064   */
17065
17066
17067  parseAsBinding(value) {
17068    if (!this.peekKeywordAs()) {
17069      return null;
17070    }
17071
17072    this.advance(); // consume the 'as' keyword
17073
17074    const key = this.expectTemplateBindingKey();
17075    this.consumeStatementTerminator();
17076    const sourceSpan = new AbsoluteSourceSpan(value.span.start, this.currentAbsoluteOffset);
17077    return new VariableBinding(sourceSpan, key, value);
17078  }
17079  /**
17080   * Return the binding for a variable declared using `let`. For example,
17081   * ```
17082   *   *ngFor="let item of items; let i=index;"
17083   *           ^^^^^^^^           ^^^^^^^^^^^
17084   * ```
17085   * In the first binding, `item` is bound to `NgForOfContext.$implicit`.
17086   * In the second binding, `i` is bound to `NgForOfContext.index`.
17087   */
17088
17089
17090  parseLetBinding() {
17091    if (!this.peekKeywordLet()) {
17092      return null;
17093    }
17094
17095    const spanStart = this.currentAbsoluteOffset;
17096    this.advance(); // consume the 'let' keyword
17097
17098    const key = this.expectTemplateBindingKey();
17099    let value = null;
17100
17101    if (this.consumeOptionalOperator('=')) {
17102      value = this.expectTemplateBindingKey();
17103    }
17104
17105    this.consumeStatementTerminator();
17106    const sourceSpan = new AbsoluteSourceSpan(spanStart, this.currentAbsoluteOffset);
17107    return new VariableBinding(sourceSpan, key, value);
17108  }
17109  /**
17110   * Consume the optional statement terminator: semicolon or comma.
17111   */
17112
17113
17114  consumeStatementTerminator() {
17115    this.consumeOptionalCharacter($SEMICOLON) || this.consumeOptionalCharacter($COMMA);
17116  }
17117  /**
17118   * Records an error and skips over the token stream until reaching a recoverable point. See
17119   * `this.skip` for more details on token skipping.
17120   */
17121
17122
17123  error(message, index = null) {
17124    this.errors.push(new ParserError(message, this.input, this.locationText(index), this.location));
17125    this.skip();
17126  }
17127
17128  locationText(index = null) {
17129    if (index == null) index = this.index;
17130    return index < this.tokens.length ? `at column ${this.tokens[index].index + 1} in` : `at the end of the expression`;
17131  }
17132  /**
17133   * Records an error for an unexpected private identifier being discovered.
17134   * @param token Token representing a private identifier.
17135   * @param extraMessage Optional additional message being appended to the error.
17136   */
17137
17138
17139  _reportErrorForPrivateIdentifier(token, extraMessage) {
17140    let errorMessage = `Private identifiers are not supported. Unexpected private identifier: ${token}`;
17141
17142    if (extraMessage !== null) {
17143      errorMessage += `, ${extraMessage}`;
17144    }
17145
17146    this.error(errorMessage);
17147  }
17148  /**
17149   * Error recovery should skip tokens until it encounters a recovery point.
17150   *
17151   * The following are treated as unconditional recovery points:
17152   *   - end of input
17153   *   - ';' (parseChain() is always the root production, and it expects a ';')
17154   *   - '|' (since pipes may be chained and each pipe expression may be treated independently)
17155   *
17156   * The following are conditional recovery points:
17157   *   - ')', '}', ']' if one of calling productions is expecting one of these symbols
17158   *     - This allows skip() to recover from errors such as '(a.) + 1' allowing more of the AST to
17159   *       be retained (it doesn't skip any tokens as the ')' is retained because of the '(' begins
17160   *       an '(' <expr> ')' production).
17161   *       The recovery points of grouping symbols must be conditional as they must be skipped if
17162   *       none of the calling productions are not expecting the closing token else we will never
17163   *       make progress in the case of an extraneous group closing symbol (such as a stray ')').
17164   *       That is, we skip a closing symbol if we are not in a grouping production.
17165   *   - '=' in a `Writable` context
17166   *     - In this context, we are able to recover after seeing the `=` operator, which
17167   *       signals the presence of an independent rvalue expression following the `=` operator.
17168   *
17169   * If a production expects one of these token it increments the corresponding nesting count,
17170   * and then decrements it just prior to checking if the token is in the input.
17171   */
17172
17173
17174  skip() {
17175    let n = this.next;
17176
17177    while (this.index < this.tokens.length && !n.isCharacter($SEMICOLON) && !n.isOperator('|') && (this.rparensExpected <= 0 || !n.isCharacter($RPAREN)) && (this.rbracesExpected <= 0 || !n.isCharacter($RBRACE)) && (this.rbracketsExpected <= 0 || !n.isCharacter($RBRACKET)) && (!(this.context & ParseContextFlags.Writable) || !n.isOperator('='))) {
17178      if (this.next.isError()) {
17179        this.errors.push(new ParserError(this.next.toString(), this.input, this.locationText(), this.location));
17180      }
17181
17182      this.advance();
17183      n = this.next;
17184    }
17185  }
17186
17187}
17188
17189class SimpleExpressionChecker extends RecursiveAstVisitor {
17190  constructor() {
17191    super(...arguments);
17192    this.errors = [];
17193  }
17194
17195  visitPipe() {
17196    this.errors.push('pipes');
17197  }
17198
17199}
17200/**
17201 * Computes the real offset in the original template for indexes in an interpolation.
17202 *
17203 * Because templates can have encoded HTML entities and the input passed to the parser at this stage
17204 * of the compiler is the _decoded_ value, we need to compute the real offset using the original
17205 * encoded values in the interpolated tokens. Note that this is only a special case handling for
17206 * `MlParserTokenType.ENCODED_ENTITY` token types. All other interpolated tokens are expected to
17207 * have parts which exactly match the input string for parsing the interpolation.
17208 *
17209 * @param interpolatedTokens The tokens for the interpolated value.
17210 *
17211 * @returns A map of index locations in the decoded template to indexes in the original template
17212 */
17213
17214
17215function getIndexMapForOriginalTemplate(interpolatedTokens) {
17216  let offsetMap = new Map();
17217  let consumedInOriginalTemplate = 0;
17218  let consumedInInput = 0;
17219  let tokenIndex = 0;
17220
17221  while (tokenIndex < interpolatedTokens.length) {
17222    const currentToken = interpolatedTokens[tokenIndex];
17223
17224    if (currentToken.type === 9
17225    /* MlParserTokenType.ENCODED_ENTITY */
17226    ) {
17227      const [decoded, encoded] = currentToken.parts;
17228      consumedInOriginalTemplate += encoded.length;
17229      consumedInInput += decoded.length;
17230    } else {
17231      const lengthOfParts = currentToken.parts.reduce((sum, current) => sum + current.length, 0);
17232      consumedInInput += lengthOfParts;
17233      consumedInOriginalTemplate += lengthOfParts;
17234    }
17235
17236    offsetMap.set(consumedInInput, consumedInOriginalTemplate);
17237    tokenIndex++;
17238  }
17239
17240  return offsetMap;
17241}
17242/**
17243 * @license
17244 * Copyright Google LLC All Rights Reserved.
17245 *
17246 * Use of this source code is governed by an MIT-style license that can be
17247 * found in the LICENSE file at https://angular.io/license
17248 */
17249
17250
17251class NodeWithI18n {
17252  constructor(sourceSpan, i18n) {
17253    this.sourceSpan = sourceSpan;
17254    this.i18n = i18n;
17255  }
17256
17257}
17258
17259class Text extends NodeWithI18n {
17260  constructor(value, sourceSpan, tokens, i18n) {
17261    super(sourceSpan, i18n);
17262    this.value = value;
17263    this.tokens = tokens;
17264  }
17265
17266  visit(visitor, context) {
17267    return visitor.visitText(this, context);
17268  }
17269
17270}
17271
17272class Expansion extends NodeWithI18n {
17273  constructor(switchValue, type, cases, sourceSpan, switchValueSourceSpan, i18n) {
17274    super(sourceSpan, i18n);
17275    this.switchValue = switchValue;
17276    this.type = type;
17277    this.cases = cases;
17278    this.switchValueSourceSpan = switchValueSourceSpan;
17279  }
17280
17281  visit(visitor, context) {
17282    return visitor.visitExpansion(this, context);
17283  }
17284
17285}
17286
17287class ExpansionCase {
17288  constructor(value, expression, sourceSpan, valueSourceSpan, expSourceSpan) {
17289    this.value = value;
17290    this.expression = expression;
17291    this.sourceSpan = sourceSpan;
17292    this.valueSourceSpan = valueSourceSpan;
17293    this.expSourceSpan = expSourceSpan;
17294  }
17295
17296  visit(visitor, context) {
17297    return visitor.visitExpansionCase(this, context);
17298  }
17299
17300}
17301
17302class Attribute extends NodeWithI18n {
17303  constructor(name, value, sourceSpan, keySpan, valueSpan, valueTokens, i18n) {
17304    super(sourceSpan, i18n);
17305    this.name = name;
17306    this.value = value;
17307    this.keySpan = keySpan;
17308    this.valueSpan = valueSpan;
17309    this.valueTokens = valueTokens;
17310  }
17311
17312  visit(visitor, context) {
17313    return visitor.visitAttribute(this, context);
17314  }
17315
17316}
17317
17318class Element extends NodeWithI18n {
17319  constructor(name, attrs, children, sourceSpan, startSourceSpan, endSourceSpan = null, i18n) {
17320    super(sourceSpan, i18n);
17321    this.name = name;
17322    this.attrs = attrs;
17323    this.children = children;
17324    this.startSourceSpan = startSourceSpan;
17325    this.endSourceSpan = endSourceSpan;
17326  }
17327
17328  visit(visitor, context) {
17329    return visitor.visitElement(this, context);
17330  }
17331
17332}
17333
17334class Comment {
17335  constructor(value, sourceSpan) {
17336    this.value = value;
17337    this.sourceSpan = sourceSpan;
17338  }
17339
17340  visit(visitor, context) {
17341    return visitor.visitComment(this, context);
17342  }
17343
17344}
17345
17346function visitAll(visitor, nodes, context = null) {
17347  const result = [];
17348  const visit = visitor.visit ? ast => visitor.visit(ast, context) || ast.visit(visitor, context) : ast => ast.visit(visitor, context);
17349  nodes.forEach(ast => {
17350    const astResult = visit(ast);
17351
17352    if (astResult) {
17353      result.push(astResult);
17354    }
17355  });
17356  return result;
17357}
17358
17359class RecursiveVisitor {
17360  constructor() {}
17361
17362  visitElement(ast, context) {
17363    this.visitChildren(context, visit => {
17364      visit(ast.attrs);
17365      visit(ast.children);
17366    });
17367  }
17368
17369  visitAttribute(ast, context) {}
17370
17371  visitText(ast, context) {}
17372
17373  visitComment(ast, context) {}
17374
17375  visitExpansion(ast, context) {
17376    return this.visitChildren(context, visit => {
17377      visit(ast.cases);
17378    });
17379  }
17380
17381  visitExpansionCase(ast, context) {}
17382
17383  visitChildren(context, cb) {
17384    let results = [];
17385    let t = this;
17386
17387    function visit(children) {
17388      if (children) results.push(visitAll(t, children, context));
17389    }
17390
17391    cb(visit);
17392    return Array.prototype.concat.apply([], results);
17393  }
17394
17395}
17396/**
17397 * @license
17398 * Copyright Google LLC All Rights Reserved.
17399 *
17400 * Use of this source code is governed by an MIT-style license that can be
17401 * found in the LICENSE file at https://angular.io/license
17402 */
17403// Mapping between all HTML entity names and their unicode representation.
17404// Generated from https://html.spec.whatwg.org/multipage/entities.json by stripping
17405// the `&` and `;` from the keys and removing the duplicates.
17406// see https://www.w3.org/TR/html51/syntax.html#named-character-references
17407
17408
17409const NAMED_ENTITIES = {
17410  'AElig': '\u00C6',
17411  'AMP': '\u0026',
17412  'amp': '\u0026',
17413  'Aacute': '\u00C1',
17414  'Abreve': '\u0102',
17415  'Acirc': '\u00C2',
17416  'Acy': '\u0410',
17417  'Afr': '\uD835\uDD04',
17418  'Agrave': '\u00C0',
17419  'Alpha': '\u0391',
17420  'Amacr': '\u0100',
17421  'And': '\u2A53',
17422  'Aogon': '\u0104',
17423  'Aopf': '\uD835\uDD38',
17424  'ApplyFunction': '\u2061',
17425  'af': '\u2061',
17426  'Aring': '\u00C5',
17427  'angst': '\u00C5',
17428  'Ascr': '\uD835\uDC9C',
17429  'Assign': '\u2254',
17430  'colone': '\u2254',
17431  'coloneq': '\u2254',
17432  'Atilde': '\u00C3',
17433  'Auml': '\u00C4',
17434  'Backslash': '\u2216',
17435  'setminus': '\u2216',
17436  'setmn': '\u2216',
17437  'smallsetminus': '\u2216',
17438  'ssetmn': '\u2216',
17439  'Barv': '\u2AE7',
17440  'Barwed': '\u2306',
17441  'doublebarwedge': '\u2306',
17442  'Bcy': '\u0411',
17443  'Because': '\u2235',
17444  'becaus': '\u2235',
17445  'because': '\u2235',
17446  'Bernoullis': '\u212C',
17447  'Bscr': '\u212C',
17448  'bernou': '\u212C',
17449  'Beta': '\u0392',
17450  'Bfr': '\uD835\uDD05',
17451  'Bopf': '\uD835\uDD39',
17452  'Breve': '\u02D8',
17453  'breve': '\u02D8',
17454  'Bumpeq': '\u224E',
17455  'HumpDownHump': '\u224E',
17456  'bump': '\u224E',
17457  'CHcy': '\u0427',
17458  'COPY': '\u00A9',
17459  'copy': '\u00A9',
17460  'Cacute': '\u0106',
17461  'Cap': '\u22D2',
17462  'CapitalDifferentialD': '\u2145',
17463  'DD': '\u2145',
17464  'Cayleys': '\u212D',
17465  'Cfr': '\u212D',
17466  'Ccaron': '\u010C',
17467  'Ccedil': '\u00C7',
17468  'Ccirc': '\u0108',
17469  'Cconint': '\u2230',
17470  'Cdot': '\u010A',
17471  'Cedilla': '\u00B8',
17472  'cedil': '\u00B8',
17473  'CenterDot': '\u00B7',
17474  'centerdot': '\u00B7',
17475  'middot': '\u00B7',
17476  'Chi': '\u03A7',
17477  'CircleDot': '\u2299',
17478  'odot': '\u2299',
17479  'CircleMinus': '\u2296',
17480  'ominus': '\u2296',
17481  'CirclePlus': '\u2295',
17482  'oplus': '\u2295',
17483  'CircleTimes': '\u2297',
17484  'otimes': '\u2297',
17485  'ClockwiseContourIntegral': '\u2232',
17486  'cwconint': '\u2232',
17487  'CloseCurlyDoubleQuote': '\u201D',
17488  'rdquo': '\u201D',
17489  'rdquor': '\u201D',
17490  'CloseCurlyQuote': '\u2019',
17491  'rsquo': '\u2019',
17492  'rsquor': '\u2019',
17493  'Colon': '\u2237',
17494  'Proportion': '\u2237',
17495  'Colone': '\u2A74',
17496  'Congruent': '\u2261',
17497  'equiv': '\u2261',
17498  'Conint': '\u222F',
17499  'DoubleContourIntegral': '\u222F',
17500  'ContourIntegral': '\u222E',
17501  'conint': '\u222E',
17502  'oint': '\u222E',
17503  'Copf': '\u2102',
17504  'complexes': '\u2102',
17505  'Coproduct': '\u2210',
17506  'coprod': '\u2210',
17507  'CounterClockwiseContourIntegral': '\u2233',
17508  'awconint': '\u2233',
17509  'Cross': '\u2A2F',
17510  'Cscr': '\uD835\uDC9E',
17511  'Cup': '\u22D3',
17512  'CupCap': '\u224D',
17513  'asympeq': '\u224D',
17514  'DDotrahd': '\u2911',
17515  'DJcy': '\u0402',
17516  'DScy': '\u0405',
17517  'DZcy': '\u040F',
17518  'Dagger': '\u2021',
17519  'ddagger': '\u2021',
17520  'Darr': '\u21A1',
17521  'Dashv': '\u2AE4',
17522  'DoubleLeftTee': '\u2AE4',
17523  'Dcaron': '\u010E',
17524  'Dcy': '\u0414',
17525  'Del': '\u2207',
17526  'nabla': '\u2207',
17527  'Delta': '\u0394',
17528  'Dfr': '\uD835\uDD07',
17529  'DiacriticalAcute': '\u00B4',
17530  'acute': '\u00B4',
17531  'DiacriticalDot': '\u02D9',
17532  'dot': '\u02D9',
17533  'DiacriticalDoubleAcute': '\u02DD',
17534  'dblac': '\u02DD',
17535  'DiacriticalGrave': '\u0060',
17536  'grave': '\u0060',
17537  'DiacriticalTilde': '\u02DC',
17538  'tilde': '\u02DC',
17539  'Diamond': '\u22C4',
17540  'diam': '\u22C4',
17541  'diamond': '\u22C4',
17542  'DifferentialD': '\u2146',
17543  'dd': '\u2146',
17544  'Dopf': '\uD835\uDD3B',
17545  'Dot': '\u00A8',
17546  'DoubleDot': '\u00A8',
17547  'die': '\u00A8',
17548  'uml': '\u00A8',
17549  'DotDot': '\u20DC',
17550  'DotEqual': '\u2250',
17551  'doteq': '\u2250',
17552  'esdot': '\u2250',
17553  'DoubleDownArrow': '\u21D3',
17554  'Downarrow': '\u21D3',
17555  'dArr': '\u21D3',
17556  'DoubleLeftArrow': '\u21D0',
17557  'Leftarrow': '\u21D0',
17558  'lArr': '\u21D0',
17559  'DoubleLeftRightArrow': '\u21D4',
17560  'Leftrightarrow': '\u21D4',
17561  'hArr': '\u21D4',
17562  'iff': '\u21D4',
17563  'DoubleLongLeftArrow': '\u27F8',
17564  'Longleftarrow': '\u27F8',
17565  'xlArr': '\u27F8',
17566  'DoubleLongLeftRightArrow': '\u27FA',
17567  'Longleftrightarrow': '\u27FA',
17568  'xhArr': '\u27FA',
17569  'DoubleLongRightArrow': '\u27F9',
17570  'Longrightarrow': '\u27F9',
17571  'xrArr': '\u27F9',
17572  'DoubleRightArrow': '\u21D2',
17573  'Implies': '\u21D2',
17574  'Rightarrow': '\u21D2',
17575  'rArr': '\u21D2',
17576  'DoubleRightTee': '\u22A8',
17577  'vDash': '\u22A8',
17578  'DoubleUpArrow': '\u21D1',
17579  'Uparrow': '\u21D1',
17580  'uArr': '\u21D1',
17581  'DoubleUpDownArrow': '\u21D5',
17582  'Updownarrow': '\u21D5',
17583  'vArr': '\u21D5',
17584  'DoubleVerticalBar': '\u2225',
17585  'par': '\u2225',
17586  'parallel': '\u2225',
17587  'shortparallel': '\u2225',
17588  'spar': '\u2225',
17589  'DownArrow': '\u2193',
17590  'ShortDownArrow': '\u2193',
17591  'darr': '\u2193',
17592  'downarrow': '\u2193',
17593  'DownArrowBar': '\u2913',
17594  'DownArrowUpArrow': '\u21F5',
17595  'duarr': '\u21F5',
17596  'DownBreve': '\u0311',
17597  'DownLeftRightVector': '\u2950',
17598  'DownLeftTeeVector': '\u295E',
17599  'DownLeftVector': '\u21BD',
17600  'leftharpoondown': '\u21BD',
17601  'lhard': '\u21BD',
17602  'DownLeftVectorBar': '\u2956',
17603  'DownRightTeeVector': '\u295F',
17604  'DownRightVector': '\u21C1',
17605  'rhard': '\u21C1',
17606  'rightharpoondown': '\u21C1',
17607  'DownRightVectorBar': '\u2957',
17608  'DownTee': '\u22A4',
17609  'top': '\u22A4',
17610  'DownTeeArrow': '\u21A7',
17611  'mapstodown': '\u21A7',
17612  'Dscr': '\uD835\uDC9F',
17613  'Dstrok': '\u0110',
17614  'ENG': '\u014A',
17615  'ETH': '\u00D0',
17616  'Eacute': '\u00C9',
17617  'Ecaron': '\u011A',
17618  'Ecirc': '\u00CA',
17619  'Ecy': '\u042D',
17620  'Edot': '\u0116',
17621  'Efr': '\uD835\uDD08',
17622  'Egrave': '\u00C8',
17623  'Element': '\u2208',
17624  'in': '\u2208',
17625  'isin': '\u2208',
17626  'isinv': '\u2208',
17627  'Emacr': '\u0112',
17628  'EmptySmallSquare': '\u25FB',
17629  'EmptyVerySmallSquare': '\u25AB',
17630  'Eogon': '\u0118',
17631  'Eopf': '\uD835\uDD3C',
17632  'Epsilon': '\u0395',
17633  'Equal': '\u2A75',
17634  'EqualTilde': '\u2242',
17635  'eqsim': '\u2242',
17636  'esim': '\u2242',
17637  'Equilibrium': '\u21CC',
17638  'rightleftharpoons': '\u21CC',
17639  'rlhar': '\u21CC',
17640  'Escr': '\u2130',
17641  'expectation': '\u2130',
17642  'Esim': '\u2A73',
17643  'Eta': '\u0397',
17644  'Euml': '\u00CB',
17645  'Exists': '\u2203',
17646  'exist': '\u2203',
17647  'ExponentialE': '\u2147',
17648  'ee': '\u2147',
17649  'exponentiale': '\u2147',
17650  'Fcy': '\u0424',
17651  'Ffr': '\uD835\uDD09',
17652  'FilledSmallSquare': '\u25FC',
17653  'FilledVerySmallSquare': '\u25AA',
17654  'blacksquare': '\u25AA',
17655  'squarf': '\u25AA',
17656  'squf': '\u25AA',
17657  'Fopf': '\uD835\uDD3D',
17658  'ForAll': '\u2200',
17659  'forall': '\u2200',
17660  'Fouriertrf': '\u2131',
17661  'Fscr': '\u2131',
17662  'GJcy': '\u0403',
17663  'GT': '\u003E',
17664  'gt': '\u003E',
17665  'Gamma': '\u0393',
17666  'Gammad': '\u03DC',
17667  'Gbreve': '\u011E',
17668  'Gcedil': '\u0122',
17669  'Gcirc': '\u011C',
17670  'Gcy': '\u0413',
17671  'Gdot': '\u0120',
17672  'Gfr': '\uD835\uDD0A',
17673  'Gg': '\u22D9',
17674  'ggg': '\u22D9',
17675  'Gopf': '\uD835\uDD3E',
17676  'GreaterEqual': '\u2265',
17677  'ge': '\u2265',
17678  'geq': '\u2265',
17679  'GreaterEqualLess': '\u22DB',
17680  'gel': '\u22DB',
17681  'gtreqless': '\u22DB',
17682  'GreaterFullEqual': '\u2267',
17683  'gE': '\u2267',
17684  'geqq': '\u2267',
17685  'GreaterGreater': '\u2AA2',
17686  'GreaterLess': '\u2277',
17687  'gl': '\u2277',
17688  'gtrless': '\u2277',
17689  'GreaterSlantEqual': '\u2A7E',
17690  'geqslant': '\u2A7E',
17691  'ges': '\u2A7E',
17692  'GreaterTilde': '\u2273',
17693  'gsim': '\u2273',
17694  'gtrsim': '\u2273',
17695  'Gscr': '\uD835\uDCA2',
17696  'Gt': '\u226B',
17697  'NestedGreaterGreater': '\u226B',
17698  'gg': '\u226B',
17699  'HARDcy': '\u042A',
17700  'Hacek': '\u02C7',
17701  'caron': '\u02C7',
17702  'Hat': '\u005E',
17703  'Hcirc': '\u0124',
17704  'Hfr': '\u210C',
17705  'Poincareplane': '\u210C',
17706  'HilbertSpace': '\u210B',
17707  'Hscr': '\u210B',
17708  'hamilt': '\u210B',
17709  'Hopf': '\u210D',
17710  'quaternions': '\u210D',
17711  'HorizontalLine': '\u2500',
17712  'boxh': '\u2500',
17713  'Hstrok': '\u0126',
17714  'HumpEqual': '\u224F',
17715  'bumpe': '\u224F',
17716  'bumpeq': '\u224F',
17717  'IEcy': '\u0415',
17718  'IJlig': '\u0132',
17719  'IOcy': '\u0401',
17720  'Iacute': '\u00CD',
17721  'Icirc': '\u00CE',
17722  'Icy': '\u0418',
17723  'Idot': '\u0130',
17724  'Ifr': '\u2111',
17725  'Im': '\u2111',
17726  'image': '\u2111',
17727  'imagpart': '\u2111',
17728  'Igrave': '\u00CC',
17729  'Imacr': '\u012A',
17730  'ImaginaryI': '\u2148',
17731  'ii': '\u2148',
17732  'Int': '\u222C',
17733  'Integral': '\u222B',
17734  'int': '\u222B',
17735  'Intersection': '\u22C2',
17736  'bigcap': '\u22C2',
17737  'xcap': '\u22C2',
17738  'InvisibleComma': '\u2063',
17739  'ic': '\u2063',
17740  'InvisibleTimes': '\u2062',
17741  'it': '\u2062',
17742  'Iogon': '\u012E',
17743  'Iopf': '\uD835\uDD40',
17744  'Iota': '\u0399',
17745  'Iscr': '\u2110',
17746  'imagline': '\u2110',
17747  'Itilde': '\u0128',
17748  'Iukcy': '\u0406',
17749  'Iuml': '\u00CF',
17750  'Jcirc': '\u0134',
17751  'Jcy': '\u0419',
17752  'Jfr': '\uD835\uDD0D',
17753  'Jopf': '\uD835\uDD41',
17754  'Jscr': '\uD835\uDCA5',
17755  'Jsercy': '\u0408',
17756  'Jukcy': '\u0404',
17757  'KHcy': '\u0425',
17758  'KJcy': '\u040C',
17759  'Kappa': '\u039A',
17760  'Kcedil': '\u0136',
17761  'Kcy': '\u041A',
17762  'Kfr': '\uD835\uDD0E',
17763  'Kopf': '\uD835\uDD42',
17764  'Kscr': '\uD835\uDCA6',
17765  'LJcy': '\u0409',
17766  'LT': '\u003C',
17767  'lt': '\u003C',
17768  'Lacute': '\u0139',
17769  'Lambda': '\u039B',
17770  'Lang': '\u27EA',
17771  'Laplacetrf': '\u2112',
17772  'Lscr': '\u2112',
17773  'lagran': '\u2112',
17774  'Larr': '\u219E',
17775  'twoheadleftarrow': '\u219E',
17776  'Lcaron': '\u013D',
17777  'Lcedil': '\u013B',
17778  'Lcy': '\u041B',
17779  'LeftAngleBracket': '\u27E8',
17780  'lang': '\u27E8',
17781  'langle': '\u27E8',
17782  'LeftArrow': '\u2190',
17783  'ShortLeftArrow': '\u2190',
17784  'larr': '\u2190',
17785  'leftarrow': '\u2190',
17786  'slarr': '\u2190',
17787  'LeftArrowBar': '\u21E4',
17788  'larrb': '\u21E4',
17789  'LeftArrowRightArrow': '\u21C6',
17790  'leftrightarrows': '\u21C6',
17791  'lrarr': '\u21C6',
17792  'LeftCeiling': '\u2308',
17793  'lceil': '\u2308',
17794  'LeftDoubleBracket': '\u27E6',
17795  'lobrk': '\u27E6',
17796  'LeftDownTeeVector': '\u2961',
17797  'LeftDownVector': '\u21C3',
17798  'dharl': '\u21C3',
17799  'downharpoonleft': '\u21C3',
17800  'LeftDownVectorBar': '\u2959',
17801  'LeftFloor': '\u230A',
17802  'lfloor': '\u230A',
17803  'LeftRightArrow': '\u2194',
17804  'harr': '\u2194',
17805  'leftrightarrow': '\u2194',
17806  'LeftRightVector': '\u294E',
17807  'LeftTee': '\u22A3',
17808  'dashv': '\u22A3',
17809  'LeftTeeArrow': '\u21A4',
17810  'mapstoleft': '\u21A4',
17811  'LeftTeeVector': '\u295A',
17812  'LeftTriangle': '\u22B2',
17813  'vartriangleleft': '\u22B2',
17814  'vltri': '\u22B2',
17815  'LeftTriangleBar': '\u29CF',
17816  'LeftTriangleEqual': '\u22B4',
17817  'ltrie': '\u22B4',
17818  'trianglelefteq': '\u22B4',
17819  'LeftUpDownVector': '\u2951',
17820  'LeftUpTeeVector': '\u2960',
17821  'LeftUpVector': '\u21BF',
17822  'uharl': '\u21BF',
17823  'upharpoonleft': '\u21BF',
17824  'LeftUpVectorBar': '\u2958',
17825  'LeftVector': '\u21BC',
17826  'leftharpoonup': '\u21BC',
17827  'lharu': '\u21BC',
17828  'LeftVectorBar': '\u2952',
17829  'LessEqualGreater': '\u22DA',
17830  'leg': '\u22DA',
17831  'lesseqgtr': '\u22DA',
17832  'LessFullEqual': '\u2266',
17833  'lE': '\u2266',
17834  'leqq': '\u2266',
17835  'LessGreater': '\u2276',
17836  'lessgtr': '\u2276',
17837  'lg': '\u2276',
17838  'LessLess': '\u2AA1',
17839  'LessSlantEqual': '\u2A7D',
17840  'leqslant': '\u2A7D',
17841  'les': '\u2A7D',
17842  'LessTilde': '\u2272',
17843  'lesssim': '\u2272',
17844  'lsim': '\u2272',
17845  'Lfr': '\uD835\uDD0F',
17846  'Ll': '\u22D8',
17847  'Lleftarrow': '\u21DA',
17848  'lAarr': '\u21DA',
17849  'Lmidot': '\u013F',
17850  'LongLeftArrow': '\u27F5',
17851  'longleftarrow': '\u27F5',
17852  'xlarr': '\u27F5',
17853  'LongLeftRightArrow': '\u27F7',
17854  'longleftrightarrow': '\u27F7',
17855  'xharr': '\u27F7',
17856  'LongRightArrow': '\u27F6',
17857  'longrightarrow': '\u27F6',
17858  'xrarr': '\u27F6',
17859  'Lopf': '\uD835\uDD43',
17860  'LowerLeftArrow': '\u2199',
17861  'swarr': '\u2199',
17862  'swarrow': '\u2199',
17863  'LowerRightArrow': '\u2198',
17864  'searr': '\u2198',
17865  'searrow': '\u2198',
17866  'Lsh': '\u21B0',
17867  'lsh': '\u21B0',
17868  'Lstrok': '\u0141',
17869  'Lt': '\u226A',
17870  'NestedLessLess': '\u226A',
17871  'll': '\u226A',
17872  'Map': '\u2905',
17873  'Mcy': '\u041C',
17874  'MediumSpace': '\u205F',
17875  'Mellintrf': '\u2133',
17876  'Mscr': '\u2133',
17877  'phmmat': '\u2133',
17878  'Mfr': '\uD835\uDD10',
17879  'MinusPlus': '\u2213',
17880  'mnplus': '\u2213',
17881  'mp': '\u2213',
17882  'Mopf': '\uD835\uDD44',
17883  'Mu': '\u039C',
17884  'NJcy': '\u040A',
17885  'Nacute': '\u0143',
17886  'Ncaron': '\u0147',
17887  'Ncedil': '\u0145',
17888  'Ncy': '\u041D',
17889  'NegativeMediumSpace': '\u200B',
17890  'NegativeThickSpace': '\u200B',
17891  'NegativeThinSpace': '\u200B',
17892  'NegativeVeryThinSpace': '\u200B',
17893  'ZeroWidthSpace': '\u200B',
17894  'NewLine': '\u000A',
17895  'Nfr': '\uD835\uDD11',
17896  'NoBreak': '\u2060',
17897  'NonBreakingSpace': '\u00A0',
17898  'nbsp': '\u00A0',
17899  'Nopf': '\u2115',
17900  'naturals': '\u2115',
17901  'Not': '\u2AEC',
17902  'NotCongruent': '\u2262',
17903  'nequiv': '\u2262',
17904  'NotCupCap': '\u226D',
17905  'NotDoubleVerticalBar': '\u2226',
17906  'npar': '\u2226',
17907  'nparallel': '\u2226',
17908  'nshortparallel': '\u2226',
17909  'nspar': '\u2226',
17910  'NotElement': '\u2209',
17911  'notin': '\u2209',
17912  'notinva': '\u2209',
17913  'NotEqual': '\u2260',
17914  'ne': '\u2260',
17915  'NotEqualTilde': '\u2242\u0338',
17916  'nesim': '\u2242\u0338',
17917  'NotExists': '\u2204',
17918  'nexist': '\u2204',
17919  'nexists': '\u2204',
17920  'NotGreater': '\u226F',
17921  'ngt': '\u226F',
17922  'ngtr': '\u226F',
17923  'NotGreaterEqual': '\u2271',
17924  'nge': '\u2271',
17925  'ngeq': '\u2271',
17926  'NotGreaterFullEqual': '\u2267\u0338',
17927  'ngE': '\u2267\u0338',
17928  'ngeqq': '\u2267\u0338',
17929  'NotGreaterGreater': '\u226B\u0338',
17930  'nGtv': '\u226B\u0338',
17931  'NotGreaterLess': '\u2279',
17932  'ntgl': '\u2279',
17933  'NotGreaterSlantEqual': '\u2A7E\u0338',
17934  'ngeqslant': '\u2A7E\u0338',
17935  'nges': '\u2A7E\u0338',
17936  'NotGreaterTilde': '\u2275',
17937  'ngsim': '\u2275',
17938  'NotHumpDownHump': '\u224E\u0338',
17939  'nbump': '\u224E\u0338',
17940  'NotHumpEqual': '\u224F\u0338',
17941  'nbumpe': '\u224F\u0338',
17942  'NotLeftTriangle': '\u22EA',
17943  'nltri': '\u22EA',
17944  'ntriangleleft': '\u22EA',
17945  'NotLeftTriangleBar': '\u29CF\u0338',
17946  'NotLeftTriangleEqual': '\u22EC',
17947  'nltrie': '\u22EC',
17948  'ntrianglelefteq': '\u22EC',
17949  'NotLess': '\u226E',
17950  'nless': '\u226E',
17951  'nlt': '\u226E',
17952  'NotLessEqual': '\u2270',
17953  'nle': '\u2270',
17954  'nleq': '\u2270',
17955  'NotLessGreater': '\u2278',
17956  'ntlg': '\u2278',
17957  'NotLessLess': '\u226A\u0338',
17958  'nLtv': '\u226A\u0338',
17959  'NotLessSlantEqual': '\u2A7D\u0338',
17960  'nleqslant': '\u2A7D\u0338',
17961  'nles': '\u2A7D\u0338',
17962  'NotLessTilde': '\u2274',
17963  'nlsim': '\u2274',
17964  'NotNestedGreaterGreater': '\u2AA2\u0338',
17965  'NotNestedLessLess': '\u2AA1\u0338',
17966  'NotPrecedes': '\u2280',
17967  'npr': '\u2280',
17968  'nprec': '\u2280',
17969  'NotPrecedesEqual': '\u2AAF\u0338',
17970  'npre': '\u2AAF\u0338',
17971  'npreceq': '\u2AAF\u0338',
17972  'NotPrecedesSlantEqual': '\u22E0',
17973  'nprcue': '\u22E0',
17974  'NotReverseElement': '\u220C',
17975  'notni': '\u220C',
17976  'notniva': '\u220C',
17977  'NotRightTriangle': '\u22EB',
17978  'nrtri': '\u22EB',
17979  'ntriangleright': '\u22EB',
17980  'NotRightTriangleBar': '\u29D0\u0338',
17981  'NotRightTriangleEqual': '\u22ED',
17982  'nrtrie': '\u22ED',
17983  'ntrianglerighteq': '\u22ED',
17984  'NotSquareSubset': '\u228F\u0338',
17985  'NotSquareSubsetEqual': '\u22E2',
17986  'nsqsube': '\u22E2',
17987  'NotSquareSuperset': '\u2290\u0338',
17988  'NotSquareSupersetEqual': '\u22E3',
17989  'nsqsupe': '\u22E3',
17990  'NotSubset': '\u2282\u20D2',
17991  'nsubset': '\u2282\u20D2',
17992  'vnsub': '\u2282\u20D2',
17993  'NotSubsetEqual': '\u2288',
17994  'nsube': '\u2288',
17995  'nsubseteq': '\u2288',
17996  'NotSucceeds': '\u2281',
17997  'nsc': '\u2281',
17998  'nsucc': '\u2281',
17999  'NotSucceedsEqual': '\u2AB0\u0338',
18000  'nsce': '\u2AB0\u0338',
18001  'nsucceq': '\u2AB0\u0338',
18002  'NotSucceedsSlantEqual': '\u22E1',
18003  'nsccue': '\u22E1',
18004  'NotSucceedsTilde': '\u227F\u0338',
18005  'NotSuperset': '\u2283\u20D2',
18006  'nsupset': '\u2283\u20D2',
18007  'vnsup': '\u2283\u20D2',
18008  'NotSupersetEqual': '\u2289',
18009  'nsupe': '\u2289',
18010  'nsupseteq': '\u2289',
18011  'NotTilde': '\u2241',
18012  'nsim': '\u2241',
18013  'NotTildeEqual': '\u2244',
18014  'nsime': '\u2244',
18015  'nsimeq': '\u2244',
18016  'NotTildeFullEqual': '\u2247',
18017  'ncong': '\u2247',
18018  'NotTildeTilde': '\u2249',
18019  'nap': '\u2249',
18020  'napprox': '\u2249',
18021  'NotVerticalBar': '\u2224',
18022  'nmid': '\u2224',
18023  'nshortmid': '\u2224',
18024  'nsmid': '\u2224',
18025  'Nscr': '\uD835\uDCA9',
18026  'Ntilde': '\u00D1',
18027  'Nu': '\u039D',
18028  'OElig': '\u0152',
18029  'Oacute': '\u00D3',
18030  'Ocirc': '\u00D4',
18031  'Ocy': '\u041E',
18032  'Odblac': '\u0150',
18033  'Ofr': '\uD835\uDD12',
18034  'Ograve': '\u00D2',
18035  'Omacr': '\u014C',
18036  'Omega': '\u03A9',
18037  'ohm': '\u03A9',
18038  'Omicron': '\u039F',
18039  'Oopf': '\uD835\uDD46',
18040  'OpenCurlyDoubleQuote': '\u201C',
18041  'ldquo': '\u201C',
18042  'OpenCurlyQuote': '\u2018',
18043  'lsquo': '\u2018',
18044  'Or': '\u2A54',
18045  'Oscr': '\uD835\uDCAA',
18046  'Oslash': '\u00D8',
18047  'Otilde': '\u00D5',
18048  'Otimes': '\u2A37',
18049  'Ouml': '\u00D6',
18050  'OverBar': '\u203E',
18051  'oline': '\u203E',
18052  'OverBrace': '\u23DE',
18053  'OverBracket': '\u23B4',
18054  'tbrk': '\u23B4',
18055  'OverParenthesis': '\u23DC',
18056  'PartialD': '\u2202',
18057  'part': '\u2202',
18058  'Pcy': '\u041F',
18059  'Pfr': '\uD835\uDD13',
18060  'Phi': '\u03A6',
18061  'Pi': '\u03A0',
18062  'PlusMinus': '\u00B1',
18063  'plusmn': '\u00B1',
18064  'pm': '\u00B1',
18065  'Popf': '\u2119',
18066  'primes': '\u2119',
18067  'Pr': '\u2ABB',
18068  'Precedes': '\u227A',
18069  'pr': '\u227A',
18070  'prec': '\u227A',
18071  'PrecedesEqual': '\u2AAF',
18072  'pre': '\u2AAF',
18073  'preceq': '\u2AAF',
18074  'PrecedesSlantEqual': '\u227C',
18075  'prcue': '\u227C',
18076  'preccurlyeq': '\u227C',
18077  'PrecedesTilde': '\u227E',
18078  'precsim': '\u227E',
18079  'prsim': '\u227E',
18080  'Prime': '\u2033',
18081  'Product': '\u220F',
18082  'prod': '\u220F',
18083  'Proportional': '\u221D',
18084  'prop': '\u221D',
18085  'propto': '\u221D',
18086  'varpropto': '\u221D',
18087  'vprop': '\u221D',
18088  'Pscr': '\uD835\uDCAB',
18089  'Psi': '\u03A8',
18090  'QUOT': '\u0022',
18091  'quot': '\u0022',
18092  'Qfr': '\uD835\uDD14',
18093  'Qopf': '\u211A',
18094  'rationals': '\u211A',
18095  'Qscr': '\uD835\uDCAC',
18096  'RBarr': '\u2910',
18097  'drbkarow': '\u2910',
18098  'REG': '\u00AE',
18099  'circledR': '\u00AE',
18100  'reg': '\u00AE',
18101  'Racute': '\u0154',
18102  'Rang': '\u27EB',
18103  'Rarr': '\u21A0',
18104  'twoheadrightarrow': '\u21A0',
18105  'Rarrtl': '\u2916',
18106  'Rcaron': '\u0158',
18107  'Rcedil': '\u0156',
18108  'Rcy': '\u0420',
18109  'Re': '\u211C',
18110  'Rfr': '\u211C',
18111  'real': '\u211C',
18112  'realpart': '\u211C',
18113  'ReverseElement': '\u220B',
18114  'SuchThat': '\u220B',
18115  'ni': '\u220B',
18116  'niv': '\u220B',
18117  'ReverseEquilibrium': '\u21CB',
18118  'leftrightharpoons': '\u21CB',
18119  'lrhar': '\u21CB',
18120  'ReverseUpEquilibrium': '\u296F',
18121  'duhar': '\u296F',
18122  'Rho': '\u03A1',
18123  'RightAngleBracket': '\u27E9',
18124  'rang': '\u27E9',
18125  'rangle': '\u27E9',
18126  'RightArrow': '\u2192',
18127  'ShortRightArrow': '\u2192',
18128  'rarr': '\u2192',
18129  'rightarrow': '\u2192',
18130  'srarr': '\u2192',
18131  'RightArrowBar': '\u21E5',
18132  'rarrb': '\u21E5',
18133  'RightArrowLeftArrow': '\u21C4',
18134  'rightleftarrows': '\u21C4',
18135  'rlarr': '\u21C4',
18136  'RightCeiling': '\u2309',
18137  'rceil': '\u2309',
18138  'RightDoubleBracket': '\u27E7',
18139  'robrk': '\u27E7',
18140  'RightDownTeeVector': '\u295D',
18141  'RightDownVector': '\u21C2',
18142  'dharr': '\u21C2',
18143  'downharpoonright': '\u21C2',
18144  'RightDownVectorBar': '\u2955',
18145  'RightFloor': '\u230B',
18146  'rfloor': '\u230B',
18147  'RightTee': '\u22A2',
18148  'vdash': '\u22A2',
18149  'RightTeeArrow': '\u21A6',
18150  'map': '\u21A6',
18151  'mapsto': '\u21A6',
18152  'RightTeeVector': '\u295B',
18153  'RightTriangle': '\u22B3',
18154  'vartriangleright': '\u22B3',
18155  'vrtri': '\u22B3',
18156  'RightTriangleBar': '\u29D0',
18157  'RightTriangleEqual': '\u22B5',
18158  'rtrie': '\u22B5',
18159  'trianglerighteq': '\u22B5',
18160  'RightUpDownVector': '\u294F',
18161  'RightUpTeeVector': '\u295C',
18162  'RightUpVector': '\u21BE',
18163  'uharr': '\u21BE',
18164  'upharpoonright': '\u21BE',
18165  'RightUpVectorBar': '\u2954',
18166  'RightVector': '\u21C0',
18167  'rharu': '\u21C0',
18168  'rightharpoonup': '\u21C0',
18169  'RightVectorBar': '\u2953',
18170  'Ropf': '\u211D',
18171  'reals': '\u211D',
18172  'RoundImplies': '\u2970',
18173  'Rrightarrow': '\u21DB',
18174  'rAarr': '\u21DB',
18175  'Rscr': '\u211B',
18176  'realine': '\u211B',
18177  'Rsh': '\u21B1',
18178  'rsh': '\u21B1',
18179  'RuleDelayed': '\u29F4',
18180  'SHCHcy': '\u0429',
18181  'SHcy': '\u0428',
18182  'SOFTcy': '\u042C',
18183  'Sacute': '\u015A',
18184  'Sc': '\u2ABC',
18185  'Scaron': '\u0160',
18186  'Scedil': '\u015E',
18187  'Scirc': '\u015C',
18188  'Scy': '\u0421',
18189  'Sfr': '\uD835\uDD16',
18190  'ShortUpArrow': '\u2191',
18191  'UpArrow': '\u2191',
18192  'uarr': '\u2191',
18193  'uparrow': '\u2191',
18194  'Sigma': '\u03A3',
18195  'SmallCircle': '\u2218',
18196  'compfn': '\u2218',
18197  'Sopf': '\uD835\uDD4A',
18198  'Sqrt': '\u221A',
18199  'radic': '\u221A',
18200  'Square': '\u25A1',
18201  'squ': '\u25A1',
18202  'square': '\u25A1',
18203  'SquareIntersection': '\u2293',
18204  'sqcap': '\u2293',
18205  'SquareSubset': '\u228F',
18206  'sqsub': '\u228F',
18207  'sqsubset': '\u228F',
18208  'SquareSubsetEqual': '\u2291',
18209  'sqsube': '\u2291',
18210  'sqsubseteq': '\u2291',
18211  'SquareSuperset': '\u2290',
18212  'sqsup': '\u2290',
18213  'sqsupset': '\u2290',
18214  'SquareSupersetEqual': '\u2292',
18215  'sqsupe': '\u2292',
18216  'sqsupseteq': '\u2292',
18217  'SquareUnion': '\u2294',
18218  'sqcup': '\u2294',
18219  'Sscr': '\uD835\uDCAE',
18220  'Star': '\u22C6',
18221  'sstarf': '\u22C6',
18222  'Sub': '\u22D0',
18223  'Subset': '\u22D0',
18224  'SubsetEqual': '\u2286',
18225  'sube': '\u2286',
18226  'subseteq': '\u2286',
18227  'Succeeds': '\u227B',
18228  'sc': '\u227B',
18229  'succ': '\u227B',
18230  'SucceedsEqual': '\u2AB0',
18231  'sce': '\u2AB0',
18232  'succeq': '\u2AB0',
18233  'SucceedsSlantEqual': '\u227D',
18234  'sccue': '\u227D',
18235  'succcurlyeq': '\u227D',
18236  'SucceedsTilde': '\u227F',
18237  'scsim': '\u227F',
18238  'succsim': '\u227F',
18239  'Sum': '\u2211',
18240  'sum': '\u2211',
18241  'Sup': '\u22D1',
18242  'Supset': '\u22D1',
18243  'Superset': '\u2283',
18244  'sup': '\u2283',
18245  'supset': '\u2283',
18246  'SupersetEqual': '\u2287',
18247  'supe': '\u2287',
18248  'supseteq': '\u2287',
18249  'THORN': '\u00DE',
18250  'TRADE': '\u2122',
18251  'trade': '\u2122',
18252  'TSHcy': '\u040B',
18253  'TScy': '\u0426',
18254  'Tab': '\u0009',
18255  'Tau': '\u03A4',
18256  'Tcaron': '\u0164',
18257  'Tcedil': '\u0162',
18258  'Tcy': '\u0422',
18259  'Tfr': '\uD835\uDD17',
18260  'Therefore': '\u2234',
18261  'there4': '\u2234',
18262  'therefore': '\u2234',
18263  'Theta': '\u0398',
18264  'ThickSpace': '\u205F\u200A',
18265  'ThinSpace': '\u2009',
18266  'thinsp': '\u2009',
18267  'Tilde': '\u223C',
18268  'sim': '\u223C',
18269  'thicksim': '\u223C',
18270  'thksim': '\u223C',
18271  'TildeEqual': '\u2243',
18272  'sime': '\u2243',
18273  'simeq': '\u2243',
18274  'TildeFullEqual': '\u2245',
18275  'cong': '\u2245',
18276  'TildeTilde': '\u2248',
18277  'ap': '\u2248',
18278  'approx': '\u2248',
18279  'asymp': '\u2248',
18280  'thickapprox': '\u2248',
18281  'thkap': '\u2248',
18282  'Topf': '\uD835\uDD4B',
18283  'TripleDot': '\u20DB',
18284  'tdot': '\u20DB',
18285  'Tscr': '\uD835\uDCAF',
18286  'Tstrok': '\u0166',
18287  'Uacute': '\u00DA',
18288  'Uarr': '\u219F',
18289  'Uarrocir': '\u2949',
18290  'Ubrcy': '\u040E',
18291  'Ubreve': '\u016C',
18292  'Ucirc': '\u00DB',
18293  'Ucy': '\u0423',
18294  'Udblac': '\u0170',
18295  'Ufr': '\uD835\uDD18',
18296  'Ugrave': '\u00D9',
18297  'Umacr': '\u016A',
18298  'UnderBar': '\u005F',
18299  'lowbar': '\u005F',
18300  'UnderBrace': '\u23DF',
18301  'UnderBracket': '\u23B5',
18302  'bbrk': '\u23B5',
18303  'UnderParenthesis': '\u23DD',
18304  'Union': '\u22C3',
18305  'bigcup': '\u22C3',
18306  'xcup': '\u22C3',
18307  'UnionPlus': '\u228E',
18308  'uplus': '\u228E',
18309  'Uogon': '\u0172',
18310  'Uopf': '\uD835\uDD4C',
18311  'UpArrowBar': '\u2912',
18312  'UpArrowDownArrow': '\u21C5',
18313  'udarr': '\u21C5',
18314  'UpDownArrow': '\u2195',
18315  'updownarrow': '\u2195',
18316  'varr': '\u2195',
18317  'UpEquilibrium': '\u296E',
18318  'udhar': '\u296E',
18319  'UpTee': '\u22A5',
18320  'bot': '\u22A5',
18321  'bottom': '\u22A5',
18322  'perp': '\u22A5',
18323  'UpTeeArrow': '\u21A5',
18324  'mapstoup': '\u21A5',
18325  'UpperLeftArrow': '\u2196',
18326  'nwarr': '\u2196',
18327  'nwarrow': '\u2196',
18328  'UpperRightArrow': '\u2197',
18329  'nearr': '\u2197',
18330  'nearrow': '\u2197',
18331  'Upsi': '\u03D2',
18332  'upsih': '\u03D2',
18333  'Upsilon': '\u03A5',
18334  'Uring': '\u016E',
18335  'Uscr': '\uD835\uDCB0',
18336  'Utilde': '\u0168',
18337  'Uuml': '\u00DC',
18338  'VDash': '\u22AB',
18339  'Vbar': '\u2AEB',
18340  'Vcy': '\u0412',
18341  'Vdash': '\u22A9',
18342  'Vdashl': '\u2AE6',
18343  'Vee': '\u22C1',
18344  'bigvee': '\u22C1',
18345  'xvee': '\u22C1',
18346  'Verbar': '\u2016',
18347  'Vert': '\u2016',
18348  'VerticalBar': '\u2223',
18349  'mid': '\u2223',
18350  'shortmid': '\u2223',
18351  'smid': '\u2223',
18352  'VerticalLine': '\u007C',
18353  'verbar': '\u007C',
18354  'vert': '\u007C',
18355  'VerticalSeparator': '\u2758',
18356  'VerticalTilde': '\u2240',
18357  'wr': '\u2240',
18358  'wreath': '\u2240',
18359  'VeryThinSpace': '\u200A',
18360  'hairsp': '\u200A',
18361  'Vfr': '\uD835\uDD19',
18362  'Vopf': '\uD835\uDD4D',
18363  'Vscr': '\uD835\uDCB1',
18364  'Vvdash': '\u22AA',
18365  'Wcirc': '\u0174',
18366  'Wedge': '\u22C0',
18367  'bigwedge': '\u22C0',
18368  'xwedge': '\u22C0',
18369  'Wfr': '\uD835\uDD1A',
18370  'Wopf': '\uD835\uDD4E',
18371  'Wscr': '\uD835\uDCB2',
18372  'Xfr': '\uD835\uDD1B',
18373  'Xi': '\u039E',
18374  'Xopf': '\uD835\uDD4F',
18375  'Xscr': '\uD835\uDCB3',
18376  'YAcy': '\u042F',
18377  'YIcy': '\u0407',
18378  'YUcy': '\u042E',
18379  'Yacute': '\u00DD',
18380  'Ycirc': '\u0176',
18381  'Ycy': '\u042B',
18382  'Yfr': '\uD835\uDD1C',
18383  'Yopf': '\uD835\uDD50',
18384  'Yscr': '\uD835\uDCB4',
18385  'Yuml': '\u0178',
18386  'ZHcy': '\u0416',
18387  'Zacute': '\u0179',
18388  'Zcaron': '\u017D',
18389  'Zcy': '\u0417',
18390  'Zdot': '\u017B',
18391  'Zeta': '\u0396',
18392  'Zfr': '\u2128',
18393  'zeetrf': '\u2128',
18394  'Zopf': '\u2124',
18395  'integers': '\u2124',
18396  'Zscr': '\uD835\uDCB5',
18397  'aacute': '\u00E1',
18398  'abreve': '\u0103',
18399  'ac': '\u223E',
18400  'mstpos': '\u223E',
18401  'acE': '\u223E\u0333',
18402  'acd': '\u223F',
18403  'acirc': '\u00E2',
18404  'acy': '\u0430',
18405  'aelig': '\u00E6',
18406  'afr': '\uD835\uDD1E',
18407  'agrave': '\u00E0',
18408  'alefsym': '\u2135',
18409  'aleph': '\u2135',
18410  'alpha': '\u03B1',
18411  'amacr': '\u0101',
18412  'amalg': '\u2A3F',
18413  'and': '\u2227',
18414  'wedge': '\u2227',
18415  'andand': '\u2A55',
18416  'andd': '\u2A5C',
18417  'andslope': '\u2A58',
18418  'andv': '\u2A5A',
18419  'ang': '\u2220',
18420  'angle': '\u2220',
18421  'ange': '\u29A4',
18422  'angmsd': '\u2221',
18423  'measuredangle': '\u2221',
18424  'angmsdaa': '\u29A8',
18425  'angmsdab': '\u29A9',
18426  'angmsdac': '\u29AA',
18427  'angmsdad': '\u29AB',
18428  'angmsdae': '\u29AC',
18429  'angmsdaf': '\u29AD',
18430  'angmsdag': '\u29AE',
18431  'angmsdah': '\u29AF',
18432  'angrt': '\u221F',
18433  'angrtvb': '\u22BE',
18434  'angrtvbd': '\u299D',
18435  'angsph': '\u2222',
18436  'angzarr': '\u237C',
18437  'aogon': '\u0105',
18438  'aopf': '\uD835\uDD52',
18439  'apE': '\u2A70',
18440  'apacir': '\u2A6F',
18441  'ape': '\u224A',
18442  'approxeq': '\u224A',
18443  'apid': '\u224B',
18444  'apos': '\u0027',
18445  'aring': '\u00E5',
18446  'ascr': '\uD835\uDCB6',
18447  'ast': '\u002A',
18448  'midast': '\u002A',
18449  'atilde': '\u00E3',
18450  'auml': '\u00E4',
18451  'awint': '\u2A11',
18452  'bNot': '\u2AED',
18453  'backcong': '\u224C',
18454  'bcong': '\u224C',
18455  'backepsilon': '\u03F6',
18456  'bepsi': '\u03F6',
18457  'backprime': '\u2035',
18458  'bprime': '\u2035',
18459  'backsim': '\u223D',
18460  'bsim': '\u223D',
18461  'backsimeq': '\u22CD',
18462  'bsime': '\u22CD',
18463  'barvee': '\u22BD',
18464  'barwed': '\u2305',
18465  'barwedge': '\u2305',
18466  'bbrktbrk': '\u23B6',
18467  'bcy': '\u0431',
18468  'bdquo': '\u201E',
18469  'ldquor': '\u201E',
18470  'bemptyv': '\u29B0',
18471  'beta': '\u03B2',
18472  'beth': '\u2136',
18473  'between': '\u226C',
18474  'twixt': '\u226C',
18475  'bfr': '\uD835\uDD1F',
18476  'bigcirc': '\u25EF',
18477  'xcirc': '\u25EF',
18478  'bigodot': '\u2A00',
18479  'xodot': '\u2A00',
18480  'bigoplus': '\u2A01',
18481  'xoplus': '\u2A01',
18482  'bigotimes': '\u2A02',
18483  'xotime': '\u2A02',
18484  'bigsqcup': '\u2A06',
18485  'xsqcup': '\u2A06',
18486  'bigstar': '\u2605',
18487  'starf': '\u2605',
18488  'bigtriangledown': '\u25BD',
18489  'xdtri': '\u25BD',
18490  'bigtriangleup': '\u25B3',
18491  'xutri': '\u25B3',
18492  'biguplus': '\u2A04',
18493  'xuplus': '\u2A04',
18494  'bkarow': '\u290D',
18495  'rbarr': '\u290D',
18496  'blacklozenge': '\u29EB',
18497  'lozf': '\u29EB',
18498  'blacktriangle': '\u25B4',
18499  'utrif': '\u25B4',
18500  'blacktriangledown': '\u25BE',
18501  'dtrif': '\u25BE',
18502  'blacktriangleleft': '\u25C2',
18503  'ltrif': '\u25C2',
18504  'blacktriangleright': '\u25B8',
18505  'rtrif': '\u25B8',
18506  'blank': '\u2423',
18507  'blk12': '\u2592',
18508  'blk14': '\u2591',
18509  'blk34': '\u2593',
18510  'block': '\u2588',
18511  'bne': '\u003D\u20E5',
18512  'bnequiv': '\u2261\u20E5',
18513  'bnot': '\u2310',
18514  'bopf': '\uD835\uDD53',
18515  'bowtie': '\u22C8',
18516  'boxDL': '\u2557',
18517  'boxDR': '\u2554',
18518  'boxDl': '\u2556',
18519  'boxDr': '\u2553',
18520  'boxH': '\u2550',
18521  'boxHD': '\u2566',
18522  'boxHU': '\u2569',
18523  'boxHd': '\u2564',
18524  'boxHu': '\u2567',
18525  'boxUL': '\u255D',
18526  'boxUR': '\u255A',
18527  'boxUl': '\u255C',
18528  'boxUr': '\u2559',
18529  'boxV': '\u2551',
18530  'boxVH': '\u256C',
18531  'boxVL': '\u2563',
18532  'boxVR': '\u2560',
18533  'boxVh': '\u256B',
18534  'boxVl': '\u2562',
18535  'boxVr': '\u255F',
18536  'boxbox': '\u29C9',
18537  'boxdL': '\u2555',
18538  'boxdR': '\u2552',
18539  'boxdl': '\u2510',
18540  'boxdr': '\u250C',
18541  'boxhD': '\u2565',
18542  'boxhU': '\u2568',
18543  'boxhd': '\u252C',
18544  'boxhu': '\u2534',
18545  'boxminus': '\u229F',
18546  'minusb': '\u229F',
18547  'boxplus': '\u229E',
18548  'plusb': '\u229E',
18549  'boxtimes': '\u22A0',
18550  'timesb': '\u22A0',
18551  'boxuL': '\u255B',
18552  'boxuR': '\u2558',
18553  'boxul': '\u2518',
18554  'boxur': '\u2514',
18555  'boxv': '\u2502',
18556  'boxvH': '\u256A',
18557  'boxvL': '\u2561',
18558  'boxvR': '\u255E',
18559  'boxvh': '\u253C',
18560  'boxvl': '\u2524',
18561  'boxvr': '\u251C',
18562  'brvbar': '\u00A6',
18563  'bscr': '\uD835\uDCB7',
18564  'bsemi': '\u204F',
18565  'bsol': '\u005C',
18566  'bsolb': '\u29C5',
18567  'bsolhsub': '\u27C8',
18568  'bull': '\u2022',
18569  'bullet': '\u2022',
18570  'bumpE': '\u2AAE',
18571  'cacute': '\u0107',
18572  'cap': '\u2229',
18573  'capand': '\u2A44',
18574  'capbrcup': '\u2A49',
18575  'capcap': '\u2A4B',
18576  'capcup': '\u2A47',
18577  'capdot': '\u2A40',
18578  'caps': '\u2229\uFE00',
18579  'caret': '\u2041',
18580  'ccaps': '\u2A4D',
18581  'ccaron': '\u010D',
18582  'ccedil': '\u00E7',
18583  'ccirc': '\u0109',
18584  'ccups': '\u2A4C',
18585  'ccupssm': '\u2A50',
18586  'cdot': '\u010B',
18587  'cemptyv': '\u29B2',
18588  'cent': '\u00A2',
18589  'cfr': '\uD835\uDD20',
18590  'chcy': '\u0447',
18591  'check': '\u2713',
18592  'checkmark': '\u2713',
18593  'chi': '\u03C7',
18594  'cir': '\u25CB',
18595  'cirE': '\u29C3',
18596  'circ': '\u02C6',
18597  'circeq': '\u2257',
18598  'cire': '\u2257',
18599  'circlearrowleft': '\u21BA',
18600  'olarr': '\u21BA',
18601  'circlearrowright': '\u21BB',
18602  'orarr': '\u21BB',
18603  'circledS': '\u24C8',
18604  'oS': '\u24C8',
18605  'circledast': '\u229B',
18606  'oast': '\u229B',
18607  'circledcirc': '\u229A',
18608  'ocir': '\u229A',
18609  'circleddash': '\u229D',
18610  'odash': '\u229D',
18611  'cirfnint': '\u2A10',
18612  'cirmid': '\u2AEF',
18613  'cirscir': '\u29C2',
18614  'clubs': '\u2663',
18615  'clubsuit': '\u2663',
18616  'colon': '\u003A',
18617  'comma': '\u002C',
18618  'commat': '\u0040',
18619  'comp': '\u2201',
18620  'complement': '\u2201',
18621  'congdot': '\u2A6D',
18622  'copf': '\uD835\uDD54',
18623  'copysr': '\u2117',
18624  'crarr': '\u21B5',
18625  'cross': '\u2717',
18626  'cscr': '\uD835\uDCB8',
18627  'csub': '\u2ACF',
18628  'csube': '\u2AD1',
18629  'csup': '\u2AD0',
18630  'csupe': '\u2AD2',
18631  'ctdot': '\u22EF',
18632  'cudarrl': '\u2938',
18633  'cudarrr': '\u2935',
18634  'cuepr': '\u22DE',
18635  'curlyeqprec': '\u22DE',
18636  'cuesc': '\u22DF',
18637  'curlyeqsucc': '\u22DF',
18638  'cularr': '\u21B6',
18639  'curvearrowleft': '\u21B6',
18640  'cularrp': '\u293D',
18641  'cup': '\u222A',
18642  'cupbrcap': '\u2A48',
18643  'cupcap': '\u2A46',
18644  'cupcup': '\u2A4A',
18645  'cupdot': '\u228D',
18646  'cupor': '\u2A45',
18647  'cups': '\u222A\uFE00',
18648  'curarr': '\u21B7',
18649  'curvearrowright': '\u21B7',
18650  'curarrm': '\u293C',
18651  'curlyvee': '\u22CE',
18652  'cuvee': '\u22CE',
18653  'curlywedge': '\u22CF',
18654  'cuwed': '\u22CF',
18655  'curren': '\u00A4',
18656  'cwint': '\u2231',
18657  'cylcty': '\u232D',
18658  'dHar': '\u2965',
18659  'dagger': '\u2020',
18660  'daleth': '\u2138',
18661  'dash': '\u2010',
18662  'hyphen': '\u2010',
18663  'dbkarow': '\u290F',
18664  'rBarr': '\u290F',
18665  'dcaron': '\u010F',
18666  'dcy': '\u0434',
18667  'ddarr': '\u21CA',
18668  'downdownarrows': '\u21CA',
18669  'ddotseq': '\u2A77',
18670  'eDDot': '\u2A77',
18671  'deg': '\u00B0',
18672  'delta': '\u03B4',
18673  'demptyv': '\u29B1',
18674  'dfisht': '\u297F',
18675  'dfr': '\uD835\uDD21',
18676  'diamondsuit': '\u2666',
18677  'diams': '\u2666',
18678  'digamma': '\u03DD',
18679  'gammad': '\u03DD',
18680  'disin': '\u22F2',
18681  'div': '\u00F7',
18682  'divide': '\u00F7',
18683  'divideontimes': '\u22C7',
18684  'divonx': '\u22C7',
18685  'djcy': '\u0452',
18686  'dlcorn': '\u231E',
18687  'llcorner': '\u231E',
18688  'dlcrop': '\u230D',
18689  'dollar': '\u0024',
18690  'dopf': '\uD835\uDD55',
18691  'doteqdot': '\u2251',
18692  'eDot': '\u2251',
18693  'dotminus': '\u2238',
18694  'minusd': '\u2238',
18695  'dotplus': '\u2214',
18696  'plusdo': '\u2214',
18697  'dotsquare': '\u22A1',
18698  'sdotb': '\u22A1',
18699  'drcorn': '\u231F',
18700  'lrcorner': '\u231F',
18701  'drcrop': '\u230C',
18702  'dscr': '\uD835\uDCB9',
18703  'dscy': '\u0455',
18704  'dsol': '\u29F6',
18705  'dstrok': '\u0111',
18706  'dtdot': '\u22F1',
18707  'dtri': '\u25BF',
18708  'triangledown': '\u25BF',
18709  'dwangle': '\u29A6',
18710  'dzcy': '\u045F',
18711  'dzigrarr': '\u27FF',
18712  'eacute': '\u00E9',
18713  'easter': '\u2A6E',
18714  'ecaron': '\u011B',
18715  'ecir': '\u2256',
18716  'eqcirc': '\u2256',
18717  'ecirc': '\u00EA',
18718  'ecolon': '\u2255',
18719  'eqcolon': '\u2255',
18720  'ecy': '\u044D',
18721  'edot': '\u0117',
18722  'efDot': '\u2252',
18723  'fallingdotseq': '\u2252',
18724  'efr': '\uD835\uDD22',
18725  'eg': '\u2A9A',
18726  'egrave': '\u00E8',
18727  'egs': '\u2A96',
18728  'eqslantgtr': '\u2A96',
18729  'egsdot': '\u2A98',
18730  'el': '\u2A99',
18731  'elinters': '\u23E7',
18732  'ell': '\u2113',
18733  'els': '\u2A95',
18734  'eqslantless': '\u2A95',
18735  'elsdot': '\u2A97',
18736  'emacr': '\u0113',
18737  'empty': '\u2205',
18738  'emptyset': '\u2205',
18739  'emptyv': '\u2205',
18740  'varnothing': '\u2205',
18741  'emsp13': '\u2004',
18742  'emsp14': '\u2005',
18743  'emsp': '\u2003',
18744  'eng': '\u014B',
18745  'ensp': '\u2002',
18746  'eogon': '\u0119',
18747  'eopf': '\uD835\uDD56',
18748  'epar': '\u22D5',
18749  'eparsl': '\u29E3',
18750  'eplus': '\u2A71',
18751  'epsi': '\u03B5',
18752  'epsilon': '\u03B5',
18753  'epsiv': '\u03F5',
18754  'straightepsilon': '\u03F5',
18755  'varepsilon': '\u03F5',
18756  'equals': '\u003D',
18757  'equest': '\u225F',
18758  'questeq': '\u225F',
18759  'equivDD': '\u2A78',
18760  'eqvparsl': '\u29E5',
18761  'erDot': '\u2253',
18762  'risingdotseq': '\u2253',
18763  'erarr': '\u2971',
18764  'escr': '\u212F',
18765  'eta': '\u03B7',
18766  'eth': '\u00F0',
18767  'euml': '\u00EB',
18768  'euro': '\u20AC',
18769  'excl': '\u0021',
18770  'fcy': '\u0444',
18771  'female': '\u2640',
18772  'ffilig': '\uFB03',
18773  'fflig': '\uFB00',
18774  'ffllig': '\uFB04',
18775  'ffr': '\uD835\uDD23',
18776  'filig': '\uFB01',
18777  'fjlig': '\u0066\u006A',
18778  'flat': '\u266D',
18779  'fllig': '\uFB02',
18780  'fltns': '\u25B1',
18781  'fnof': '\u0192',
18782  'fopf': '\uD835\uDD57',
18783  'fork': '\u22D4',
18784  'pitchfork': '\u22D4',
18785  'forkv': '\u2AD9',
18786  'fpartint': '\u2A0D',
18787  'frac12': '\u00BD',
18788  'half': '\u00BD',
18789  'frac13': '\u2153',
18790  'frac14': '\u00BC',
18791  'frac15': '\u2155',
18792  'frac16': '\u2159',
18793  'frac18': '\u215B',
18794  'frac23': '\u2154',
18795  'frac25': '\u2156',
18796  'frac34': '\u00BE',
18797  'frac35': '\u2157',
18798  'frac38': '\u215C',
18799  'frac45': '\u2158',
18800  'frac56': '\u215A',
18801  'frac58': '\u215D',
18802  'frac78': '\u215E',
18803  'frasl': '\u2044',
18804  'frown': '\u2322',
18805  'sfrown': '\u2322',
18806  'fscr': '\uD835\uDCBB',
18807  'gEl': '\u2A8C',
18808  'gtreqqless': '\u2A8C',
18809  'gacute': '\u01F5',
18810  'gamma': '\u03B3',
18811  'gap': '\u2A86',
18812  'gtrapprox': '\u2A86',
18813  'gbreve': '\u011F',
18814  'gcirc': '\u011D',
18815  'gcy': '\u0433',
18816  'gdot': '\u0121',
18817  'gescc': '\u2AA9',
18818  'gesdot': '\u2A80',
18819  'gesdoto': '\u2A82',
18820  'gesdotol': '\u2A84',
18821  'gesl': '\u22DB\uFE00',
18822  'gesles': '\u2A94',
18823  'gfr': '\uD835\uDD24',
18824  'gimel': '\u2137',
18825  'gjcy': '\u0453',
18826  'glE': '\u2A92',
18827  'gla': '\u2AA5',
18828  'glj': '\u2AA4',
18829  'gnE': '\u2269',
18830  'gneqq': '\u2269',
18831  'gnap': '\u2A8A',
18832  'gnapprox': '\u2A8A',
18833  'gne': '\u2A88',
18834  'gneq': '\u2A88',
18835  'gnsim': '\u22E7',
18836  'gopf': '\uD835\uDD58',
18837  'gscr': '\u210A',
18838  'gsime': '\u2A8E',
18839  'gsiml': '\u2A90',
18840  'gtcc': '\u2AA7',
18841  'gtcir': '\u2A7A',
18842  'gtdot': '\u22D7',
18843  'gtrdot': '\u22D7',
18844  'gtlPar': '\u2995',
18845  'gtquest': '\u2A7C',
18846  'gtrarr': '\u2978',
18847  'gvertneqq': '\u2269\uFE00',
18848  'gvnE': '\u2269\uFE00',
18849  'hardcy': '\u044A',
18850  'harrcir': '\u2948',
18851  'harrw': '\u21AD',
18852  'leftrightsquigarrow': '\u21AD',
18853  'hbar': '\u210F',
18854  'hslash': '\u210F',
18855  'planck': '\u210F',
18856  'plankv': '\u210F',
18857  'hcirc': '\u0125',
18858  'hearts': '\u2665',
18859  'heartsuit': '\u2665',
18860  'hellip': '\u2026',
18861  'mldr': '\u2026',
18862  'hercon': '\u22B9',
18863  'hfr': '\uD835\uDD25',
18864  'hksearow': '\u2925',
18865  'searhk': '\u2925',
18866  'hkswarow': '\u2926',
18867  'swarhk': '\u2926',
18868  'hoarr': '\u21FF',
18869  'homtht': '\u223B',
18870  'hookleftarrow': '\u21A9',
18871  'larrhk': '\u21A9',
18872  'hookrightarrow': '\u21AA',
18873  'rarrhk': '\u21AA',
18874  'hopf': '\uD835\uDD59',
18875  'horbar': '\u2015',
18876  'hscr': '\uD835\uDCBD',
18877  'hstrok': '\u0127',
18878  'hybull': '\u2043',
18879  'iacute': '\u00ED',
18880  'icirc': '\u00EE',
18881  'icy': '\u0438',
18882  'iecy': '\u0435',
18883  'iexcl': '\u00A1',
18884  'ifr': '\uD835\uDD26',
18885  'igrave': '\u00EC',
18886  'iiiint': '\u2A0C',
18887  'qint': '\u2A0C',
18888  'iiint': '\u222D',
18889  'tint': '\u222D',
18890  'iinfin': '\u29DC',
18891  'iiota': '\u2129',
18892  'ijlig': '\u0133',
18893  'imacr': '\u012B',
18894  'imath': '\u0131',
18895  'inodot': '\u0131',
18896  'imof': '\u22B7',
18897  'imped': '\u01B5',
18898  'incare': '\u2105',
18899  'infin': '\u221E',
18900  'infintie': '\u29DD',
18901  'intcal': '\u22BA',
18902  'intercal': '\u22BA',
18903  'intlarhk': '\u2A17',
18904  'intprod': '\u2A3C',
18905  'iprod': '\u2A3C',
18906  'iocy': '\u0451',
18907  'iogon': '\u012F',
18908  'iopf': '\uD835\uDD5A',
18909  'iota': '\u03B9',
18910  'iquest': '\u00BF',
18911  'iscr': '\uD835\uDCBE',
18912  'isinE': '\u22F9',
18913  'isindot': '\u22F5',
18914  'isins': '\u22F4',
18915  'isinsv': '\u22F3',
18916  'itilde': '\u0129',
18917  'iukcy': '\u0456',
18918  'iuml': '\u00EF',
18919  'jcirc': '\u0135',
18920  'jcy': '\u0439',
18921  'jfr': '\uD835\uDD27',
18922  'jmath': '\u0237',
18923  'jopf': '\uD835\uDD5B',
18924  'jscr': '\uD835\uDCBF',
18925  'jsercy': '\u0458',
18926  'jukcy': '\u0454',
18927  'kappa': '\u03BA',
18928  'kappav': '\u03F0',
18929  'varkappa': '\u03F0',
18930  'kcedil': '\u0137',
18931  'kcy': '\u043A',
18932  'kfr': '\uD835\uDD28',
18933  'kgreen': '\u0138',
18934  'khcy': '\u0445',
18935  'kjcy': '\u045C',
18936  'kopf': '\uD835\uDD5C',
18937  'kscr': '\uD835\uDCC0',
18938  'lAtail': '\u291B',
18939  'lBarr': '\u290E',
18940  'lEg': '\u2A8B',
18941  'lesseqqgtr': '\u2A8B',
18942  'lHar': '\u2962',
18943  'lacute': '\u013A',
18944  'laemptyv': '\u29B4',
18945  'lambda': '\u03BB',
18946  'langd': '\u2991',
18947  'lap': '\u2A85',
18948  'lessapprox': '\u2A85',
18949  'laquo': '\u00AB',
18950  'larrbfs': '\u291F',
18951  'larrfs': '\u291D',
18952  'larrlp': '\u21AB',
18953  'looparrowleft': '\u21AB',
18954  'larrpl': '\u2939',
18955  'larrsim': '\u2973',
18956  'larrtl': '\u21A2',
18957  'leftarrowtail': '\u21A2',
18958  'lat': '\u2AAB',
18959  'latail': '\u2919',
18960  'late': '\u2AAD',
18961  'lates': '\u2AAD\uFE00',
18962  'lbarr': '\u290C',
18963  'lbbrk': '\u2772',
18964  'lbrace': '\u007B',
18965  'lcub': '\u007B',
18966  'lbrack': '\u005B',
18967  'lsqb': '\u005B',
18968  'lbrke': '\u298B',
18969  'lbrksld': '\u298F',
18970  'lbrkslu': '\u298D',
18971  'lcaron': '\u013E',
18972  'lcedil': '\u013C',
18973  'lcy': '\u043B',
18974  'ldca': '\u2936',
18975  'ldrdhar': '\u2967',
18976  'ldrushar': '\u294B',
18977  'ldsh': '\u21B2',
18978  'le': '\u2264',
18979  'leq': '\u2264',
18980  'leftleftarrows': '\u21C7',
18981  'llarr': '\u21C7',
18982  'leftthreetimes': '\u22CB',
18983  'lthree': '\u22CB',
18984  'lescc': '\u2AA8',
18985  'lesdot': '\u2A7F',
18986  'lesdoto': '\u2A81',
18987  'lesdotor': '\u2A83',
18988  'lesg': '\u22DA\uFE00',
18989  'lesges': '\u2A93',
18990  'lessdot': '\u22D6',
18991  'ltdot': '\u22D6',
18992  'lfisht': '\u297C',
18993  'lfr': '\uD835\uDD29',
18994  'lgE': '\u2A91',
18995  'lharul': '\u296A',
18996  'lhblk': '\u2584',
18997  'ljcy': '\u0459',
18998  'llhard': '\u296B',
18999  'lltri': '\u25FA',
19000  'lmidot': '\u0140',
19001  'lmoust': '\u23B0',
19002  'lmoustache': '\u23B0',
19003  'lnE': '\u2268',
19004  'lneqq': '\u2268',
19005  'lnap': '\u2A89',
19006  'lnapprox': '\u2A89',
19007  'lne': '\u2A87',
19008  'lneq': '\u2A87',
19009  'lnsim': '\u22E6',
19010  'loang': '\u27EC',
19011  'loarr': '\u21FD',
19012  'longmapsto': '\u27FC',
19013  'xmap': '\u27FC',
19014  'looparrowright': '\u21AC',
19015  'rarrlp': '\u21AC',
19016  'lopar': '\u2985',
19017  'lopf': '\uD835\uDD5D',
19018  'loplus': '\u2A2D',
19019  'lotimes': '\u2A34',
19020  'lowast': '\u2217',
19021  'loz': '\u25CA',
19022  'lozenge': '\u25CA',
19023  'lpar': '\u0028',
19024  'lparlt': '\u2993',
19025  'lrhard': '\u296D',
19026  'lrm': '\u200E',
19027  'lrtri': '\u22BF',
19028  'lsaquo': '\u2039',
19029  'lscr': '\uD835\uDCC1',
19030  'lsime': '\u2A8D',
19031  'lsimg': '\u2A8F',
19032  'lsquor': '\u201A',
19033  'sbquo': '\u201A',
19034  'lstrok': '\u0142',
19035  'ltcc': '\u2AA6',
19036  'ltcir': '\u2A79',
19037  'ltimes': '\u22C9',
19038  'ltlarr': '\u2976',
19039  'ltquest': '\u2A7B',
19040  'ltrPar': '\u2996',
19041  'ltri': '\u25C3',
19042  'triangleleft': '\u25C3',
19043  'lurdshar': '\u294A',
19044  'luruhar': '\u2966',
19045  'lvertneqq': '\u2268\uFE00',
19046  'lvnE': '\u2268\uFE00',
19047  'mDDot': '\u223A',
19048  'macr': '\u00AF',
19049  'strns': '\u00AF',
19050  'male': '\u2642',
19051  'malt': '\u2720',
19052  'maltese': '\u2720',
19053  'marker': '\u25AE',
19054  'mcomma': '\u2A29',
19055  'mcy': '\u043C',
19056  'mdash': '\u2014',
19057  'mfr': '\uD835\uDD2A',
19058  'mho': '\u2127',
19059  'micro': '\u00B5',
19060  'midcir': '\u2AF0',
19061  'minus': '\u2212',
19062  'minusdu': '\u2A2A',
19063  'mlcp': '\u2ADB',
19064  'models': '\u22A7',
19065  'mopf': '\uD835\uDD5E',
19066  'mscr': '\uD835\uDCC2',
19067  'mu': '\u03BC',
19068  'multimap': '\u22B8',
19069  'mumap': '\u22B8',
19070  'nGg': '\u22D9\u0338',
19071  'nGt': '\u226B\u20D2',
19072  'nLeftarrow': '\u21CD',
19073  'nlArr': '\u21CD',
19074  'nLeftrightarrow': '\u21CE',
19075  'nhArr': '\u21CE',
19076  'nLl': '\u22D8\u0338',
19077  'nLt': '\u226A\u20D2',
19078  'nRightarrow': '\u21CF',
19079  'nrArr': '\u21CF',
19080  'nVDash': '\u22AF',
19081  'nVdash': '\u22AE',
19082  'nacute': '\u0144',
19083  'nang': '\u2220\u20D2',
19084  'napE': '\u2A70\u0338',
19085  'napid': '\u224B\u0338',
19086  'napos': '\u0149',
19087  'natur': '\u266E',
19088  'natural': '\u266E',
19089  'ncap': '\u2A43',
19090  'ncaron': '\u0148',
19091  'ncedil': '\u0146',
19092  'ncongdot': '\u2A6D\u0338',
19093  'ncup': '\u2A42',
19094  'ncy': '\u043D',
19095  'ndash': '\u2013',
19096  'neArr': '\u21D7',
19097  'nearhk': '\u2924',
19098  'nedot': '\u2250\u0338',
19099  'nesear': '\u2928',
19100  'toea': '\u2928',
19101  'nfr': '\uD835\uDD2B',
19102  'nharr': '\u21AE',
19103  'nleftrightarrow': '\u21AE',
19104  'nhpar': '\u2AF2',
19105  'nis': '\u22FC',
19106  'nisd': '\u22FA',
19107  'njcy': '\u045A',
19108  'nlE': '\u2266\u0338',
19109  'nleqq': '\u2266\u0338',
19110  'nlarr': '\u219A',
19111  'nleftarrow': '\u219A',
19112  'nldr': '\u2025',
19113  'nopf': '\uD835\uDD5F',
19114  'not': '\u00AC',
19115  'notinE': '\u22F9\u0338',
19116  'notindot': '\u22F5\u0338',
19117  'notinvb': '\u22F7',
19118  'notinvc': '\u22F6',
19119  'notnivb': '\u22FE',
19120  'notnivc': '\u22FD',
19121  'nparsl': '\u2AFD\u20E5',
19122  'npart': '\u2202\u0338',
19123  'npolint': '\u2A14',
19124  'nrarr': '\u219B',
19125  'nrightarrow': '\u219B',
19126  'nrarrc': '\u2933\u0338',
19127  'nrarrw': '\u219D\u0338',
19128  'nscr': '\uD835\uDCC3',
19129  'nsub': '\u2284',
19130  'nsubE': '\u2AC5\u0338',
19131  'nsubseteqq': '\u2AC5\u0338',
19132  'nsup': '\u2285',
19133  'nsupE': '\u2AC6\u0338',
19134  'nsupseteqq': '\u2AC6\u0338',
19135  'ntilde': '\u00F1',
19136  'nu': '\u03BD',
19137  'num': '\u0023',
19138  'numero': '\u2116',
19139  'numsp': '\u2007',
19140  'nvDash': '\u22AD',
19141  'nvHarr': '\u2904',
19142  'nvap': '\u224D\u20D2',
19143  'nvdash': '\u22AC',
19144  'nvge': '\u2265\u20D2',
19145  'nvgt': '\u003E\u20D2',
19146  'nvinfin': '\u29DE',
19147  'nvlArr': '\u2902',
19148  'nvle': '\u2264\u20D2',
19149  'nvlt': '\u003C\u20D2',
19150  'nvltrie': '\u22B4\u20D2',
19151  'nvrArr': '\u2903',
19152  'nvrtrie': '\u22B5\u20D2',
19153  'nvsim': '\u223C\u20D2',
19154  'nwArr': '\u21D6',
19155  'nwarhk': '\u2923',
19156  'nwnear': '\u2927',
19157  'oacute': '\u00F3',
19158  'ocirc': '\u00F4',
19159  'ocy': '\u043E',
19160  'odblac': '\u0151',
19161  'odiv': '\u2A38',
19162  'odsold': '\u29BC',
19163  'oelig': '\u0153',
19164  'ofcir': '\u29BF',
19165  'ofr': '\uD835\uDD2C',
19166  'ogon': '\u02DB',
19167  'ograve': '\u00F2',
19168  'ogt': '\u29C1',
19169  'ohbar': '\u29B5',
19170  'olcir': '\u29BE',
19171  'olcross': '\u29BB',
19172  'olt': '\u29C0',
19173  'omacr': '\u014D',
19174  'omega': '\u03C9',
19175  'omicron': '\u03BF',
19176  'omid': '\u29B6',
19177  'oopf': '\uD835\uDD60',
19178  'opar': '\u29B7',
19179  'operp': '\u29B9',
19180  'or': '\u2228',
19181  'vee': '\u2228',
19182  'ord': '\u2A5D',
19183  'order': '\u2134',
19184  'orderof': '\u2134',
19185  'oscr': '\u2134',
19186  'ordf': '\u00AA',
19187  'ordm': '\u00BA',
19188  'origof': '\u22B6',
19189  'oror': '\u2A56',
19190  'orslope': '\u2A57',
19191  'orv': '\u2A5B',
19192  'oslash': '\u00F8',
19193  'osol': '\u2298',
19194  'otilde': '\u00F5',
19195  'otimesas': '\u2A36',
19196  'ouml': '\u00F6',
19197  'ovbar': '\u233D',
19198  'para': '\u00B6',
19199  'parsim': '\u2AF3',
19200  'parsl': '\u2AFD',
19201  'pcy': '\u043F',
19202  'percnt': '\u0025',
19203  'period': '\u002E',
19204  'permil': '\u2030',
19205  'pertenk': '\u2031',
19206  'pfr': '\uD835\uDD2D',
19207  'phi': '\u03C6',
19208  'phiv': '\u03D5',
19209  'straightphi': '\u03D5',
19210  'varphi': '\u03D5',
19211  'phone': '\u260E',
19212  'pi': '\u03C0',
19213  'piv': '\u03D6',
19214  'varpi': '\u03D6',
19215  'planckh': '\u210E',
19216  'plus': '\u002B',
19217  'plusacir': '\u2A23',
19218  'pluscir': '\u2A22',
19219  'plusdu': '\u2A25',
19220  'pluse': '\u2A72',
19221  'plussim': '\u2A26',
19222  'plustwo': '\u2A27',
19223  'pointint': '\u2A15',
19224  'popf': '\uD835\uDD61',
19225  'pound': '\u00A3',
19226  'prE': '\u2AB3',
19227  'prap': '\u2AB7',
19228  'precapprox': '\u2AB7',
19229  'precnapprox': '\u2AB9',
19230  'prnap': '\u2AB9',
19231  'precneqq': '\u2AB5',
19232  'prnE': '\u2AB5',
19233  'precnsim': '\u22E8',
19234  'prnsim': '\u22E8',
19235  'prime': '\u2032',
19236  'profalar': '\u232E',
19237  'profline': '\u2312',
19238  'profsurf': '\u2313',
19239  'prurel': '\u22B0',
19240  'pscr': '\uD835\uDCC5',
19241  'psi': '\u03C8',
19242  'puncsp': '\u2008',
19243  'qfr': '\uD835\uDD2E',
19244  'qopf': '\uD835\uDD62',
19245  'qprime': '\u2057',
19246  'qscr': '\uD835\uDCC6',
19247  'quatint': '\u2A16',
19248  'quest': '\u003F',
19249  'rAtail': '\u291C',
19250  'rHar': '\u2964',
19251  'race': '\u223D\u0331',
19252  'racute': '\u0155',
19253  'raemptyv': '\u29B3',
19254  'rangd': '\u2992',
19255  'range': '\u29A5',
19256  'raquo': '\u00BB',
19257  'rarrap': '\u2975',
19258  'rarrbfs': '\u2920',
19259  'rarrc': '\u2933',
19260  'rarrfs': '\u291E',
19261  'rarrpl': '\u2945',
19262  'rarrsim': '\u2974',
19263  'rarrtl': '\u21A3',
19264  'rightarrowtail': '\u21A3',
19265  'rarrw': '\u219D',
19266  'rightsquigarrow': '\u219D',
19267  'ratail': '\u291A',
19268  'ratio': '\u2236',
19269  'rbbrk': '\u2773',
19270  'rbrace': '\u007D',
19271  'rcub': '\u007D',
19272  'rbrack': '\u005D',
19273  'rsqb': '\u005D',
19274  'rbrke': '\u298C',
19275  'rbrksld': '\u298E',
19276  'rbrkslu': '\u2990',
19277  'rcaron': '\u0159',
19278  'rcedil': '\u0157',
19279  'rcy': '\u0440',
19280  'rdca': '\u2937',
19281  'rdldhar': '\u2969',
19282  'rdsh': '\u21B3',
19283  'rect': '\u25AD',
19284  'rfisht': '\u297D',
19285  'rfr': '\uD835\uDD2F',
19286  'rharul': '\u296C',
19287  'rho': '\u03C1',
19288  'rhov': '\u03F1',
19289  'varrho': '\u03F1',
19290  'rightrightarrows': '\u21C9',
19291  'rrarr': '\u21C9',
19292  'rightthreetimes': '\u22CC',
19293  'rthree': '\u22CC',
19294  'ring': '\u02DA',
19295  'rlm': '\u200F',
19296  'rmoust': '\u23B1',
19297  'rmoustache': '\u23B1',
19298  'rnmid': '\u2AEE',
19299  'roang': '\u27ED',
19300  'roarr': '\u21FE',
19301  'ropar': '\u2986',
19302  'ropf': '\uD835\uDD63',
19303  'roplus': '\u2A2E',
19304  'rotimes': '\u2A35',
19305  'rpar': '\u0029',
19306  'rpargt': '\u2994',
19307  'rppolint': '\u2A12',
19308  'rsaquo': '\u203A',
19309  'rscr': '\uD835\uDCC7',
19310  'rtimes': '\u22CA',
19311  'rtri': '\u25B9',
19312  'triangleright': '\u25B9',
19313  'rtriltri': '\u29CE',
19314  'ruluhar': '\u2968',
19315  'rx': '\u211E',
19316  'sacute': '\u015B',
19317  'scE': '\u2AB4',
19318  'scap': '\u2AB8',
19319  'succapprox': '\u2AB8',
19320  'scaron': '\u0161',
19321  'scedil': '\u015F',
19322  'scirc': '\u015D',
19323  'scnE': '\u2AB6',
19324  'succneqq': '\u2AB6',
19325  'scnap': '\u2ABA',
19326  'succnapprox': '\u2ABA',
19327  'scnsim': '\u22E9',
19328  'succnsim': '\u22E9',
19329  'scpolint': '\u2A13',
19330  'scy': '\u0441',
19331  'sdot': '\u22C5',
19332  'sdote': '\u2A66',
19333  'seArr': '\u21D8',
19334  'sect': '\u00A7',
19335  'semi': '\u003B',
19336  'seswar': '\u2929',
19337  'tosa': '\u2929',
19338  'sext': '\u2736',
19339  'sfr': '\uD835\uDD30',
19340  'sharp': '\u266F',
19341  'shchcy': '\u0449',
19342  'shcy': '\u0448',
19343  'shy': '\u00AD',
19344  'sigma': '\u03C3',
19345  'sigmaf': '\u03C2',
19346  'sigmav': '\u03C2',
19347  'varsigma': '\u03C2',
19348  'simdot': '\u2A6A',
19349  'simg': '\u2A9E',
19350  'simgE': '\u2AA0',
19351  'siml': '\u2A9D',
19352  'simlE': '\u2A9F',
19353  'simne': '\u2246',
19354  'simplus': '\u2A24',
19355  'simrarr': '\u2972',
19356  'smashp': '\u2A33',
19357  'smeparsl': '\u29E4',
19358  'smile': '\u2323',
19359  'ssmile': '\u2323',
19360  'smt': '\u2AAA',
19361  'smte': '\u2AAC',
19362  'smtes': '\u2AAC\uFE00',
19363  'softcy': '\u044C',
19364  'sol': '\u002F',
19365  'solb': '\u29C4',
19366  'solbar': '\u233F',
19367  'sopf': '\uD835\uDD64',
19368  'spades': '\u2660',
19369  'spadesuit': '\u2660',
19370  'sqcaps': '\u2293\uFE00',
19371  'sqcups': '\u2294\uFE00',
19372  'sscr': '\uD835\uDCC8',
19373  'star': '\u2606',
19374  'sub': '\u2282',
19375  'subset': '\u2282',
19376  'subE': '\u2AC5',
19377  'subseteqq': '\u2AC5',
19378  'subdot': '\u2ABD',
19379  'subedot': '\u2AC3',
19380  'submult': '\u2AC1',
19381  'subnE': '\u2ACB',
19382  'subsetneqq': '\u2ACB',
19383  'subne': '\u228A',
19384  'subsetneq': '\u228A',
19385  'subplus': '\u2ABF',
19386  'subrarr': '\u2979',
19387  'subsim': '\u2AC7',
19388  'subsub': '\u2AD5',
19389  'subsup': '\u2AD3',
19390  'sung': '\u266A',
19391  'sup1': '\u00B9',
19392  'sup2': '\u00B2',
19393  'sup3': '\u00B3',
19394  'supE': '\u2AC6',
19395  'supseteqq': '\u2AC6',
19396  'supdot': '\u2ABE',
19397  'supdsub': '\u2AD8',
19398  'supedot': '\u2AC4',
19399  'suphsol': '\u27C9',
19400  'suphsub': '\u2AD7',
19401  'suplarr': '\u297B',
19402  'supmult': '\u2AC2',
19403  'supnE': '\u2ACC',
19404  'supsetneqq': '\u2ACC',
19405  'supne': '\u228B',
19406  'supsetneq': '\u228B',
19407  'supplus': '\u2AC0',
19408  'supsim': '\u2AC8',
19409  'supsub': '\u2AD4',
19410  'supsup': '\u2AD6',
19411  'swArr': '\u21D9',
19412  'swnwar': '\u292A',
19413  'szlig': '\u00DF',
19414  'target': '\u2316',
19415  'tau': '\u03C4',
19416  'tcaron': '\u0165',
19417  'tcedil': '\u0163',
19418  'tcy': '\u0442',
19419  'telrec': '\u2315',
19420  'tfr': '\uD835\uDD31',
19421  'theta': '\u03B8',
19422  'thetasym': '\u03D1',
19423  'thetav': '\u03D1',
19424  'vartheta': '\u03D1',
19425  'thorn': '\u00FE',
19426  'times': '\u00D7',
19427  'timesbar': '\u2A31',
19428  'timesd': '\u2A30',
19429  'topbot': '\u2336',
19430  'topcir': '\u2AF1',
19431  'topf': '\uD835\uDD65',
19432  'topfork': '\u2ADA',
19433  'tprime': '\u2034',
19434  'triangle': '\u25B5',
19435  'utri': '\u25B5',
19436  'triangleq': '\u225C',
19437  'trie': '\u225C',
19438  'tridot': '\u25EC',
19439  'triminus': '\u2A3A',
19440  'triplus': '\u2A39',
19441  'trisb': '\u29CD',
19442  'tritime': '\u2A3B',
19443  'trpezium': '\u23E2',
19444  'tscr': '\uD835\uDCC9',
19445  'tscy': '\u0446',
19446  'tshcy': '\u045B',
19447  'tstrok': '\u0167',
19448  'uHar': '\u2963',
19449  'uacute': '\u00FA',
19450  'ubrcy': '\u045E',
19451  'ubreve': '\u016D',
19452  'ucirc': '\u00FB',
19453  'ucy': '\u0443',
19454  'udblac': '\u0171',
19455  'ufisht': '\u297E',
19456  'ufr': '\uD835\uDD32',
19457  'ugrave': '\u00F9',
19458  'uhblk': '\u2580',
19459  'ulcorn': '\u231C',
19460  'ulcorner': '\u231C',
19461  'ulcrop': '\u230F',
19462  'ultri': '\u25F8',
19463  'umacr': '\u016B',
19464  'uogon': '\u0173',
19465  'uopf': '\uD835\uDD66',
19466  'upsi': '\u03C5',
19467  'upsilon': '\u03C5',
19468  'upuparrows': '\u21C8',
19469  'uuarr': '\u21C8',
19470  'urcorn': '\u231D',
19471  'urcorner': '\u231D',
19472  'urcrop': '\u230E',
19473  'uring': '\u016F',
19474  'urtri': '\u25F9',
19475  'uscr': '\uD835\uDCCA',
19476  'utdot': '\u22F0',
19477  'utilde': '\u0169',
19478  'uuml': '\u00FC',
19479  'uwangle': '\u29A7',
19480  'vBar': '\u2AE8',
19481  'vBarv': '\u2AE9',
19482  'vangrt': '\u299C',
19483  'varsubsetneq': '\u228A\uFE00',
19484  'vsubne': '\u228A\uFE00',
19485  'varsubsetneqq': '\u2ACB\uFE00',
19486  'vsubnE': '\u2ACB\uFE00',
19487  'varsupsetneq': '\u228B\uFE00',
19488  'vsupne': '\u228B\uFE00',
19489  'varsupsetneqq': '\u2ACC\uFE00',
19490  'vsupnE': '\u2ACC\uFE00',
19491  'vcy': '\u0432',
19492  'veebar': '\u22BB',
19493  'veeeq': '\u225A',
19494  'vellip': '\u22EE',
19495  'vfr': '\uD835\uDD33',
19496  'vopf': '\uD835\uDD67',
19497  'vscr': '\uD835\uDCCB',
19498  'vzigzag': '\u299A',
19499  'wcirc': '\u0175',
19500  'wedbar': '\u2A5F',
19501  'wedgeq': '\u2259',
19502  'weierp': '\u2118',
19503  'wp': '\u2118',
19504  'wfr': '\uD835\uDD34',
19505  'wopf': '\uD835\uDD68',
19506  'wscr': '\uD835\uDCCC',
19507  'xfr': '\uD835\uDD35',
19508  'xi': '\u03BE',
19509  'xnis': '\u22FB',
19510  'xopf': '\uD835\uDD69',
19511  'xscr': '\uD835\uDCCD',
19512  'yacute': '\u00FD',
19513  'yacy': '\u044F',
19514  'ycirc': '\u0177',
19515  'ycy': '\u044B',
19516  'yen': '\u00A5',
19517  'yfr': '\uD835\uDD36',
19518  'yicy': '\u0457',
19519  'yopf': '\uD835\uDD6A',
19520  'yscr': '\uD835\uDCCE',
19521  'yucy': '\u044E',
19522  'yuml': '\u00FF',
19523  'zacute': '\u017A',
19524  'zcaron': '\u017E',
19525  'zcy': '\u0437',
19526  'zdot': '\u017C',
19527  'zeta': '\u03B6',
19528  'zfr': '\uD835\uDD37',
19529  'zhcy': '\u0436',
19530  'zigrarr': '\u21DD',
19531  'zopf': '\uD835\uDD6B',
19532  'zscr': '\uD835\uDCCF',
19533  'zwj': '\u200D',
19534  'zwnj': '\u200C'
19535}; // The &ngsp; pseudo-entity is denoting a space. see:
19536// https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart
19537
19538const NGSP_UNICODE = '\uE500';
19539NAMED_ENTITIES['ngsp'] = NGSP_UNICODE;
19540/**
19541 * @license
19542 * Copyright Google LLC All Rights Reserved.
19543 *
19544 * Use of this source code is governed by an MIT-style license that can be
19545 * found in the LICENSE file at https://angular.io/license
19546 */
19547
19548class TokenError extends ParseError {
19549  constructor(errorMsg, tokenType, span) {
19550    super(span, errorMsg);
19551    this.tokenType = tokenType;
19552  }
19553
19554}
19555
19556class TokenizeResult {
19557  constructor(tokens, errors, nonNormalizedIcuExpressions) {
19558    this.tokens = tokens;
19559    this.errors = errors;
19560    this.nonNormalizedIcuExpressions = nonNormalizedIcuExpressions;
19561  }
19562
19563}
19564
19565function tokenize(source, url, getTagDefinition, options = {}) {
19566  const tokenizer = new _Tokenizer(new ParseSourceFile(source, url), getTagDefinition, options);
19567  tokenizer.tokenize();
19568  return new TokenizeResult(mergeTextTokens(tokenizer.tokens), tokenizer.errors, tokenizer.nonNormalizedIcuExpressions);
19569}
19570
19571const _CR_OR_CRLF_REGEXP = /\r\n?/g;
19572
19573function _unexpectedCharacterErrorMsg(charCode) {
19574  const char = charCode === $EOF ? 'EOF' : String.fromCharCode(charCode);
19575  return `Unexpected character "${char}"`;
19576}
19577
19578function _unknownEntityErrorMsg(entitySrc) {
19579  return `Unknown entity "${entitySrc}" - use the "&#<decimal>;" or  "&#x<hex>;" syntax`;
19580}
19581
19582function _unparsableEntityErrorMsg(type, entityStr) {
19583  return `Unable to parse entity "${entityStr}" - ${type} character reference entities must end with ";"`;
19584}
19585
19586var CharacterReferenceType;
19587
19588(function (CharacterReferenceType) {
19589  CharacterReferenceType["HEX"] = "hexadecimal";
19590  CharacterReferenceType["DEC"] = "decimal";
19591})(CharacterReferenceType || (CharacterReferenceType = {}));
19592
19593class _ControlFlowError {
19594  constructor(error) {
19595    this.error = error;
19596  }
19597
19598} // See https://www.w3.org/TR/html51/syntax.html#writing-html-documents
19599
19600
19601class _Tokenizer {
19602  /**
19603   * @param _file The html source file being tokenized.
19604   * @param _getTagDefinition A function that will retrieve a tag definition for a given tag name.
19605   * @param options Configuration of the tokenization.
19606   */
19607  constructor(_file, _getTagDefinition, options) {
19608    this._getTagDefinition = _getTagDefinition;
19609    this._currentTokenStart = null;
19610    this._currentTokenType = null;
19611    this._expansionCaseStack = [];
19612    this._inInterpolation = false;
19613    this.tokens = [];
19614    this.errors = [];
19615    this.nonNormalizedIcuExpressions = [];
19616    this._tokenizeIcu = options.tokenizeExpansionForms || false;
19617    this._interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
19618    this._leadingTriviaCodePoints = options.leadingTriviaChars && options.leadingTriviaChars.map(c => c.codePointAt(0) || 0);
19619    const range = options.range || {
19620      endPos: _file.content.length,
19621      startPos: 0,
19622      startLine: 0,
19623      startCol: 0
19624    };
19625    this._cursor = options.escapedString ? new EscapedCharacterCursor(_file, range) : new PlainCharacterCursor(_file, range);
19626    this._preserveLineEndings = options.preserveLineEndings || false;
19627    this._escapedString = options.escapedString || false;
19628    this._i18nNormalizeLineEndingsInICUs = options.i18nNormalizeLineEndingsInICUs || false;
19629
19630    try {
19631      this._cursor.init();
19632    } catch (e) {
19633      this.handleError(e);
19634    }
19635  }
19636
19637  _processCarriageReturns(content) {
19638    if (this._preserveLineEndings) {
19639      return content;
19640    } // https://www.w3.org/TR/html51/syntax.html#preprocessing-the-input-stream
19641    // In order to keep the original position in the source, we can not
19642    // pre-process it.
19643    // Instead CRs are processed right before instantiating the tokens.
19644
19645
19646    return content.replace(_CR_OR_CRLF_REGEXP, '\n');
19647  }
19648
19649  tokenize() {
19650    while (this._cursor.peek() !== $EOF) {
19651      const start = this._cursor.clone();
19652
19653      try {
19654        if (this._attemptCharCode($LT)) {
19655          if (this._attemptCharCode($BANG)) {
19656            if (this._attemptCharCode($LBRACKET)) {
19657              this._consumeCdata(start);
19658            } else if (this._attemptCharCode($MINUS)) {
19659              this._consumeComment(start);
19660            } else {
19661              this._consumeDocType(start);
19662            }
19663          } else if (this._attemptCharCode($SLASH)) {
19664            this._consumeTagClose(start);
19665          } else {
19666            this._consumeTagOpen(start);
19667          }
19668        } else if (!(this._tokenizeIcu && this._tokenizeExpansionForm())) {
19669          // In (possibly interpolated) text the end of the text is given by `isTextEnd()`, while
19670          // the premature end of an interpolation is given by the start of a new HTML element.
19671          this._consumeWithInterpolation(5
19672          /* TokenType.TEXT */
19673          , 8
19674          /* TokenType.INTERPOLATION */
19675          , () => this._isTextEnd(), () => this._isTagStart());
19676        }
19677      } catch (e) {
19678        this.handleError(e);
19679      }
19680    }
19681
19682    this._beginToken(24
19683    /* TokenType.EOF */
19684    );
19685
19686    this._endToken([]);
19687  }
19688  /**
19689   * @returns whether an ICU token has been created
19690   * @internal
19691   */
19692
19693
19694  _tokenizeExpansionForm() {
19695    if (this.isExpansionFormStart()) {
19696      this._consumeExpansionFormStart();
19697
19698      return true;
19699    }
19700
19701    if (isExpansionCaseStart(this._cursor.peek()) && this._isInExpansionForm()) {
19702      this._consumeExpansionCaseStart();
19703
19704      return true;
19705    }
19706
19707    if (this._cursor.peek() === $RBRACE) {
19708      if (this._isInExpansionCase()) {
19709        this._consumeExpansionCaseEnd();
19710
19711        return true;
19712      }
19713
19714      if (this._isInExpansionForm()) {
19715        this._consumeExpansionFormEnd();
19716
19717        return true;
19718      }
19719    }
19720
19721    return false;
19722  }
19723
19724  _beginToken(type, start = this._cursor.clone()) {
19725    this._currentTokenStart = start;
19726    this._currentTokenType = type;
19727  }
19728
19729  _endToken(parts, end) {
19730    if (this._currentTokenStart === null) {
19731      throw new TokenError('Programming error - attempted to end a token when there was no start to the token', this._currentTokenType, this._cursor.getSpan(end));
19732    }
19733
19734    if (this._currentTokenType === null) {
19735      throw new TokenError('Programming error - attempted to end a token which has no token type', null, this._cursor.getSpan(this._currentTokenStart));
19736    }
19737
19738    const token = {
19739      type: this._currentTokenType,
19740      parts,
19741      sourceSpan: (end ?? this._cursor).getSpan(this._currentTokenStart, this._leadingTriviaCodePoints)
19742    };
19743    this.tokens.push(token);
19744    this._currentTokenStart = null;
19745    this._currentTokenType = null;
19746    return token;
19747  }
19748
19749  _createError(msg, span) {
19750    if (this._isInExpansionForm()) {
19751      msg += ` (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)`;
19752    }
19753
19754    const error = new TokenError(msg, this._currentTokenType, span);
19755    this._currentTokenStart = null;
19756    this._currentTokenType = null;
19757    return new _ControlFlowError(error);
19758  }
19759
19760  handleError(e) {
19761    if (e instanceof CursorError) {
19762      e = this._createError(e.msg, this._cursor.getSpan(e.cursor));
19763    }
19764
19765    if (e instanceof _ControlFlowError) {
19766      this.errors.push(e.error);
19767    } else {
19768      throw e;
19769    }
19770  }
19771
19772  _attemptCharCode(charCode) {
19773    if (this._cursor.peek() === charCode) {
19774      this._cursor.advance();
19775
19776      return true;
19777    }
19778
19779    return false;
19780  }
19781
19782  _attemptCharCodeCaseInsensitive(charCode) {
19783    if (compareCharCodeCaseInsensitive(this._cursor.peek(), charCode)) {
19784      this._cursor.advance();
19785
19786      return true;
19787    }
19788
19789    return false;
19790  }
19791
19792  _requireCharCode(charCode) {
19793    const location = this._cursor.clone();
19794
19795    if (!this._attemptCharCode(charCode)) {
19796      throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
19797    }
19798  }
19799
19800  _attemptStr(chars) {
19801    const len = chars.length;
19802
19803    if (this._cursor.charsLeft() < len) {
19804      return false;
19805    }
19806
19807    const initialPosition = this._cursor.clone();
19808
19809    for (let i = 0; i < len; i++) {
19810      if (!this._attemptCharCode(chars.charCodeAt(i))) {
19811        // If attempting to parse the string fails, we want to reset the parser
19812        // to where it was before the attempt
19813        this._cursor = initialPosition;
19814        return false;
19815      }
19816    }
19817
19818    return true;
19819  }
19820
19821  _attemptStrCaseInsensitive(chars) {
19822    for (let i = 0; i < chars.length; i++) {
19823      if (!this._attemptCharCodeCaseInsensitive(chars.charCodeAt(i))) {
19824        return false;
19825      }
19826    }
19827
19828    return true;
19829  }
19830
19831  _requireStr(chars) {
19832    const location = this._cursor.clone();
19833
19834    if (!this._attemptStr(chars)) {
19835      throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(location));
19836    }
19837  }
19838
19839  _attemptCharCodeUntilFn(predicate) {
19840    while (!predicate(this._cursor.peek())) {
19841      this._cursor.advance();
19842    }
19843  }
19844
19845  _requireCharCodeUntilFn(predicate, len) {
19846    const start = this._cursor.clone();
19847
19848    this._attemptCharCodeUntilFn(predicate);
19849
19850    if (this._cursor.diff(start) < len) {
19851      throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
19852    }
19853  }
19854
19855  _attemptUntilChar(char) {
19856    while (this._cursor.peek() !== char) {
19857      this._cursor.advance();
19858    }
19859  }
19860
19861  _readChar() {
19862    // Don't rely upon reading directly from `_input` as the actual char value
19863    // may have been generated from an escape sequence.
19864    const char = String.fromCodePoint(this._cursor.peek());
19865
19866    this._cursor.advance();
19867
19868    return char;
19869  }
19870
19871  _consumeEntity(textTokenType) {
19872    this._beginToken(9
19873    /* TokenType.ENCODED_ENTITY */
19874    );
19875
19876    const start = this._cursor.clone();
19877
19878    this._cursor.advance();
19879
19880    if (this._attemptCharCode($HASH)) {
19881      const isHex = this._attemptCharCode($x) || this._attemptCharCode($X);
19882
19883      const codeStart = this._cursor.clone();
19884
19885      this._attemptCharCodeUntilFn(isDigitEntityEnd);
19886
19887      if (this._cursor.peek() != $SEMICOLON) {
19888        // Advance cursor to include the peeked character in the string provided to the error
19889        // message.
19890        this._cursor.advance();
19891
19892        const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC;
19893        throw this._createError(_unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)), this._cursor.getSpan());
19894      }
19895
19896      const strNum = this._cursor.getChars(codeStart);
19897
19898      this._cursor.advance();
19899
19900      try {
19901        const charCode = parseInt(strNum, isHex ? 16 : 10);
19902
19903        this._endToken([String.fromCharCode(charCode), this._cursor.getChars(start)]);
19904      } catch {
19905        throw this._createError(_unknownEntityErrorMsg(this._cursor.getChars(start)), this._cursor.getSpan());
19906      }
19907    } else {
19908      const nameStart = this._cursor.clone();
19909
19910      this._attemptCharCodeUntilFn(isNamedEntityEnd);
19911
19912      if (this._cursor.peek() != $SEMICOLON) {
19913        // No semicolon was found so abort the encoded entity token that was in progress, and treat
19914        // this as a text token
19915        this._beginToken(textTokenType, start);
19916
19917        this._cursor = nameStart;
19918
19919        this._endToken(['&']);
19920      } else {
19921        const name = this._cursor.getChars(nameStart);
19922
19923        this._cursor.advance();
19924
19925        const char = NAMED_ENTITIES[name];
19926
19927        if (!char) {
19928          throw this._createError(_unknownEntityErrorMsg(name), this._cursor.getSpan(start));
19929        }
19930
19931        this._endToken([char, `&${name};`]);
19932      }
19933    }
19934  }
19935
19936  _consumeRawText(consumeEntities, endMarkerPredicate) {
19937    this._beginToken(consumeEntities ? 6
19938    /* TokenType.ESCAPABLE_RAW_TEXT */
19939    : 7
19940    /* TokenType.RAW_TEXT */
19941    );
19942
19943    const parts = [];
19944
19945    while (true) {
19946      const tagCloseStart = this._cursor.clone();
19947
19948      const foundEndMarker = endMarkerPredicate();
19949      this._cursor = tagCloseStart;
19950
19951      if (foundEndMarker) {
19952        break;
19953      }
19954
19955      if (consumeEntities && this._cursor.peek() === $AMPERSAND) {
19956        this._endToken([this._processCarriageReturns(parts.join(''))]);
19957
19958        parts.length = 0;
19959
19960        this._consumeEntity(6
19961        /* TokenType.ESCAPABLE_RAW_TEXT */
19962        );
19963
19964        this._beginToken(6
19965        /* TokenType.ESCAPABLE_RAW_TEXT */
19966        );
19967      } else {
19968        parts.push(this._readChar());
19969      }
19970    }
19971
19972    this._endToken([this._processCarriageReturns(parts.join(''))]);
19973  }
19974
19975  _consumeComment(start) {
19976    this._beginToken(10
19977    /* TokenType.COMMENT_START */
19978    , start);
19979
19980    this._requireCharCode($MINUS);
19981
19982    this._endToken([]);
19983
19984    this._consumeRawText(false, () => this._attemptStr('-->'));
19985
19986    this._beginToken(11
19987    /* TokenType.COMMENT_END */
19988    );
19989
19990    this._requireStr('-->');
19991
19992    this._endToken([]);
19993  }
19994
19995  _consumeCdata(start) {
19996    this._beginToken(12
19997    /* TokenType.CDATA_START */
19998    , start);
19999
20000    this._requireStr('CDATA[');
20001
20002    this._endToken([]);
20003
20004    this._consumeRawText(false, () => this._attemptStr(']]>'));
20005
20006    this._beginToken(13
20007    /* TokenType.CDATA_END */
20008    );
20009
20010    this._requireStr(']]>');
20011
20012    this._endToken([]);
20013  }
20014
20015  _consumeDocType(start) {
20016    this._beginToken(18
20017    /* TokenType.DOC_TYPE */
20018    , start);
20019
20020    const contentStart = this._cursor.clone();
20021
20022    this._attemptUntilChar($GT);
20023
20024    const content = this._cursor.getChars(contentStart);
20025
20026    this._cursor.advance();
20027
20028    this._endToken([content]);
20029  }
20030
20031  _consumePrefixAndName() {
20032    const nameOrPrefixStart = this._cursor.clone();
20033
20034    let prefix = '';
20035
20036    while (this._cursor.peek() !== $COLON && !isPrefixEnd(this._cursor.peek())) {
20037      this._cursor.advance();
20038    }
20039
20040    let nameStart;
20041
20042    if (this._cursor.peek() === $COLON) {
20043      prefix = this._cursor.getChars(nameOrPrefixStart);
20044
20045      this._cursor.advance();
20046
20047      nameStart = this._cursor.clone();
20048    } else {
20049      nameStart = nameOrPrefixStart;
20050    }
20051
20052    this._requireCharCodeUntilFn(isNameEnd, prefix === '' ? 0 : 1);
20053
20054    const name = this._cursor.getChars(nameStart);
20055
20056    return [prefix, name];
20057  }
20058
20059  _consumeTagOpen(start) {
20060    let tagName;
20061    let prefix;
20062    let openTagToken;
20063
20064    try {
20065      if (!isAsciiLetter(this._cursor.peek())) {
20066        throw this._createError(_unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan(start));
20067      }
20068
20069      openTagToken = this._consumeTagOpenStart(start);
20070      prefix = openTagToken.parts[0];
20071      tagName = openTagToken.parts[1];
20072
20073      this._attemptCharCodeUntilFn(isNotWhitespace);
20074
20075      while (this._cursor.peek() !== $SLASH && this._cursor.peek() !== $GT && this._cursor.peek() !== $LT && this._cursor.peek() !== $EOF) {
20076        this._consumeAttributeName();
20077
20078        this._attemptCharCodeUntilFn(isNotWhitespace);
20079
20080        if (this._attemptCharCode($EQ)) {
20081          this._attemptCharCodeUntilFn(isNotWhitespace);
20082
20083          this._consumeAttributeValue();
20084        }
20085
20086        this._attemptCharCodeUntilFn(isNotWhitespace);
20087      }
20088
20089      this._consumeTagOpenEnd();
20090    } catch (e) {
20091      if (e instanceof _ControlFlowError) {
20092        if (openTagToken) {
20093          // We errored before we could close the opening tag, so it is incomplete.
20094          openTagToken.type = 4
20095          /* TokenType.INCOMPLETE_TAG_OPEN */
20096          ;
20097        } else {
20098          // When the start tag is invalid, assume we want a "<" as text.
20099          // Back to back text tokens are merged at the end.
20100          this._beginToken(5
20101          /* TokenType.TEXT */
20102          , start);
20103
20104          this._endToken(['<']);
20105        }
20106
20107        return;
20108      }
20109
20110      throw e;
20111    }
20112
20113    const contentTokenType = this._getTagDefinition(tagName).getContentType(prefix);
20114
20115    if (contentTokenType === TagContentType.RAW_TEXT) {
20116      this._consumeRawTextWithTagClose(prefix, tagName, false);
20117    } else if (contentTokenType === TagContentType.ESCAPABLE_RAW_TEXT) {
20118      this._consumeRawTextWithTagClose(prefix, tagName, true);
20119    }
20120  }
20121
20122  _consumeRawTextWithTagClose(prefix, tagName, consumeEntities) {
20123    this._consumeRawText(consumeEntities, () => {
20124      if (!this._attemptCharCode($LT)) return false;
20125      if (!this._attemptCharCode($SLASH)) return false;
20126
20127      this._attemptCharCodeUntilFn(isNotWhitespace);
20128
20129      if (!this._attemptStrCaseInsensitive(tagName)) return false;
20130
20131      this._attemptCharCodeUntilFn(isNotWhitespace);
20132
20133      return this._attemptCharCode($GT);
20134    });
20135
20136    this._beginToken(3
20137    /* TokenType.TAG_CLOSE */
20138    );
20139
20140    this._requireCharCodeUntilFn(code => code === $GT, 3);
20141
20142    this._cursor.advance(); // Consume the `>`
20143
20144
20145    this._endToken([prefix, tagName]);
20146  }
20147
20148  _consumeTagOpenStart(start) {
20149    this._beginToken(0
20150    /* TokenType.TAG_OPEN_START */
20151    , start);
20152
20153    const parts = this._consumePrefixAndName();
20154
20155    return this._endToken(parts);
20156  }
20157
20158  _consumeAttributeName() {
20159    const attrNameStart = this._cursor.peek();
20160
20161    if (attrNameStart === $SQ || attrNameStart === $DQ) {
20162      throw this._createError(_unexpectedCharacterErrorMsg(attrNameStart), this._cursor.getSpan());
20163    }
20164
20165    this._beginToken(14
20166    /* TokenType.ATTR_NAME */
20167    );
20168
20169    const prefixAndName = this._consumePrefixAndName();
20170
20171    this._endToken(prefixAndName);
20172  }
20173
20174  _consumeAttributeValue() {
20175    let value;
20176
20177    if (this._cursor.peek() === $SQ || this._cursor.peek() === $DQ) {
20178      const quoteChar = this._cursor.peek();
20179
20180      this._consumeQuote(quoteChar); // In an attribute then end of the attribute value and the premature end to an interpolation
20181      // are both triggered by the `quoteChar`.
20182
20183
20184      const endPredicate = () => this._cursor.peek() === quoteChar;
20185
20186      this._consumeWithInterpolation(16
20187      /* TokenType.ATTR_VALUE_TEXT */
20188      , 17
20189      /* TokenType.ATTR_VALUE_INTERPOLATION */
20190      , endPredicate, endPredicate);
20191
20192      this._consumeQuote(quoteChar);
20193    } else {
20194      const endPredicate = () => isNameEnd(this._cursor.peek());
20195
20196      this._consumeWithInterpolation(16
20197      /* TokenType.ATTR_VALUE_TEXT */
20198      , 17
20199      /* TokenType.ATTR_VALUE_INTERPOLATION */
20200      , endPredicate, endPredicate);
20201    }
20202  }
20203
20204  _consumeQuote(quoteChar) {
20205    this._beginToken(15
20206    /* TokenType.ATTR_QUOTE */
20207    );
20208
20209    this._requireCharCode(quoteChar);
20210
20211    this._endToken([String.fromCodePoint(quoteChar)]);
20212  }
20213
20214  _consumeTagOpenEnd() {
20215    const tokenType = this._attemptCharCode($SLASH) ? 2
20216    /* TokenType.TAG_OPEN_END_VOID */
20217    : 1
20218    /* TokenType.TAG_OPEN_END */
20219    ;
20220
20221    this._beginToken(tokenType);
20222
20223    this._requireCharCode($GT);
20224
20225    this._endToken([]);
20226  }
20227
20228  _consumeTagClose(start) {
20229    this._beginToken(3
20230    /* TokenType.TAG_CLOSE */
20231    , start);
20232
20233    this._attemptCharCodeUntilFn(isNotWhitespace);
20234
20235    const prefixAndName = this._consumePrefixAndName();
20236
20237    this._attemptCharCodeUntilFn(isNotWhitespace);
20238
20239    this._requireCharCode($GT);
20240
20241    this._endToken(prefixAndName);
20242  }
20243
20244  _consumeExpansionFormStart() {
20245    this._beginToken(19
20246    /* TokenType.EXPANSION_FORM_START */
20247    );
20248
20249    this._requireCharCode($LBRACE);
20250
20251    this._endToken([]);
20252
20253    this._expansionCaseStack.push(19
20254    /* TokenType.EXPANSION_FORM_START */
20255    );
20256
20257    this._beginToken(7
20258    /* TokenType.RAW_TEXT */
20259    );
20260
20261    const condition = this._readUntil($COMMA);
20262
20263    const normalizedCondition = this._processCarriageReturns(condition);
20264
20265    if (this._i18nNormalizeLineEndingsInICUs) {
20266      // We explicitly want to normalize line endings for this text.
20267      this._endToken([normalizedCondition]);
20268    } else {
20269      // We are not normalizing line endings.
20270      const conditionToken = this._endToken([condition]);
20271
20272      if (normalizedCondition !== condition) {
20273        this.nonNormalizedIcuExpressions.push(conditionToken);
20274      }
20275    }
20276
20277    this._requireCharCode($COMMA);
20278
20279    this._attemptCharCodeUntilFn(isNotWhitespace);
20280
20281    this._beginToken(7
20282    /* TokenType.RAW_TEXT */
20283    );
20284
20285    const type = this._readUntil($COMMA);
20286
20287    this._endToken([type]);
20288
20289    this._requireCharCode($COMMA);
20290
20291    this._attemptCharCodeUntilFn(isNotWhitespace);
20292  }
20293
20294  _consumeExpansionCaseStart() {
20295    this._beginToken(20
20296    /* TokenType.EXPANSION_CASE_VALUE */
20297    );
20298
20299    const value = this._readUntil($LBRACE).trim();
20300
20301    this._endToken([value]);
20302
20303    this._attemptCharCodeUntilFn(isNotWhitespace);
20304
20305    this._beginToken(21
20306    /* TokenType.EXPANSION_CASE_EXP_START */
20307    );
20308
20309    this._requireCharCode($LBRACE);
20310
20311    this._endToken([]);
20312
20313    this._attemptCharCodeUntilFn(isNotWhitespace);
20314
20315    this._expansionCaseStack.push(21
20316    /* TokenType.EXPANSION_CASE_EXP_START */
20317    );
20318  }
20319
20320  _consumeExpansionCaseEnd() {
20321    this._beginToken(22
20322    /* TokenType.EXPANSION_CASE_EXP_END */
20323    );
20324
20325    this._requireCharCode($RBRACE);
20326
20327    this._endToken([]);
20328
20329    this._attemptCharCodeUntilFn(isNotWhitespace);
20330
20331    this._expansionCaseStack.pop();
20332  }
20333
20334  _consumeExpansionFormEnd() {
20335    this._beginToken(23
20336    /* TokenType.EXPANSION_FORM_END */
20337    );
20338
20339    this._requireCharCode($RBRACE);
20340
20341    this._endToken([]);
20342
20343    this._expansionCaseStack.pop();
20344  }
20345  /**
20346   * Consume a string that may contain interpolation expressions.
20347   *
20348   * The first token consumed will be of `tokenType` and then there will be alternating
20349   * `interpolationTokenType` and `tokenType` tokens until the `endPredicate()` returns true.
20350   *
20351   * If an interpolation token ends prematurely it will have no end marker in its `parts` array.
20352   *
20353   * @param textTokenType the kind of tokens to interleave around interpolation tokens.
20354   * @param interpolationTokenType the kind of tokens that contain interpolation.
20355   * @param endPredicate a function that should return true when we should stop consuming.
20356   * @param endInterpolation a function that should return true if there is a premature end to an
20357   *     interpolation expression - i.e. before we get to the normal interpolation closing marker.
20358   */
20359
20360
20361  _consumeWithInterpolation(textTokenType, interpolationTokenType, endPredicate, endInterpolation) {
20362    this._beginToken(textTokenType);
20363
20364    const parts = [];
20365
20366    while (!endPredicate()) {
20367      const current = this._cursor.clone();
20368
20369      if (this._interpolationConfig && this._attemptStr(this._interpolationConfig.start)) {
20370        this._endToken([this._processCarriageReturns(parts.join(''))], current);
20371
20372        parts.length = 0;
20373
20374        this._consumeInterpolation(interpolationTokenType, current, endInterpolation);
20375
20376        this._beginToken(textTokenType);
20377      } else if (this._cursor.peek() === $AMPERSAND) {
20378        this._endToken([this._processCarriageReturns(parts.join(''))]);
20379
20380        parts.length = 0;
20381
20382        this._consumeEntity(textTokenType);
20383
20384        this._beginToken(textTokenType);
20385      } else {
20386        parts.push(this._readChar());
20387      }
20388    } // It is possible that an interpolation was started but not ended inside this text token.
20389    // Make sure that we reset the state of the lexer correctly.
20390
20391
20392    this._inInterpolation = false;
20393
20394    this._endToken([this._processCarriageReturns(parts.join(''))]);
20395  }
20396  /**
20397   * Consume a block of text that has been interpreted as an Angular interpolation.
20398   *
20399   * @param interpolationTokenType the type of the interpolation token to generate.
20400   * @param interpolationStart a cursor that points to the start of this interpolation.
20401   * @param prematureEndPredicate a function that should return true if the next characters indicate
20402   *     an end to the interpolation before its normal closing marker.
20403   */
20404
20405
20406  _consumeInterpolation(interpolationTokenType, interpolationStart, prematureEndPredicate) {
20407    const parts = [];
20408
20409    this._beginToken(interpolationTokenType, interpolationStart);
20410
20411    parts.push(this._interpolationConfig.start); // Find the end of the interpolation, ignoring content inside quotes.
20412
20413    const expressionStart = this._cursor.clone();
20414
20415    let inQuote = null;
20416    let inComment = false;
20417
20418    while (this._cursor.peek() !== $EOF && (prematureEndPredicate === null || !prematureEndPredicate())) {
20419      const current = this._cursor.clone();
20420
20421      if (this._isTagStart()) {
20422        // We are starting what looks like an HTML element in the middle of this interpolation.
20423        // Reset the cursor to before the `<` character and end the interpolation token.
20424        // (This is actually wrong but here for backward compatibility).
20425        this._cursor = current;
20426        parts.push(this._getProcessedChars(expressionStart, current));
20427
20428        this._endToken(parts);
20429
20430        return;
20431      }
20432
20433      if (inQuote === null) {
20434        if (this._attemptStr(this._interpolationConfig.end)) {
20435          // We are not in a string, and we hit the end interpolation marker
20436          parts.push(this._getProcessedChars(expressionStart, current));
20437          parts.push(this._interpolationConfig.end);
20438
20439          this._endToken(parts);
20440
20441          return;
20442        } else if (this._attemptStr('//')) {
20443          // Once we are in a comment we ignore any quotes
20444          inComment = true;
20445        }
20446      }
20447
20448      const char = this._cursor.peek();
20449
20450      this._cursor.advance();
20451
20452      if (char === $BACKSLASH) {
20453        // Skip the next character because it was escaped.
20454        this._cursor.advance();
20455      } else if (char === inQuote) {
20456        // Exiting the current quoted string
20457        inQuote = null;
20458      } else if (!inComment && inQuote === null && isQuote(char)) {
20459        // Entering a new quoted string
20460        inQuote = char;
20461      }
20462    } // We hit EOF without finding a closing interpolation marker
20463
20464
20465    parts.push(this._getProcessedChars(expressionStart, this._cursor));
20466
20467    this._endToken(parts);
20468  }
20469
20470  _getProcessedChars(start, end) {
20471    return this._processCarriageReturns(end.getChars(start));
20472  }
20473
20474  _isTextEnd() {
20475    if (this._isTagStart() || this._cursor.peek() === $EOF) {
20476      return true;
20477    }
20478
20479    if (this._tokenizeIcu && !this._inInterpolation) {
20480      if (this.isExpansionFormStart()) {
20481        // start of an expansion form
20482        return true;
20483      }
20484
20485      if (this._cursor.peek() === $RBRACE && this._isInExpansionCase()) {
20486        // end of and expansion case
20487        return true;
20488      }
20489    }
20490
20491    return false;
20492  }
20493  /**
20494   * Returns true if the current cursor is pointing to the start of a tag
20495   * (opening/closing/comments/cdata/etc).
20496   */
20497
20498
20499  _isTagStart() {
20500    if (this._cursor.peek() === $LT) {
20501      // We assume that `<` followed by whitespace is not the start of an HTML element.
20502      const tmp = this._cursor.clone();
20503
20504      tmp.advance(); // If the next character is alphabetic, ! nor / then it is a tag start
20505
20506      const code = tmp.peek();
20507
20508      if ($a <= code && code <= $z || $A <= code && code <= $Z || code === $SLASH || code === $BANG) {
20509        return true;
20510      }
20511    }
20512
20513    return false;
20514  }
20515
20516  _readUntil(char) {
20517    const start = this._cursor.clone();
20518
20519    this._attemptUntilChar(char);
20520
20521    return this._cursor.getChars(start);
20522  }
20523
20524  _isInExpansionCase() {
20525    return this._expansionCaseStack.length > 0 && this._expansionCaseStack[this._expansionCaseStack.length - 1] === 21
20526    /* TokenType.EXPANSION_CASE_EXP_START */
20527    ;
20528  }
20529
20530  _isInExpansionForm() {
20531    return this._expansionCaseStack.length > 0 && this._expansionCaseStack[this._expansionCaseStack.length - 1] === 19
20532    /* TokenType.EXPANSION_FORM_START */
20533    ;
20534  }
20535
20536  isExpansionFormStart() {
20537    if (this._cursor.peek() !== $LBRACE) {
20538      return false;
20539    }
20540
20541    if (this._interpolationConfig) {
20542      const start = this._cursor.clone();
20543
20544      const isInterpolation = this._attemptStr(this._interpolationConfig.start);
20545
20546      this._cursor = start;
20547      return !isInterpolation;
20548    }
20549
20550    return true;
20551  }
20552
20553}
20554
20555function isNotWhitespace(code) {
20556  return !isWhitespace(code) || code === $EOF;
20557}
20558
20559function isNameEnd(code) {
20560  return isWhitespace(code) || code === $GT || code === $LT || code === $SLASH || code === $SQ || code === $DQ || code === $EQ || code === $EOF;
20561}
20562
20563function isPrefixEnd(code) {
20564  return (code < $a || $z < code) && (code < $A || $Z < code) && (code < $0 || code > $9);
20565}
20566
20567function isDigitEntityEnd(code) {
20568  return code === $SEMICOLON || code === $EOF || !isAsciiHexDigit(code);
20569}
20570
20571function isNamedEntityEnd(code) {
20572  return code === $SEMICOLON || code === $EOF || !isAsciiLetter(code);
20573}
20574
20575function isExpansionCaseStart(peek) {
20576  return peek !== $RBRACE;
20577}
20578
20579function compareCharCodeCaseInsensitive(code1, code2) {
20580  return toUpperCaseCharCode(code1) === toUpperCaseCharCode(code2);
20581}
20582
20583function toUpperCaseCharCode(code) {
20584  return code >= $a && code <= $z ? code - $a + $A : code;
20585}
20586
20587function mergeTextTokens(srcTokens) {
20588  const dstTokens = [];
20589  let lastDstToken = undefined;
20590
20591  for (let i = 0; i < srcTokens.length; i++) {
20592    const token = srcTokens[i];
20593
20594    if (lastDstToken && lastDstToken.type === 5
20595    /* TokenType.TEXT */
20596    && token.type === 5
20597    /* TokenType.TEXT */
20598    || lastDstToken && lastDstToken.type === 16
20599    /* TokenType.ATTR_VALUE_TEXT */
20600    && token.type === 16
20601    /* TokenType.ATTR_VALUE_TEXT */
20602    ) {
20603      lastDstToken.parts[0] += token.parts[0];
20604      lastDstToken.sourceSpan.end = token.sourceSpan.end;
20605    } else {
20606      lastDstToken = token;
20607      dstTokens.push(lastDstToken);
20608    }
20609  }
20610
20611  return dstTokens;
20612}
20613
20614class PlainCharacterCursor {
20615  constructor(fileOrCursor, range) {
20616    if (fileOrCursor instanceof PlainCharacterCursor) {
20617      this.file = fileOrCursor.file;
20618      this.input = fileOrCursor.input;
20619      this.end = fileOrCursor.end;
20620      const state = fileOrCursor.state; // Note: avoid using `{...fileOrCursor.state}` here as that has a severe performance penalty.
20621      // In ES5 bundles the object spread operator is translated into the `__assign` helper, which
20622      // is not optimized by VMs as efficiently as a raw object literal. Since this constructor is
20623      // called in tight loops, this difference matters.
20624
20625      this.state = {
20626        peek: state.peek,
20627        offset: state.offset,
20628        line: state.line,
20629        column: state.column
20630      };
20631    } else {
20632      if (!range) {
20633        throw new Error('Programming error: the range argument must be provided with a file argument.');
20634      }
20635
20636      this.file = fileOrCursor;
20637      this.input = fileOrCursor.content;
20638      this.end = range.endPos;
20639      this.state = {
20640        peek: -1,
20641        offset: range.startPos,
20642        line: range.startLine,
20643        column: range.startCol
20644      };
20645    }
20646  }
20647
20648  clone() {
20649    return new PlainCharacterCursor(this);
20650  }
20651
20652  peek() {
20653    return this.state.peek;
20654  }
20655
20656  charsLeft() {
20657    return this.end - this.state.offset;
20658  }
20659
20660  diff(other) {
20661    return this.state.offset - other.state.offset;
20662  }
20663
20664  advance() {
20665    this.advanceState(this.state);
20666  }
20667
20668  init() {
20669    this.updatePeek(this.state);
20670  }
20671
20672  getSpan(start, leadingTriviaCodePoints) {
20673    start = start || this;
20674    let fullStart = start;
20675
20676    if (leadingTriviaCodePoints) {
20677      while (this.diff(start) > 0 && leadingTriviaCodePoints.indexOf(start.peek()) !== -1) {
20678        if (fullStart === start) {
20679          start = start.clone();
20680        }
20681
20682        start.advance();
20683      }
20684    }
20685
20686    const startLocation = this.locationFromCursor(start);
20687    const endLocation = this.locationFromCursor(this);
20688    const fullStartLocation = fullStart !== start ? this.locationFromCursor(fullStart) : startLocation;
20689    return new ParseSourceSpan(startLocation, endLocation, fullStartLocation);
20690  }
20691
20692  getChars(start) {
20693    return this.input.substring(start.state.offset, this.state.offset);
20694  }
20695
20696  charAt(pos) {
20697    return this.input.charCodeAt(pos);
20698  }
20699
20700  advanceState(state) {
20701    if (state.offset >= this.end) {
20702      this.state = state;
20703      throw new CursorError('Unexpected character "EOF"', this);
20704    }
20705
20706    const currentChar = this.charAt(state.offset);
20707
20708    if (currentChar === $LF) {
20709      state.line++;
20710      state.column = 0;
20711    } else if (!isNewLine(currentChar)) {
20712      state.column++;
20713    }
20714
20715    state.offset++;
20716    this.updatePeek(state);
20717  }
20718
20719  updatePeek(state) {
20720    state.peek = state.offset >= this.end ? $EOF : this.charAt(state.offset);
20721  }
20722
20723  locationFromCursor(cursor) {
20724    return new ParseLocation(cursor.file, cursor.state.offset, cursor.state.line, cursor.state.column);
20725  }
20726
20727}
20728
20729class EscapedCharacterCursor extends PlainCharacterCursor {
20730  constructor(fileOrCursor, range) {
20731    if (fileOrCursor instanceof EscapedCharacterCursor) {
20732      super(fileOrCursor);
20733      this.internalState = { ...fileOrCursor.internalState
20734      };
20735    } else {
20736      super(fileOrCursor, range);
20737      this.internalState = this.state;
20738    }
20739  }
20740
20741  advance() {
20742    this.state = this.internalState;
20743    super.advance();
20744    this.processEscapeSequence();
20745  }
20746
20747  init() {
20748    super.init();
20749    this.processEscapeSequence();
20750  }
20751
20752  clone() {
20753    return new EscapedCharacterCursor(this);
20754  }
20755
20756  getChars(start) {
20757    const cursor = start.clone();
20758    let chars = '';
20759
20760    while (cursor.internalState.offset < this.internalState.offset) {
20761      chars += String.fromCodePoint(cursor.peek());
20762      cursor.advance();
20763    }
20764
20765    return chars;
20766  }
20767  /**
20768   * Process the escape sequence that starts at the current position in the text.
20769   *
20770   * This method is called to ensure that `peek` has the unescaped value of escape sequences.
20771   */
20772
20773
20774  processEscapeSequence() {
20775    const peek = () => this.internalState.peek;
20776
20777    if (peek() === $BACKSLASH) {
20778      // We have hit an escape sequence so we need the internal state to become independent
20779      // of the external state.
20780      this.internalState = { ...this.state
20781      }; // Move past the backslash
20782
20783      this.advanceState(this.internalState); // First check for standard control char sequences
20784
20785      if (peek() === $n) {
20786        this.state.peek = $LF;
20787      } else if (peek() === $r) {
20788        this.state.peek = $CR;
20789      } else if (peek() === $v) {
20790        this.state.peek = $VTAB;
20791      } else if (peek() === $t) {
20792        this.state.peek = $TAB;
20793      } else if (peek() === $b) {
20794        this.state.peek = $BSPACE;
20795      } else if (peek() === $f) {
20796        this.state.peek = $FF;
20797      } // Now consider more complex sequences
20798      else if (peek() === $u) {
20799        // Unicode code-point sequence
20800        this.advanceState(this.internalState); // advance past the `u` char
20801
20802        if (peek() === $LBRACE) {
20803          // Variable length Unicode, e.g. `\x{123}`
20804          this.advanceState(this.internalState); // advance past the `{` char
20805          // Advance past the variable number of hex digits until we hit a `}` char
20806
20807          const digitStart = this.clone();
20808          let length = 0;
20809
20810          while (peek() !== $RBRACE) {
20811            this.advanceState(this.internalState);
20812            length++;
20813          }
20814
20815          this.state.peek = this.decodeHexDigits(digitStart, length);
20816        } else {
20817          // Fixed length Unicode, e.g. `\u1234`
20818          const digitStart = this.clone();
20819          this.advanceState(this.internalState);
20820          this.advanceState(this.internalState);
20821          this.advanceState(this.internalState);
20822          this.state.peek = this.decodeHexDigits(digitStart, 4);
20823        }
20824      } else if (peek() === $x) {
20825        // Hex char code, e.g. `\x2F`
20826        this.advanceState(this.internalState); // advance past the `x` char
20827
20828        const digitStart = this.clone();
20829        this.advanceState(this.internalState);
20830        this.state.peek = this.decodeHexDigits(digitStart, 2);
20831      } else if (isOctalDigit(peek())) {
20832        // Octal char code, e.g. `\012`,
20833        let octal = '';
20834        let length = 0;
20835        let previous = this.clone();
20836
20837        while (isOctalDigit(peek()) && length < 3) {
20838          previous = this.clone();
20839          octal += String.fromCodePoint(peek());
20840          this.advanceState(this.internalState);
20841          length++;
20842        }
20843
20844        this.state.peek = parseInt(octal, 8); // Backup one char
20845
20846        this.internalState = previous.internalState;
20847      } else if (isNewLine(this.internalState.peek)) {
20848        // Line continuation `\` followed by a new line
20849        this.advanceState(this.internalState); // advance over the newline
20850
20851        this.state = this.internalState;
20852      } else {
20853        // If none of the `if` blocks were executed then we just have an escaped normal character.
20854        // In that case we just, effectively, skip the backslash from the character.
20855        this.state.peek = this.internalState.peek;
20856      }
20857    }
20858  }
20859
20860  decodeHexDigits(start, length) {
20861    const hex = this.input.slice(start.internalState.offset, start.internalState.offset + length);
20862    const charCode = parseInt(hex, 16);
20863
20864    if (!isNaN(charCode)) {
20865      return charCode;
20866    } else {
20867      start.state = start.internalState;
20868      throw new CursorError('Invalid hexadecimal escape sequence', start);
20869    }
20870  }
20871
20872}
20873
20874class CursorError {
20875  constructor(msg, cursor) {
20876    this.msg = msg;
20877    this.cursor = cursor;
20878  }
20879
20880}
20881/**
20882 * @license
20883 * Copyright Google LLC All Rights Reserved.
20884 *
20885 * Use of this source code is governed by an MIT-style license that can be
20886 * found in the LICENSE file at https://angular.io/license
20887 */
20888
20889
20890class TreeError extends ParseError {
20891  constructor(elementName, span, msg) {
20892    super(span, msg);
20893    this.elementName = elementName;
20894  }
20895
20896  static create(elementName, span, msg) {
20897    return new TreeError(elementName, span, msg);
20898  }
20899
20900}
20901
20902class ParseTreeResult {
20903  constructor(rootNodes, errors) {
20904    this.rootNodes = rootNodes;
20905    this.errors = errors;
20906  }
20907
20908}
20909
20910class Parser {
20911  constructor(getTagDefinition) {
20912    this.getTagDefinition = getTagDefinition;
20913  }
20914
20915  parse(source, url, options) {
20916    const tokenizeResult = tokenize(source, url, this.getTagDefinition, options);
20917    const parser = new _TreeBuilder(tokenizeResult.tokens, this.getTagDefinition);
20918    parser.build();
20919    return new ParseTreeResult(parser.rootNodes, tokenizeResult.errors.concat(parser.errors));
20920  }
20921
20922}
20923
20924class _TreeBuilder {
20925  constructor(tokens, getTagDefinition) {
20926    this.tokens = tokens;
20927    this.getTagDefinition = getTagDefinition;
20928    this._index = -1;
20929    this._elementStack = [];
20930    this.rootNodes = [];
20931    this.errors = [];
20932
20933    this._advance();
20934  }
20935
20936  build() {
20937    while (this._peek.type !== 24
20938    /* TokenType.EOF */
20939    ) {
20940      if (this._peek.type === 0
20941      /* TokenType.TAG_OPEN_START */
20942      || this._peek.type === 4
20943      /* TokenType.INCOMPLETE_TAG_OPEN */
20944      ) {
20945        this._consumeStartTag(this._advance());
20946      } else if (this._peek.type === 3
20947      /* TokenType.TAG_CLOSE */
20948      ) {
20949        this._consumeEndTag(this._advance());
20950      } else if (this._peek.type === 12
20951      /* TokenType.CDATA_START */
20952      ) {
20953        this._closeVoidElement();
20954
20955        this._consumeCdata(this._advance());
20956      } else if (this._peek.type === 10
20957      /* TokenType.COMMENT_START */
20958      ) {
20959        this._closeVoidElement();
20960
20961        this._consumeComment(this._advance());
20962      } else if (this._peek.type === 5
20963      /* TokenType.TEXT */
20964      || this._peek.type === 7
20965      /* TokenType.RAW_TEXT */
20966      || this._peek.type === 6
20967      /* TokenType.ESCAPABLE_RAW_TEXT */
20968      ) {
20969        this._closeVoidElement();
20970
20971        this._consumeText(this._advance());
20972      } else if (this._peek.type === 19
20973      /* TokenType.EXPANSION_FORM_START */
20974      ) {
20975        this._consumeExpansion(this._advance());
20976      } else {
20977        // Skip all other tokens...
20978        this._advance();
20979      }
20980    }
20981  }
20982
20983  _advance() {
20984    const prev = this._peek;
20985
20986    if (this._index < this.tokens.length - 1) {
20987      // Note: there is always an EOF token at the end
20988      this._index++;
20989    }
20990
20991    this._peek = this.tokens[this._index];
20992    return prev;
20993  }
20994
20995  _advanceIf(type) {
20996    if (this._peek.type === type) {
20997      return this._advance();
20998    }
20999
21000    return null;
21001  }
21002
21003  _consumeCdata(_startToken) {
21004    this._consumeText(this._advance());
21005
21006    this._advanceIf(13
21007    /* TokenType.CDATA_END */
21008    );
21009  }
21010
21011  _consumeComment(token) {
21012    const text = this._advanceIf(7
21013    /* TokenType.RAW_TEXT */
21014    );
21015
21016    this._advanceIf(11
21017    /* TokenType.COMMENT_END */
21018    );
21019
21020    const value = text != null ? text.parts[0].trim() : null;
21021
21022    this._addToParent(new Comment(value, token.sourceSpan));
21023  }
21024
21025  _consumeExpansion(token) {
21026    const switchValue = this._advance();
21027
21028    const type = this._advance();
21029
21030    const cases = []; // read =
21031
21032    while (this._peek.type === 20
21033    /* TokenType.EXPANSION_CASE_VALUE */
21034    ) {
21035      const expCase = this._parseExpansionCase();
21036
21037      if (!expCase) return; // error
21038
21039      cases.push(expCase);
21040    } // read the final }
21041
21042
21043    if (this._peek.type !== 23
21044    /* TokenType.EXPANSION_FORM_END */
21045    ) {
21046      this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '}'.`));
21047      return;
21048    }
21049
21050    const sourceSpan = new ParseSourceSpan(token.sourceSpan.start, this._peek.sourceSpan.end, token.sourceSpan.fullStart);
21051
21052    this._addToParent(new Expansion(switchValue.parts[0], type.parts[0], cases, sourceSpan, switchValue.sourceSpan));
21053
21054    this._advance();
21055  }
21056
21057  _parseExpansionCase() {
21058    const value = this._advance(); // read {
21059
21060
21061    if (this._peek.type !== 21
21062    /* TokenType.EXPANSION_CASE_EXP_START */
21063    ) {
21064      this.errors.push(TreeError.create(null, this._peek.sourceSpan, `Invalid ICU message. Missing '{'.`));
21065      return null;
21066    } // read until }
21067
21068
21069    const start = this._advance();
21070
21071    const exp = this._collectExpansionExpTokens(start);
21072
21073    if (!exp) return null;
21074
21075    const end = this._advance();
21076
21077    exp.push({
21078      type: 24
21079      /* TokenType.EOF */
21080      ,
21081      parts: [],
21082      sourceSpan: end.sourceSpan
21083    }); // parse everything in between { and }
21084
21085    const expansionCaseParser = new _TreeBuilder(exp, this.getTagDefinition);
21086    expansionCaseParser.build();
21087
21088    if (expansionCaseParser.errors.length > 0) {
21089      this.errors = this.errors.concat(expansionCaseParser.errors);
21090      return null;
21091    }
21092
21093    const sourceSpan = new ParseSourceSpan(value.sourceSpan.start, end.sourceSpan.end, value.sourceSpan.fullStart);
21094    const expSourceSpan = new ParseSourceSpan(start.sourceSpan.start, end.sourceSpan.end, start.sourceSpan.fullStart);
21095    return new ExpansionCase(value.parts[0], expansionCaseParser.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan);
21096  }
21097
21098  _collectExpansionExpTokens(start) {
21099    const exp = [];
21100    const expansionFormStack = [21
21101    /* TokenType.EXPANSION_CASE_EXP_START */
21102    ];
21103
21104    while (true) {
21105      if (this._peek.type === 19
21106      /* TokenType.EXPANSION_FORM_START */
21107      || this._peek.type === 21
21108      /* TokenType.EXPANSION_CASE_EXP_START */
21109      ) {
21110        expansionFormStack.push(this._peek.type);
21111      }
21112
21113      if (this._peek.type === 22
21114      /* TokenType.EXPANSION_CASE_EXP_END */
21115      ) {
21116        if (lastOnStack(expansionFormStack, 21
21117        /* TokenType.EXPANSION_CASE_EXP_START */
21118        )) {
21119          expansionFormStack.pop();
21120          if (expansionFormStack.length === 0) return exp;
21121        } else {
21122          this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
21123          return null;
21124        }
21125      }
21126
21127      if (this._peek.type === 23
21128      /* TokenType.EXPANSION_FORM_END */
21129      ) {
21130        if (lastOnStack(expansionFormStack, 19
21131        /* TokenType.EXPANSION_FORM_START */
21132        )) {
21133          expansionFormStack.pop();
21134        } else {
21135          this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
21136          return null;
21137        }
21138      }
21139
21140      if (this._peek.type === 24
21141      /* TokenType.EOF */
21142      ) {
21143        this.errors.push(TreeError.create(null, start.sourceSpan, `Invalid ICU message. Missing '}'.`));
21144        return null;
21145      }
21146
21147      exp.push(this._advance());
21148    }
21149  }
21150
21151  _consumeText(token) {
21152    const tokens = [token];
21153    const startSpan = token.sourceSpan;
21154    let text = token.parts[0];
21155
21156    if (text.length > 0 && text[0] === '\n') {
21157      const parent = this._getParentElement();
21158
21159      if (parent != null && parent.children.length === 0 && this.getTagDefinition(parent.name).ignoreFirstLf) {
21160        text = text.substring(1);
21161        tokens[0] = {
21162          type: token.type,
21163          sourceSpan: token.sourceSpan,
21164          parts: [text]
21165        };
21166      }
21167    }
21168
21169    while (this._peek.type === 8
21170    /* TokenType.INTERPOLATION */
21171    || this._peek.type === 5
21172    /* TokenType.TEXT */
21173    || this._peek.type === 9
21174    /* TokenType.ENCODED_ENTITY */
21175    ) {
21176      token = this._advance();
21177      tokens.push(token);
21178
21179      if (token.type === 8
21180      /* TokenType.INTERPOLATION */
21181      ) {
21182        // For backward compatibility we decode HTML entities that appear in interpolation
21183        // expressions. This is arguably a bug, but it could be a considerable breaking change to
21184        // fix it. It should be addressed in a larger project to refactor the entire parser/lexer
21185        // chain after View Engine has been removed.
21186        text += token.parts.join('').replace(/&([^;]+);/g, decodeEntity);
21187      } else if (token.type === 9
21188      /* TokenType.ENCODED_ENTITY */
21189      ) {
21190        text += token.parts[0];
21191      } else {
21192        text += token.parts.join('');
21193      }
21194    }
21195
21196    if (text.length > 0) {
21197      const endSpan = token.sourceSpan;
21198
21199      this._addToParent(new Text(text, new ParseSourceSpan(start
21199Span.start, endSpan.end, startSpan.fullStart, startSpan.details), tokens));
21200    }
21201  }
21202
21203  _closeVoidElement() {
21204    const el = this._getParentElement();
21205
21206    if (el && this.getTagDefinition(el.name).isVoid) {
21207      this._elementStack.pop();
21208    }
21209  }
21210
21211  _consumeStartTag(startTagToken) {
21212    const [prefix, name] = startTagToken.parts;
21213    const attrs = [];
21214
21215    while (this._peek.type === 14
21216    /* TokenType.ATTR_NAME */
21217    ) {
21218      attrs.push(this._consumeAttr(this._advance()));
21219    }
21220
21221    const fullName = this._getElementFullName(prefix, name, this._getParentElement());
21222
21223    let selfClosing = false; // Note: There could have been a tokenizer error
21224    // so that we don't get a token for the end tag...
21225
21226    if (this._peek.type === 2
21227    /* TokenType.TAG_OPEN_END_VOID */
21228    ) {
21229      this._advance();
21230
21231      selfClosing = true;
21232      const tagDef = this.getTagDefinition(fullName);
21233
21234      if (!(tagDef.canSelfClose || getNsPrefix(fullName) !== null || tagDef.isVoid)) {
21235        this.errors.push(TreeError.create(fullName, startTagToken.sourceSpan, `Only void and foreign elements can be self closed "${startTagToken.parts[1]}"`));
21236      }
21237    } else if (this._peek.type === 1
21238    /* TokenType.TAG_OPEN_END */
21239    ) {
21240      this._advance();
21241
21242      selfClosing = false;
21243    }
21244
21245    const end = this._peek.sourceSpan.fullStart;
21246    const span = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart); // Create a separate `startSpan` because `span` will be modified when there is an `end` span.
21247
21248    const startSpan = new ParseSourceSpan(startTagToken.sourceSpan.start, end, startTagToken.sourceSpan.fullStart);
21249    const el = new Element(fullName, attrs, [], span, startSpan, undefined);
21250
21251    this._pushElement(el);
21252
21253    if (selfClosing) {
21254      // Elements that are self-closed have their `endSourceSpan` set to the full span, as the
21255      // element start tag also represents the end tag.
21256      this._popElement(fullName, span);
21257    } else if (startTagToken.type === 4
21258    /* TokenType.INCOMPLETE_TAG_OPEN */
21259    ) {
21260      // We already know the opening tag is not complete, so it is unlikely it has a corresponding
21261      // close tag. Let's optimistically parse it as a full element and emit an error.
21262      this._popElement(fullName, null);
21263
21264      this.errors.push(TreeError.create(fullName, span, `Opening tag "${fullName}" not terminated.`));
21265    }
21266  }
21267
21268  _pushElement(el) {
21269    const parentEl = this._getParentElement();
21270
21271    if (parentEl && this.getTagDefinition(parentEl.name).isClosedByChild(el.name)) {
21272      this._elementStack.pop();
21273    }
21274
21275    this._addToParent(el);
21276
21277    this._elementStack.push(el);
21278  }
21279
21280  _consumeEndTag(endTagToken) {
21281    const fullName = this._getElementFullName(endTagToken.parts[0], endTagToken.parts[1], this._getParentElement());
21282
21283    if (this.getTagDefinition(fullName).isVoid) {
21284      this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, `Void elements do not have end tags "${endTagToken.parts[1]}"`));
21285    } else if (!this._popElement(fullName, endTagToken.sourceSpan)) {
21286      const errMsg = `Unexpected closing tag "${fullName}". It may happen when the tag has already been closed by another tag. For more info see https://www.w3.org/TR/html5/syntax.html#closing-elements-that-have-implied-end-tags`;
21287      this.errors.push(TreeError.create(fullName, endTagToken.sourceSpan, errMsg));
21288    }
21289  }
21290  /**
21291   * Closes the nearest element with the tag name `fullName` in the parse tree.
21292   * `endSourceSpan` is the span of the closing tag, or null if the element does
21293   * not have a closing tag (for example, this happens when an incomplete
21294   * opening tag is recovered).
21295   */
21296
21297
21298  _popElement(fullName, endSourceSpan) {
21299    let unexpectedCloseTagDetected = false;
21300
21301    for (let stackIndex = this._elementStack.length - 1; stackIndex >= 0; stackIndex--) {
21302      const el = this._elementStack[stackIndex];
21303
21304      if (el.name === fullName) {
21305        // Record the parse span with the element that is being closed. Any elements that are
21306        // removed from the element stack at this point are closed implicitly, so they won't get
21307        // an end source span (as there is no explicit closing element).
21308        el.endSourceSpan = endSourceSpan;
21309        el.sourceSpan.end = endSourceSpan !== null ? endSourceSpan.end : el.sourceSpan.end;
21310
21311        this._elementStack.splice(stackIndex, this._elementStack.length - stackIndex);
21312
21313        return !unexpectedCloseTagDetected;
21314      }
21315
21316      if (!this.getTagDefinition(el.name).closedByParent) {
21317        // Note that we encountered an unexpected close tag but continue processing the element
21318        // stack so we can assign an `endSourceSpan` if there is a corresponding start tag for this
21319        // end tag in the stack.
21320        unexpectedCloseTagDetected = true;
21321      }
21322    }
21323
21324    return false;
21325  }
21326
21327  _consumeAttr(attrName) {
21328    const fullName = mergeNsAndName(attrName.parts[0], attrName.parts[1]);
21329    let attrEnd = attrName.sourceSpan.end; // Consume any quote
21330
21331    if (this._peek.type === 15
21332    /* TokenType.ATTR_QUOTE */
21333    ) {
21334      this._advance();
21335    } // Consume the attribute value
21336
21337
21338    let value = '';
21339    const valueTokens = [];
21340    let valueStartSpan = undefined;
21341    let valueEnd = undefined; // NOTE: We need to use a new variable `nextTokenType` here to hide the actual type of
21342    // `_peek.type` from TS. Otherwise TS will narrow the type of `_peek.type` preventing it from
21343    // being able to consider `ATTR_VALUE_INTERPOLATION` as an option. This is because TS is not
21344    // able to see that `_advance()` will actually mutate `_peek`.
21345
21346    const nextTokenType = this._peek.type;
21347
21348    if (nextTokenType === 16
21349    /* TokenType.ATTR_VALUE_TEXT */
21350    ) {
21351      valueStartSpan = this._peek.sourceSpan;
21352      valueEnd = this._peek.sourceSpan.end;
21353
21354      while (this._peek.type === 16
21355      /* TokenType.ATTR_VALUE_TEXT */
21356      || this._peek.type === 17
21357      /* TokenType.ATTR_VALUE_INTERPOLATION */
21358      || this._peek.type === 9
21359      /* TokenType.ENCODED_ENTITY */
21360      ) {
21361        const valueToken = this._advance();
21362
21363        valueTokens.push(valueToken);
21364
21365        if (valueToken.type === 17
21366        /* TokenType.ATTR_VALUE_INTERPOLATION */
21367        ) {
21368          // For backward compatibility we decode HTML entities that appear in interpolation
21369          // expressions. This is arguably a bug, but it could be a considerable breaking change to
21370          // fix it. It should be addressed in a larger project to refactor the entire parser/lexer
21371          // chain after View Engine has been removed.
21372          value += valueToken.parts.join('').replace(/&([^;]+);/g, decodeEntity);
21373        } else if (valueToken.type === 9
21374        /* TokenType.ENCODED_ENTITY */
21375        ) {
21376          value += valueToken.parts[0];
21377        } else {
21378          value += valueToken.parts.join('');
21379        }
21380
21381        valueEnd = attrEnd = valueToken.sourceSpan.end;
21382      }
21383    } // Consume any quote
21384
21385
21386    if (this._peek.type === 15
21387    /* TokenType.ATTR_QUOTE */
21388    ) {
21389      const quoteToken = this._advance();
21390
21391      attrEnd = quoteToken.sourceSpan.end;
21392    }
21393
21394    const valueSpan = valueStartSpan && valueEnd && new ParseSourceSpan(valueStartSpan.start, valueEnd, valueStartSpan.fullStart);
21395    return new Attribute(fullName, value, new ParseSourceSpan(attrName.sourceSpan.start, attrEnd, attrName.sourceSpan.fullStart), attrName.sourceSpan, valueSpan, valueTokens.length > 0 ? valueTokens : undefined, undefined);
21396  }
21397
21398  _getParentElement() {
21399    return this._elementStack.length > 0 ? this._elementStack[this._elementStack.length - 1] : null;
21400  }
21401
21402  _addToParent(node) {
21403    const parent = this._getParentElement();
21404
21405    if (parent != null) {
21406      parent.children.push(node);
21407    } else {
21408      this.rootNodes.push(node);
21409    }
21410  }
21411
21412  _getElementFullName(prefix, localName, parentElement) {
21413    if (prefix === '') {
21414      prefix = this.getTagDefinition(localName).implicitNamespacePrefix || '';
21415
21416      if (prefix === '' && parentElement != null) {
21417        const parentTagName = splitNsName(parentElement.name)[1];
21418        const parentTagDefinition = this.getTagDefinition(parentTagName);
21419
21420        if (!parentTagDefinition.preventNamespaceInheritance) {
21421          prefix = getNsPrefix(parentElement.name);
21422        }
21423      }
21424    }
21425
21426    return mergeNsAndName(prefix, localName);
21427  }
21428
21429}
21430
21431function lastOnStack(stack, element) {
21432  return stack.length > 0 && stack[stack.length - 1] === element;
21433}
21434/**
21435 * Decode the `entity` string, which we believe is the contents of an HTML entity.
21436 *
21437 * If the string is not actually a valid/known entity then just return the original `match` string.
21438 */
21439
21440
21441function decodeEntity(match, entity) {
21442  if (NAMED_ENTITIES[entity] !== undefined) {
21443    return NAMED_ENTITIES[entity] || match;
21444  }
21445
21446  if (/^#x[a-f0-9]+$/i.test(entity)) {
21447    return String.fromCodePoint(parseInt(entity.slice(2), 16));
21448  }
21449
21450  if (/^#\d+$/.test(entity)) {
21451    return String.fromCodePoint(parseInt(entity.slice(1), 10));
21452  }
21453
21454  return match;
21455}
21456/**
21457 * @license
21458 * Copyright Google LLC All Rights Reserved.
21459 *
21460 * Use of this source code is governed by an MIT-style license that can be
21461 * found in the LICENSE file at https://angular.io/license
21462 */
21463
21464
21465class HtmlParser extends Parser {
21466  constructor() {
21467    super(getHtmlTagDefinition);
21468  }
21469
21470  parse(source, url, options) {
21471    return super.parse(source, url, options);
21472  }
21473
21474}
21475/**
21476 * @license
21477 * Copyright Google LLC All Rights Reserved.
21478 *
21479 * Use of this source code is governed by an MIT-style license that can be
21480 * found in the LICENSE file at https://angular.io/license
21481 */
21482
21483
21484const PRESERVE_WS_ATTR_NAME = 'ngPreserveWhitespaces';
21485const SKIP_WS_TRIM_TAGS = new Set(['pre', 'template', 'textarea', 'script', 'style']); // Equivalent to \s with \u00a0 (non-breaking space) excluded.
21486// Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp
21487
21488const WS_CHARS = ' \f\n\r\t\v\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff';
21489const NO_WS_REGEXP = new RegExp(`[^${WS_CHARS}]`);
21490const WS_REPLACE_REGEXP = new RegExp(`[${WS_CHARS}]{2,}`, 'g');
21491
21492function hasPreserveWhitespacesAttr(attrs) {
21493  return attrs.some(attr => attr.name === PRESERVE_WS_ATTR_NAME);
21494}
21495/**
21496 * Angular Dart introduced &ngsp; as a placeholder for non-removable space, see:
21497 * https://github.com/dart-lang/angular/blob/0bb611387d29d65b5af7f9d2515ab571fd3fbee4/_tests/test/compiler/preserve_whitespace_test.dart#L25-L32
21498 * In Angular Dart &ngsp; is converted to the 0xE500 PUA (Private Use Areas) unicode character
21499 * and later on replaced by a space. We are re-implementing the same idea here.
21500 */
21501
21502
21503function replaceNgsp(value) {
21504  // lexer is replacing the &ngsp; pseudo-entity with NGSP_UNICODE
21505  return value.replace(new RegExp(NGSP_UNICODE, 'g'), ' ');
21506}
21507/**
21508 * This visitor can walk HTML parse tree and remove / trim text nodes using the following rules:
21509 * - consider spaces, tabs and new lines as whitespace characters;
21510 * - drop text nodes consisting of whitespace characters only;
21511 * - for all other text nodes replace consecutive whitespace characters with one space;
21512 * - convert &ngsp; pseudo-entity to a single space;
21513 *
21514 * Removal and trimming of whitespaces have positive performance impact (less code to generate
21515 * while compiling templates, faster view creation). At the same time it can be "destructive"
21516 * in some cases (whitespaces can influence layout). Because of the potential of breaking layout
21517 * this visitor is not activated by default in Angular 5 and people need to explicitly opt-in for
21518 * whitespace removal. The default option for whitespace removal will be revisited in Angular 6
21519 * and might be changed to "on" by default.
21520 */
21521
21522
21523class WhitespaceVisitor {
21524  visitElement(element, context) {
21525    if (SKIP_WS_TRIM_TAGS.has(element.name) || hasPreserveWhitespacesAttr(element.attrs)) {
21526      // don't descent into elements where we need to preserve whitespaces
21527      // but still visit all attributes to eliminate one used as a market to preserve WS
21528      return new Element(element.name, visitAll(this, element.attrs), element.children, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
21529    }
21530
21531    return new Element(element.name, element.attrs, visitAllWithSiblings(this, element.children), element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
21532  }
21533
21534  visitAttribute(attribute, context) {
21535    return attribute.name !== PRESERVE_WS_ATTR_NAME ? attribute : null;
21536  }
21537
21538  visitText(text, context) {
21539    const isNotBlank = text.value.match(NO_WS_REGEXP);
21540    const hasExpansionSibling = context && (context.prev instanceof Expansion || context.next instanceof Expansion);
21541
21542    if (isNotBlank || hasExpansionSibling) {
21543      // Process the whitespace in the tokens of this Text node
21544      const tokens = text.tokens.map(token => token.type === 5
21545      /* TokenType.TEXT */
21546      ? createWhitespaceProcessedTextToken(token) : token); // Process the whitespace of the value of this Text node
21547
21548      const value = processWhitespace(text.value);
21549      return new Text(value, text.sourceSpan, tokens, text.i18n);
21550    }
21551
21552    return null;
21553  }
21554
21555  visitComment(comment, context) {
21556    return comment;
21557  }
21558
21559  visitExpansion(expansion, context) {
21560    return expansion;
21561  }
21562
21563  visitExpansionCase(expansionCase, context) {
21564    return expansionCase;
21565  }
21566
21567}
21568
21569function createWhitespaceProcessedTextToken({
21570  type,
21571  parts,
21572  sourceSpan
21573}) {
21574  return {
21575    type,
21576    parts: [processWhitespace(parts[0])],
21577    sourceSpan
21578  };
21579}
21580
21581function processWhitespace(text) {
21582  return replaceNgsp(text).replace(WS_REPLACE_REGEXP, ' ');
21583}
21584
21585function removeWhitespaces(htmlAstWithErrors) {
21586  return new ParseTreeResult(visitAll(new WhitespaceVisitor(), htmlAstWithErrors.rootNodes), htmlAstWithErrors.errors);
21587}
21588
21589function visitAllWithSiblings(visitor, nodes) {
21590  const result = [];
21591  nodes.forEach((ast, i) => {
21592    const context = {
21593      prev: nodes[i - 1],
21594      next: nodes[i + 1]
21595    };
21596    const astResult = ast.visit(visitor, context);
21597
21598    if (astResult) {
21599      result.push(astResult);
21600    }
21601  });
21602  return result;
21603}
21604/**
21605 * @license
21606 * Copyright Google LLC All Rights Reserved.
21607 *
21608 * Use of this source code is governed by an MIT-style license that can be
21609 * found in the LICENSE file at https://angular.io/license
21610 */
21611
21612
21613function mapEntry(key, value) {
21614  return {
21615    key,
21616    value,
21617    quoted: false
21618  };
21619}
21620
21621function mapLiteral(obj, quoted = false) {
21622  return literalMap(Object.keys(obj).map(key => ({
21623    key,
21624    quoted,
21625    value: obj[key]
21626  })));
21627}
21628/**
21629 * @license
21630 * Copyright Google LLC All Rights Reserved.
21631 *
21632 * Use of this source code is governed by an MIT-style license that can be
21633 * found in the LICENSE file at https://angular.io/license
21634 */
21635
21636
21637class ElementSchemaRegistry {}
21638/**
21639 * @license
21640 * Copyright Google LLC All Rights Reserved.
21641 *
21642 * Use of this source code is governed by an MIT-style license that can be
21643 * found in the LICENSE file at https://angular.io/license
21644 */
21645
21646
21647const EVENT = 'event';
21648const BOOLEAN = 'boolean';
21649const NUMBER = 'number';
21650const STRING = 'string';
21651const OBJECT = 'object';
21652/**
21653 * This array represents the DOM schema. It encodes inheritance, properties, and events.
21654 *
21655 * ## Overview
21656 *
21657 * Each line represents one kind of element. The `element_inheritance` and properties are joined
21658 * using `element_inheritance|properties` syntax.
21659 *
21660 * ## Element Inheritance
21661 *
21662 * The `element_inheritance` can be further subdivided as `element1,element2,...^parentElement`.
21663 * Here the individual elements are separated by `,` (commas). Every element in the list
21664 * has identical properties.
21665 *
21666 * An `element` may inherit additional properties from `parentElement` If no `^parentElement` is
21667 * specified then `""` (blank) element is assumed.
21668 *
21669 * NOTE: The blank element inherits from root `[Element]` element, the super element of all
21670 * elements.
21671 *
21672 * NOTE an element prefix such as `:svg:` has no special meaning to the schema.
21673 *
21674 * ## Properties
21675 *
21676 * Each element has a set of properties separated by `,` (commas). Each property can be prefixed
21677 * by a special character designating its type:
21678 *
21679 * - (no prefix): property is a string.
21680 * - `*`: property represents an event.
21681 * - `!`: property is a boolean.
21682 * - `#`: property is a number.
21683 * - `%`: property is an object.
21684 *
21685 * ## Query
21686 *
21687 * The class creates an internal squas representation which allows to easily answer the query of
21688 * if a given property exist on a given element.
21689 *
21690 * NOTE: We don't yet support querying for types or events.
21691 * NOTE: This schema is auto extracted from `schema_extractor.ts` located in the test folder,
21692 *       see dom_element_schema_registry_spec.ts
21693 */
21694// =================================================================================================
21695// =================================================================================================
21696// =========== S T O P   -  S T O P   -  S T O P   -  S T O P   -  S T O P   -  S T O P  ===========
21697// =================================================================================================
21698// =================================================================================================
21699//
21700//                       DO NOT EDIT THIS DOM SCHEMA WITHOUT A SECURITY REVIEW!
21701//
21702// Newly added properties must be security reviewed and assigned an appropriate SecurityContext in
21703// dom_security_schema.ts. Reach out to mprobst & rjamet for details.
21704//
21705// =================================================================================================
21706
21707const SCHEMA = ['[Element]|textContent,%classList,className,id,innerHTML,*beforecopy,*beforecut,*beforepaste,*copy,*cut,*paste,*search,*selectstart,*webkitfullscreenchange,*webkitfullscreenerror,*w
21707heel,outerHTML,#scrollLeft,#scrollTop,slot' +
21708/* added manually to avoid breaking changes */
21709',*message,*mozfullscreenchange,*mozfullscreenerror,*mozpointerlockchange,*mozpointerlockerror,*webglcontextcreationerror,*webglcontextlost,*webglcontextrestored', '[HTMLElement]^[Element]|accessKey,contentEditable,dir,!draggable,!hidden,innerText,lang,*abort,*auxclick,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*cuechange,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*seeked,*seeking,*select,*show,*stalled,*submit,*suspend,*timeupdate,*toggle,*volumechange,*waiting,outerText,!spellcheck,%style,#tabIndex,title,!translate', 'abbr,address,article,aside,b,bdi,bdo,cite,code,dd,dfn,dt,em,figcaption,figure,footer,header,i,kbd,main,mark,nav,noscript,rb,rp,rt,rtc,ruby,s,samp,section,small,strong,sub,sup,u,var,wbr^[HTMLElement]|accessKey,contentEditable,dir,!draggable,!hidden,innerText,lang,*abort,*auxclick,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*cuechange,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*seeked,*seeking,*select,*show,*stalled,*submit,*suspend,*timeupdate,*toggle,*volumechange,*waiting,outerText,!spellcheck,%style,#tabIndex,title,!translate', 'media^[HTMLElement]|!autoplay,!controls,%controlsList,%crossOrigin,#currentTime,!defaultMuted,#defaultPlaybackRate,!disableRemotePlayback,!loop,!muted,*encrypted,*waitingforkey,#playbackRate,preload,src,%srcObject,#volume', ':svg:^[HTMLElement]|*abort,*auxclick,*blur,*cancel,*canplay,*canplaythrough,*change,*click,*close,*contextmenu,*cuechange,*dblclick,*drag,*dragend,*dragenter,*dragleave,*dragover,*dragstart,*drop,*durationchange,*emptied,*ended,*error,*focus,*gotpointercapture,*input,*invalid,*keydown,*keypress,*keyup,*load,*loadeddata,*loadedmetadata,*loadstart,*lostpointercapture,*mousedown,*mouseenter,*mouseleave,*mousemove,*mouseout,*mouseover,*mouseup,*mousewheel,*pause,*play,*playing,*pointercancel,*pointerdown,*pointerenter,*pointerleave,*pointermove,*pointerout,*pointerover,*pointerup,*progress,*ratechange,*reset,*resize,*scroll,*seeked,*seeking,*select,*show,*stalled,*submit,*suspend,*timeupdate,*toggle,*volumechange,*waiting,%style,#tabIndex', ':svg:graphics^:svg:|', ':svg:animation^:svg:|*begin,*end,*repeat', ':svg:geometry^:svg:|', ':svg:componentTransferFunction^:svg:|', ':svg:gradient^:svg:|', ':svg:textContent^:svg:graphics|', ':svg:textPositioning^:svg:textContent|', 'a^[HTMLElement]|charset,coords,download,hash,host,hostname,href,hreflang,name,password,pathname,ping,port,protocol,referrerPolicy,rel,rev,search,shape,target,text,type,username', 'area^[HTMLElement]|alt,coords,download,hash,host,hostname,href,!noHref,password,pathname,ping,port,protocol,referrerPolicy,rel,search,shape,target,username', 'audio^media|', 'br^[HTMLElement]|clear', 'base^[HTMLElement]|href,target', 'body^[HTMLElement]|aLink,background,bgColor,link,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,text,vLink', 'button^[HTMLElement]|!autofocus,!disabled,formAction,formEnctype,formMethod,!formNoValidate,formTarget,name,type,value', 'canvas^[HTMLElement]|#height,#width', 'content^[HTMLElement]|select', 'dl^[HTMLElement]|!compact', 'datalist^[HTMLElement]|', 'details^[HTMLElement]|!open', 'dialog^[HTMLElement]|!open,returnValue', 'dir^[HTMLElement]|!compact', 'div^[HTMLElement]|align', 'embed^[HTMLElement]|align,height,name,src,type,width', 'fieldset^[HTMLElement]|!disabled,name', 'font^[HTMLElement]|color,face,size', 'form^[HTMLElement]|acceptCharset,action,autocomplete,encoding,enctype,method,name,!noValidate,target', 'frame^[HTMLElement]|frameBorder,longDesc,marginHeight,marginWidth,name,!noResize,scrolling,src', 'frameset^[HTMLElement]|cols,*beforeunload,*blur,*error,*focus,*hashchange,*languagechange,*load,*message,*offline,*online,*pagehide,*pageshow,*popstate,*rejectionhandled,*resize,*scroll,*storage,*unhandledrejection,*unload,rows', 'hr^[HTMLElement]|align,color,!noShade,size,width', 'head^[HTMLElement]|', 'h1,h2,h3,h4,h5,h6^[HTMLElement]|align', 'html^[HTMLElement]|version', 'iframe^[HTMLElement]|align,!allowFullscreen,frameBorder,height,longDesc,marginHeight,marginWidth,name,referrerPolicy,%sandbox,scrolling,src,srcdoc,width', 'img^[HTMLElement]|align,alt,border,%crossOrigin,#height,#hspace,!isMap,longDesc,lowsrc,name,referrerPolicy,sizes,src,srcset,useMap,#vspace,#width', 'input^[HTMLElement]|accept,align,alt,autocapitalize,autocomplete,!autofocus,!checked,!defaultChecked,defaultValue,dirName,!disabled,%files,formAction,formEnctype,formMethod,!formNoValidate,formTarget,#height,!incremental,!indeterminate,max,#maxLength,min,#minLength,!multiple,name,pattern,placeholder,!readOnly,!required,selectionDirection,#selectionEnd,#selectionStart,#size,src,step,type,useMap,value,%valueAsDate,#valueAsNumber,#width', 'li^[HTMLElement]|type,#value', 'label^[HTMLElement]|htmlFor', 'legend^[HTMLElement]|align', 'link^[HTMLElement]|as,charset,%crossOrigin,!disabled,href,hreflang,integrity,media,referrerPolicy,rel,%relList,rev,%sizes,target,type', 'map^[HTMLElement]|name', 'marquee^[HTMLElement]|behavior,bgColor,direction,height,#hspace,#loop,#scrollAmount,#scrollDelay,!trueSpeed,#vspace,width', 'menu^[HTMLElement]|!compact', 'meta^[HTMLElement]|content,httpEquiv,name,scheme', 'meter^[HTMLElement]|#high,#low,#max,#min,#optimum,#value', 'ins,del^[HTMLElement]|cite,dateTime', 'ol^[HTMLElement]|!compact,!reversed,#start,type', 'object^[HTMLElement]|align,archive,border,code,codeBase,codeType,data,!declare,height,#hspace,name,standby,type,useMap,#vspace,width', 'optgroup^[HTMLElement]|!disabled,label', 'option^[HTMLElement]|!defaultSelected,!disabled,label,!selected,text,value', 'output^[HTMLElement]|defaultValue,%htmlFor,name,value', 'p^[HTMLElement]|align', 'param^[HTMLElement]|name,type,value,valueType', 'picture^[HTMLElement]|', 'pre^[HTMLElement]|#width', 'progress^[HTMLElement]|#max,#value', 'q,blockquote,cite^[HTMLElement]|', 'script^[HTMLElement]|!async,charset,%crossOrigin,!defer,event,htmlFor,integrity,src,text,type', 'select^[HTMLElement]|autocomplete,!autofocus,!disabled,#length,!multiple,name,!required,#selectedIndex,#size,value', 'shadow^[HTMLElement]|', 'slot^[HTMLElement]|name', 'source^[HTMLElement]|media,sizes,src,srcset,type', 'span^[HTMLElement]|', 'style^[HTMLElement]|!disabled,media,type', 'caption^[HTMLElement]|align', 'th,td^[HTMLElement]|abbr,align,axis,bgColor,ch,chOff,#colSpan,headers,height,!noWrap,#rowSpan,scope,vAlign,width', 'col,colgroup^[HTMLElement]|align,ch,chOff,#span,vAlign,width', 'table^[HTMLElement]|align,bgColor,border,%caption,cellPadding,cellSpacing,frame,rules,summary,%tFoot,%tHead,width', 'tr^[HTMLElement]|align,bgColor,ch,chOff,vAlign', 'tfoot,thead,tbody^[HTMLElement]|align,ch,chOff,vAlign', 'template^[HTMLElement]|', 'textarea^[HTMLElement]|autocapitalize,autocomplete,!autofocus,#cols,defaultValue,dirName,!disabled,#maxLength,#minLength,name,placeholder,!readOnly,!required,#rows,selectionDirection,#selectionEnd,#selectionStart,value,wrap', 'title^[HTMLElement]|text', 'track^[HTMLElement]|!default,kind,label,src,srclang', 'ul^[HTMLElement]|!compact,type', 'unknown^[HTMLElement]|', 'video^media|#height,poster,#width', ':svg:a^:svg:graphics|', ':svg:animate^:svg:animation|', ':svg:animateMotion^:svg:animation|', ':svg:animateTransform^:svg:animation|', ':svg:circle^:svg:geometry|', ':svg:clipPath^:svg:graphics|', ':svg:defs^:svg:graphics|', ':svg:desc^:svg:|', ':svg:discard^:svg:|', ':svg:ellipse^:svg:geometry|', ':svg:feBlend^:svg:|', ':svg:feColorMatrix^:svg:|', ':svg:feComponentTransfer^:svg:|', ':svg:feComposite^:svg:|', ':svg:feConvolveMatrix^:svg:|', ':svg:feDiffuseLighting^:svg:|', ':svg:feDisplacementMap^:svg:|', ':svg:feDistantLight^:svg:|', ':svg:feDropShadow^:svg:|', ':svg:feFlood^:svg:|', ':svg:feFuncA^:svg:componentTransferFunction|', ':svg:feFuncB^:svg:componentTransferFunction|', ':svg:feFuncG^:svg:componentTransferFunction|', ':svg:feFuncR^:svg:componentTransferFunction|', ':svg:feGaussianBlur^:svg:|', ':svg:feImage^:svg:|', ':svg:feMerge^:svg:|', ':svg:feMergeNode^:svg:|', ':svg:feMorphology^:svg:|', ':svg:feOffset^:svg:|', ':svg:fePointLight^:svg:|', ':svg:feSpecularLighting^:svg:|', ':svg:feSpotLight^:svg:|', ':svg:feTile^:svg:|', ':svg:feTurbulence^:svg:|', ':svg:filter^:svg:|', ':svg:foreignObject^:svg:graphics|', ':svg:g^:svg:graphics|', ':svg:image^:svg:graphics|', ':svg:line^:svg:geometry|', ':svg:linearGradient^:svg:gradient|', ':svg:mpath^:svg:|', ':svg:marker^:svg:|', ':svg:mask^:svg:|', ':svg:metadata^:svg:|', ':svg:path^:svg:geometry|', ':svg:pattern^:svg:|', ':svg:polygon^:svg:geometry|', ':svg:polyline^:svg:geometry|', ':svg:radialGradient^:svg:gradient|', ':svg:rect^:svg:geometry|', ':svg:svg^:svg:graphics|#currentScale,#zoomAndPan', ':svg:script^:svg:|type', ':svg:set^:svg:animation|', ':svg:stop^:svg:|', ':svg:style^:svg:|!disabled,media,title,type', ':svg:switch^:svg:graphics|', ':svg:symbol^:svg:|', ':svg:tspan^:svg:textPositioning|', ':svg:text^:svg:textPositioning|', ':svg:textPath^:svg:textContent|', ':svg:title^:svg:|', ':svg:use^:svg:graphics|', ':svg:view^:svg:|#zoomAndPan', 'data^[HTMLElement]|value', 'keygen^[HTMLElement]|!autofocus,challenge,!disabled,form,keytype,name', 'menuitem^[HTMLElement]|type,label,icon,!disabled,!checked,radiogroup,!default', 'summary^[HTMLElement]|', 'time^[HTMLElement]|dateTime', ':svg:cursor^:svg:|'];
21710
21711const _ATTR_TO_PROP = new Map(Object.entries({
21712  'class': 'className',
21713  'for': 'htmlFor',
21714  'formaction': 'formAction',
21715  'innerHtml': 'innerHTML',
21716  'readonly': 'readOnly',
21717  'tabindex': 'tabIndex'
21718})); // Invert _ATTR_TO_PROP.
21719
21720
21721const _PROP_TO_ATTR = Array.from(_ATTR_TO_PROP).reduce((inverted, [propertyName, attributeName]) => {
21722  inverted.set(propertyName, attributeName);
21723  return inverted;
21724}, new Map());
21725
21726class DomElementSchemaRegistry extends ElementSchemaRegistry {
21727  constructor() {
21728    super();
21729    this._schema = new Map(); // We don't allow binding to events for security reasons. Allowing event bindings would almost
21730    // certainly introduce bad XSS vulnerabilities. Instead, we store events in a separate schema.
21731
21732    this._eventSchema = new Map();
21733    SCHEMA.forEach(encodedType => {
21734      const type = new Map();
21735      const events = new Set();
21736      const [strType, strProperties] = encodedType.split('|');
21737      const properties = strProperties.split(',');
21738      const [typeNames, superName] = strType.split('^');
21739      typeNames.split(',').forEach(tag => {
21740        this._schema.set(tag.toLowerCase(), type);
21741
21742        this._eventSchema.set(tag.toLowerCase(), events);
21743      });
21744
21745      const superType = superName && this._schema.get(superName.toLowerCase());
21746
21747      if (superType) {
21748        for (const [prop, value] of superType) {
21749          type.set(prop, value);
21750        }
21751
21752        for (const superEvent of this._eventSchema.get(superName.toLowerCase())) {
21753          events.add(superEvent);
21754        }
21755      }
21756
21757      properties.forEach(property => {
21758        if (property.length > 0) {
21759          switch (property[0]) {
21760            case '*':
21761              events.add(property.substring(1));
21762              break;
21763
21764            case '!':
21765              type.set(property.substring(1), BOOLEAN);
21766              break;
21767
21768            case '#':
21769              type.set(property.substring(1), NUMBER);
21770              break;
21771
21772            case '%':
21773              type.set(property.substring(1), OBJECT);
21774              break;
21775
21776            default:
21777              type.set(property, STRING);
21778          }
21779        }
21780      });
21781    });
21782  }
21783
21784  hasProperty(tagName, propName, schemaMetas) {
21785    if (schemaMetas.some(schema => schema.name === NO_ERRORS_SCHEMA.name)) {
21786      return true;
21787    }
21788
21789    if (tagName.indexOf('-') > -1) {
21790      if (isNgContainer(tagName) || isNgContent(tagName)) {
21791        return false;
21792      }
21793
21794      if (schemaMetas.some(schema => schema.name === CUSTOM_ELEMENTS_SCHEMA.name)) {
21795        // Can't tell now as we don't know which properties a custom element will get
21796        // once it is instantiated
21797        return true;
21798      }
21799    }
21800
21801    const elementProperties = this._schema.get(tagName.toLowerCase()) || this._schema.get('unknown');
21802
21803    return elementProperties.has(propName);
21804  }
21805
21806  hasElement(tagName, schemaMetas) {
21807    if (schemaMetas.some(schema => schema.name === NO_ERRORS_SCHEMA.name)) {
21808      return true;
21809    }
21810
21811    if (tagName.indexOf('-') > -1) {
21812      if (isNgContainer(tagName) || isNgContent(tagName)) {
21813        return true;
21814      }
21815
21816      if (schemaMetas.some(schema => schema.name === CUSTOM_ELEMENTS_SCHEMA.name)) {
21817        // Allow any custom elements
21818        return true;
21819      }
21820    }
21821
21822    return this._schema.has(tagName.toLowerCase());
21823  }
21824  /**
21825   * securityContext returns the security context for the given property on the given DOM tag.
21826   *
21827   * Tag and property name are statically known and cannot change at runtime, i.e. it is not
21828   * possible to bind a value into a changing attribute or tag name.
21829   *
21830   * The filtering is based on a list of allowed tags|attributes. All attributes in the schema
21831   * above are assumed to have the 'NONE' security context, i.e. that they are safe inert
21832   * string values. Only specific well known attack vectors are assigned their appropriate context.
21833   */
21834
21835
21836  securityContext(tagName, propName, isAttribute) {
21837    if (isAttribute) {
21838      // NB: For security purposes, use the mapped property name, not the attribute name.
21839      propName = this.getMappedPropName(propName);
21840    } // Make sure comparisons are case insensitive, so that case differences between attribute and
21841    // property names do not have a security impact.
21842
21843
21844    tagName = tagName.toLowerCase();
21845    propName = propName.toLowerCase();
21846    let ctx = SECURITY_SCHEMA()[tagName + '|' + propName];
21847
21848    if (ctx) {
21849      return ctx;
21850    }
21851
21852    ctx = SECURITY_SCHEMA()['*|' + propName];
21853    return ctx ? ctx : SecurityContext.NONE;
21854  }
21855
21856  getMappedPropName(propName) {
21857    return _ATTR_TO_PROP.get(propName) ?? propName;
21858  }
21859
21860  getDefaultComponentElementName() {
21861    return 'ng-component';
21862  }
21863
21864  validateProperty(name) {
21865    if (name.toLowerCase().startsWith('on')) {
21866      const msg = `Binding to event property '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...` + `\nIf '${name}' is a directive input, make sure the directive is imported by the` + ` current module.`;
21867      return {
21868        error: true,
21869        msg: msg
21870      };
21871    } else {
21872      return {
21873        error: false
21874      };
21875    }
21876  }
21877
21878  validateAttribute(name) {
21879    if (name.toLowerCase().startsWith('on')) {
21880      const msg = `Binding to event attribute '${name}' is disallowed for security reasons, ` + `please use (${name.slice(2)})=...`;
21881      return {
21882        error: true,
21883        msg: msg
21884      };
21885    } else {
21886      return {
21887        error: false
21888      };
21889    }
21890  }
21891
21892  allKnownElementNames() {
21893    return Array.from(this._schema.keys());
21894  }
21895
21896  allKnownAttributesOfElement(tagName) {
21897    const elementProperties = this._schema.get(tagName.toLowerCase()) || this._schema.get('unknown'); // Convert properties to attributes.
21898
21899
21900    return Array.from(elementProperties.keys()).map(prop => _PROP_TO_ATTR.get(prop) ?? prop);
21901  }
21902
21903  allKnownEventsOfElement(tagName) {
21904    return Array.from(this._eventSchema.get(tagName.toLowerCase()) ?? []);
21905  }
21906
21907  normalizeAnimationStyleProperty(propName) {
21908    return dashCaseToCamelCase(propName);
21909  }
21910
21911  normalizeAnimationStyleValue(camelCaseProp, userProvidedProp, val) {
21912    let unit = '';
21913    const strVal = val.toString().trim();
21914    let errorMsg = null;
21915
21916    if (_isPixelDimensionStyle(camelCaseProp) && val !== 0 && val !== '0') {
21917      if (typeof val === 'number') {
21918        unit = 'px';
21919      } else {
21920        const valAndSuffixMatch = val.match(/^[+-]?[\d\.]+([a-z]*)$/);
21921
21922        if (valAndSuffixMatch && valAndSuffixMatch[1].length == 0) {
21923          errorMsg = `Please provide a CSS unit value for ${userProvidedProp}:${val}`;
21924        }
21925      }
21926    }
21927
21928    return {
21929      error: errorMsg,
21930      value: strVal + unit
21931    };
21932  }
21933
21934}
21935
21936function _isPixelDimensionStyle(prop) {
21937  switch (prop) {
21938    case 'width':
21939    case 'height':
21940    case 'minWidth':
21941    case 'minHeight':
21942    case 'maxWidth':
21943    case 'maxHeight':
21944    case 'left':
21945    case 'top':
21946    case 'bottom':
21947    case 'right':
21948    case 'fontSize':
21949    case 'outlineWidth':
21950    case 'outlineOffset':
21951    case 'paddingTop':
21952    case 'paddingLeft':
21953    case 'paddingBottom':
21954    case 'paddingRight':
21955    case 'marginTop':
21956    case 'marginLeft':
21957    case 'marginBottom':
21958    case 'marginRight':
21959    case 'borderRadius':
21960    case 'borderWidth':
21961    case 'borderTopWidth':
21962    case 'borderLeftWidth':
21963    case 'borderRightWidth':
21964    case 'borderBottomWidth':
21965    case 'textIndent':
21966      return true;
21967
21968    default:
21969      return false;
21970  }
21971}
21972/**
21973 * @license
21974 * Copyright Google LLC All Rights Reserved.
21975 *
21976 * Use of this source code is governed by an MIT-style license that can be
21977 * found in the LICENSE file at https://angular.io/license
21978 */
21979
21980/**
21981 * Set of tagName|propertyName corresponding to Trusted Types sinks. Properties applying to all
21982 * tags use '*'.
21983 *
21984 * Extracted from, and should be kept in sync with
21985 * https://w3c.github.io/webappsec-trusted-types/dist/spec/#integrations
21986 */
21987
21988
21989const TRUSTED_TYPES_SINKS = new Set([// NOTE: All strings in this set *must* be lowercase!
21990// TrustedHTML
21991'iframe|srcdoc', '*|innerhtml', '*|outerhtml', // NB: no TrustedScript here, as the corresponding tags are stripped by the compiler.
21992// TrustedScriptURL
21993'embed|src', 'object|codebase', 'object|data']);
21994/**
21995 * isTrustedTypesSink returns true if the given property on the given DOM tag is a Trusted Types
21996 * sink. In that case, use `ElementSchemaRegistry.securityContext` to determine which particular
21997 * Trusted Type is required for values passed to the sink:
21998 * - SecurityContext.HTML corresponds to TrustedHTML
21999 * - SecurityContext.RESOURCE_URL corresponds to TrustedScriptURL
22000 */
22001
22002function isTrustedTypesSink(tagName, propName) {
22003  // Make sure comparisons are case insensitive, so that case differences between attribute and
22004  // property names do not have a security impact.
22005  tagName = tagName.toLowerCase();
22006  propName = propName.toLowerCase();
22007  return TRUSTED_TYPES_SINKS.has(tagName + '|' + propName) || TRUSTED_TYPES_SINKS.has('*|' + propName);
22008}
22009/**
22010 * @license
22011 * Copyright Google LLC All Rights Reserved.
22012 *
22013 * Use of this source code is governed by an MIT-style license that can be
22014 * found in the LICENSE file at https://angular.io/license
22015 */
22016
22017
22018const PROPERTY_PARTS_SEPARATOR = '.';
22019const ATTRIBUTE_PREFIX = 'attr';
22020const CLASS_PREFIX = 'class';
22021const STYLE_PREFIX = 'style';
22022const TEMPLATE_ATTR_PREFIX$1 = '*';
22023const ANIMATE_PROP_PREFIX = 'animate-';
22024/**
22025 * Parses bindings in templates and in the directive host area.
22026 */
22027
22028class BindingParser {
22029  constructor(_exprParser, _interpolationConfig, _schemaRegistry, errors) {
22030    this._exprParser = _exprParser;
22031    this._interpolationConfig = _interpolationConfig;
22032    this._schemaRegistry = _schemaRegistry;
22033    this.errors = errors;
22034  }
22035
22036  get interpolationConfig() {
22037    return this._interpolationConfig;
22038  }
22039
22040  createBoundHostProperties(properties, sourceSpan) {
22041    const boundProps = [];
22042
22043    for (const propName of Object.keys(properties)) {
22044      const expression = properties[propName];
22045
22046      if (typeof expression === 'string') {
22047        this.parsePropertyBinding(propName, expression, true, sourceSpan, sourceSpan.start.offset, undefined, [], // Use the `sourceSpan` for  `keySpan`. This isn't really accurate, but neither is the
22048        // sourceSpan, as it represents the sourceSpan of the host itself rather than the
22049        // source of the host binding (which doesn't exist in the template). Regardless,
22050        // neither of these values are used in Ivy but are only here to satisfy the function
22051        // signature. This should likely be refactored in the future so that `sourceSpan`
22052        // isn't being used inaccurately.
22053        boundProps, sourceSpan);
22054      } else {
22055        this._reportError(`Value of the host property binding "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
22056      }
22057    }
22058
22059    return boundProps;
22060  }
22061
22062  createDirectiveHostEventAsts(hostListeners, sourceSpan) {
22063    const targetEvents = [];
22064
22065    for (const propName of Object.keys(hostListeners)) {
22066      const expression = hostListeners[propName];
22067
22068      if (typeof expression === 'string') {
22069        // Use the `sourceSpan` for  `keySpan` and `handlerSpan`. This isn't really accurate, but
22070        // neither is the `sourceSpan`, as it represents the `sourceSpan` of the host itself
22071        // rather than the source of the host binding (which doesn't exist in the template).
22072        // Regardless, neither of these values are used in Ivy but are only here to satisfy the
22073        // function signature. This should likely be refactored 
22073in the future so that `sourceSpan`
22074        // isn't being used inaccurately.
22075        this.parseEvent(propName, expression,
22076        /* isAssignmentEvent */
22077        false, sourceSpan, sourceSpan, [], targetEvents, sourceSpan);
22078      } else {
22079        this._reportError(`Value of the host listener "${propName}" needs to be a string representing an expression but got "${expression}" (${typeof expression})`, sourceSpan);
22080      }
22081    }
22082
22083    return targetEvents;
22084  }
22085
22086  parseInterpolation(value, sourceSpan, interpolatedTokens) {
22087    const sourceInfo = sourceSpan.start.toString();
22088    const absoluteOffset = sourceSpan.fullStart.offset;
22089
22090    try {
22091      const ast = this._exprParser.parseInterpolation(value, sourceInfo, absoluteOffset, interpolatedTokens, this._interpolationConfig);
22092
22093      if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan);
22094      return ast;
22095    } catch (e) {
22096      this._reportError(`${e}`, sourceSpan);
22097
22098      return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
22099    }
22100  }
22101  /**
22102   * Similar to `parseInterpolation`, but treats the provided string as a single expression
22103   * element that would normally appear within the interpolation prefix and suffix (`{{` and `}}`).
22104   * This is used for parsing the switch expression in ICUs.
22105   */
22106
22107
22108  parseInterpolationExpression(expression, sourceSpan) {
22109    const sourceInfo = sourceSpan.start.toString();
22110    const absoluteOffset = sourceSpan.start.offset;
22111
22112    try {
22113      const ast = this._exprParser.parseInterpolationExpression(expression, sourceInfo, absoluteOffset);
22114
22115      if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan);
22116      return ast;
22117    } catch (e) {
22118      this._reportError(`${e}`, sourceSpan);
22119
22120      return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
22121    }
22122  }
22123  /**
22124   * Parses the bindings in a microsyntax expression, and converts them to
22125   * `ParsedProperty` or `ParsedVariable`.
22126   *
22127   * @param tplKey template binding name
22128   * @param tplValue template binding value
22129   * @param sourceSpan span of template binding relative to entire the template
22130   * @param absoluteValueOffset start of the tplValue relative to the entire template
22131   * @param targetMatchableAttrs potential attributes to match in the template
22132   * @param targetProps target property bindings in the template
22133   * @param targetVars target variables in the template
22134   */
22135
22136
22137  parseInlineTemplateBinding(tplKey, tplValue, sourceSpan, absoluteValueOffset, targetMatchableAttrs, targetProps, targetVars, isIvyAst) {
22138    const absoluteKeyOffset = sourceSpan.start.offset + TEMPLATE_ATTR_PREFIX$1.length;
22139
22140    const bindings = this._parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset);
22141
22142    for (const binding of bindings) {
22143      // sourceSpan is for the entire HTML attribute. bindingSpan is for a particular
22144      // binding within the microsyntax expression so it's more narrow than sourceSpan.
22145      const bindingSpan = moveParseSourceSpan(sourceSpan, binding.sourceSpan);
22146      const key = binding.key.source;
22147      const keySpan = moveParseSourceSpan(sourceSpan, binding.key.span);
22148
22149      if (binding instanceof VariableBinding) {
22150        const value = binding.value ? binding.value.source : '$implicit';
22151        const valueSpan = binding.value ? moveParseSourceSpan(sourceSpan, binding.value.span) : undefined;
22152        targetVars.push(new ParsedVariable(key, value, bindingSpan, keySpan, valueSpan));
22153      } else if (binding.value) {
22154        const srcSpan = isIvyAst ? bindingSpan : sourceSpan;
22155        const valueSpan = moveParseSourceSpan(sourceSpan, binding.value.ast.sourceSpan);
22156
22157        this._parsePropertyAst(key, binding.value, srcSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
22158      } else {
22159        targetMatchableAttrs.push([key, ''
22160        /* value */
22161        ]); // Since this is a literal attribute with no RHS, source span should be
22162        // just the key span.
22163
22164        this.parseLiteralAttr(key, null
22165        /* value */
22166        , keySpan, absoluteValueOffset, undefined
22167        /* valueSpan */
22168        , targetMatchableAttrs, targetProps, keySpan);
22169      }
22170    }
22171  }
22172  /**
22173   * Parses the bindings in a microsyntax expression, e.g.
22174   * ```
22175   *    <tag *tplKey="let value1 = prop; let value2 = localVar">
22176   * ```
22177   *
22178   * @param tplKey template binding name
22179   * @param tplValue template binding value
22180   * @param sourceSpan span of template binding relative to entire the template
22181   * @param absoluteKeyOffset start of the `tplKey`
22182   * @param absoluteValueOffset start of the `tplValue`
22183   */
22184
22185
22186  _parseTemplateBindings(tplKey, tplValue, sourceSpan, absoluteKeyOffset, absoluteValueOffset) {
22187    const sourceInfo = sourceSpan.start.toString();
22188
22189    try {
22190      const bindingsResult = this._exprParser.parseTemplateBindings(tplKey, tplValue, sourceInfo, absoluteKeyOffset, absoluteValueOffset);
22191
22192      this._reportExpressionParserErrors(bindingsResult.errors, sourceSpan);
22193
22194      bindingsResult.warnings.forEach(warning => {
22195        this._reportError(warning, sourceSpan, ParseErrorLevel.WARNING);
22196      });
22197      return bindingsResult.templateBindings;
22198    } catch (e) {
22199      this._reportError(`${e}`, sourceSpan);
22200
22201      return [];
22202    }
22203  }
22204
22205  parseLiteralAttr(name, value, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) {
22206    if (isAnimationLabel(name)) {
22207      name = name.substring(1);
22208
22209      if (keySpan !== undefined) {
22210        keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
22211      }
22212
22213      if (value) {
22214        this._reportError(`Assigning animation triggers via @prop="exp" attributes with an expression is invalid.` + ` Use property bindings (e.g. [@prop]="exp") or use an attribute without a value (e.g. @prop) instead.`, sourceSpan, ParseErrorLevel.ERROR);
22215      }
22216
22217      this._parseAnimation(name, value, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
22218    } else {
22219      targetProps.push(new ParsedProperty(name, this._exprParser.wrapLiteralPrimitive(value, '', absoluteOffset), ParsedPropertyType.LITERAL_ATTR, sourceSpan, keySpan, valueSpan));
22220    }
22221  }
22222
22223  parsePropertyBinding(name, expression, isHost, sourceSpan, absoluteOffset, valueSpan, targetMatchableAttrs, targetProps, keySpan) {
22224    if (name.length === 0) {
22225      this._reportError(`Property name is missing in binding`, sourceSpan);
22226    }
22227
22228    let isAnimationProp = false;
22229
22230    if (name.startsWith(ANIMATE_PROP_PREFIX)) {
22231      isAnimationProp = true;
22232      name = name.substring(ANIMATE_PROP_PREFIX.length);
22233
22234      if (keySpan !== undefined) {
22235        keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + ANIMATE_PROP_PREFIX.length, keySpan.end.offset));
22236      }
22237    } else if (isAnimationLabel(name)) {
22238      isAnimationProp = true;
22239      name = name.substring(1);
22240
22241      if (keySpan !== undefined) {
22242        keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
22243      }
22244    }
22245
22246    if (isAnimationProp) {
22247      this._parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps);
22248    } else {
22249      this._parsePropertyAst(name, this._parseBinding(expression, isHost, valueSpan || sourceSpan, absoluteOffset), sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
22250    }
22251  }
22252
22253  parsePropertyInterpolation(name, value, sourceSpan, valueSpan, targetMatchableAttrs, targetProps, keySpan, interpolatedTokens) {
22254    const expr = this.parseInterpolation(value, valueSpan || sourceSpan, interpolatedTokens);
22255
22256    if (expr) {
22257      this._parsePropertyAst(name, expr, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps);
22258
22259      return true;
22260    }
22261
22262    return false;
22263  }
22264
22265  _parsePropertyAst(name, ast, sourceSpan, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
22266    targetMatchableAttrs.push([name, ast.source]);
22267    targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.DEFAULT, sourceSpan, keySpan, valueSpan));
22268  }
22269
22270  _parseAnimation(name, expression, sourceSpan, absoluteOffset, keySpan, valueSpan, targetMatchableAttrs, targetProps) {
22271    if (name.length === 0) {
22272      this._reportError('Animation trigger is missing', sourceSpan);
22273    } // This will occur when a @trigger is not paired with an expression.
22274    // For animations it is valid to not have an expression since */void
22275    // states will be applied by angular when the element is attached/detached
22276
22277
22278    const ast = this._parseBinding(expression || 'undefined', false, valueSpan || sourceSpan, absoluteOffset);
22279
22280    targetMatchableAttrs.push([name, ast.source]);
22281    targetProps.push(new ParsedProperty(name, ast, ParsedPropertyType.ANIMATION, sourceSpan, keySpan, valueSpan));
22282  }
22283
22284  _parseBinding(value, isHostBinding, sourceSpan, absoluteOffset) {
22285    const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown)').toString();
22286
22287    try {
22288      const ast = isHostBinding ? this._exprParser.parseSimpleBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig) : this._exprParser.parseBinding(value, sourceInfo, absoluteOffset, this._interpolationConfig);
22289      if (ast) this._reportExpressionParserErrors(ast.errors, sourceSpan);
22290      return ast;
22291    } catch (e) {
22292      this._reportError(`${e}`, sourceSpan);
22293
22294      return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
22295    }
22296  }
22297
22298  createBoundElementProperty(elementSelector, boundProp, skipValidation = false, mapPropertyName = true) {
22299    if (boundProp.isAnimation) {
22300      return new BoundElementProperty(boundProp.name, 4
22301      /* BindingType.Animation */
22302      , SecurityContext.NONE, boundProp.expression, null, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan);
22303    }
22304
22305    let unit = null;
22306    let bindingType = undefined;
22307    let boundPropertyName = null;
22308    const parts = boundProp.name.split(PROPERTY_PARTS_SEPARATOR);
22309    let securityContexts = undefined; // Check for special cases (prefix style, attr, class)
22310
22311    if (parts.length > 1) {
22312      if (parts[0] == ATTRIBUTE_PREFIX) {
22313        boundPropertyName = parts.slice(1).join(PROPERTY_PARTS_SEPARATOR);
22314
22315        if (!skipValidation) {
22316          this._validatePropertyOrAttributeName(boundPropertyName, boundProp.sourceSpan, true);
22317        }
22318
22319        securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, boundPropertyName, true);
22320        const nsSeparatorIdx = boundPropertyName.indexOf(':');
22321
22322        if (nsSeparatorIdx > -1) {
22323          const ns = boundPropertyName.substring(0, nsSeparatorIdx);
22324          const name = boundPropertyName.substring(nsSeparatorIdx + 1);
22325          boundPropertyName = mergeNsAndName(ns, name);
22326        }
22327
22328        bindingType = 1
22329        /* BindingType.Attribute */
22330        ;
22331      } else if (parts[0] == CLASS_PREFIX) {
22332        boundPropertyName = parts[1];
22333        bindingType = 2
22334        /* BindingType.Class */
22335        ;
22336        securityContexts = [SecurityContext.NONE];
22337      } else if (parts[0] == STYLE_PREFIX) {
22338        unit = parts.length > 2 ? parts[2] : null;
22339        boundPropertyName = parts[1];
22340        bindingType = 3
22341        /* BindingType.Style */
22342        ;
22343        securityContexts = [SecurityContext.STYLE];
22344      }
22345    } // If not a special case, use the full property name
22346
22347
22348    if (boundPropertyName === null) {
22349      const mappedPropName = this._schemaRegistry.getMappedPropName(boundProp.name);
22350
22351      boundPropertyName = mapPropertyName ? mappedPropName : boundProp.name;
22352      securityContexts = calcPossibleSecurityContexts(this._schemaRegistry, elementSelector, mappedPropName, false);
22353      bindingType = 0
22354      /* BindingType.Property */
22355      ;
22356
22357      if (!skipValidation) {
22358        this._validatePropertyOrAttributeName(mappedPropName, boundProp.sourceSpan, false);
22359      }
22360    }
22361
22362    return new BoundElementProperty(boundPropertyName, bindingType, securityContexts[0], boundProp.expression, unit, boundProp.sourceSpan, boundProp.keySpan, boundProp.valueSpan);
22363  } // TODO: keySpan should be required but was made optional to avoid changing VE parser.
22364
22365
22366  parseEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
22367    if (name.length === 0) {
22368      this._reportError(`Event name is missing in binding`, sourceSpan);
22369    }
22370
22371    if (isAnimationLabel(name)) {
22372      name = name.slice(1);
22373
22374      if (keySpan !== undefined) {
22375        keySpan = moveParseSourceSpan(keySpan, new AbsoluteSourceSpan(keySpan.start.offset + 1, keySpan.end.offset));
22376      }
22377
22378      this._parseAnimationEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetEvents, keySpan);
22379    } else {
22380      this._parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan);
22381    }
22382  }
22383
22384  calcPossibleSecurityContexts(selector, propName, isAttribute) {
22385    const prop = this._schemaRegistry.getMappedPropName(propName);
22386
22387    return calcPossibleSecurityContexts(this._schemaRegistry, selector, prop, isAttribute);
22388  }
22389
22390  _parseAnimationEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetEvents, keySpan) {
22391    const matches = splitAtPeriod(name, [name, '']);
22392    const eventName = matches[0];
22393    const phase = matches[1].toLowerCase();
22394
22395    const ast = this._parseAction(expression, isAssignmentEvent, handlerSpan);
22396
22397    targetEvents.push(new ParsedEvent(eventName, phase, 1
22398    /* ParsedEventType.Animation */
22399    , ast, sourceSpan, handlerSpan, keySpan));
22400
22401    if (eventName.length === 0) {
22402      this._reportError(`Animation event name is missing in binding`, sourceSpan);
22403    }
22404
22405    if (phase) {
22406      if (phase !== 'start' && phase !== 'done') {
22407        this._reportError(`The provided animation output phase value "${phase}" for "@${eventName}" is not supported (use start or done)`, sourceSpan);
22408      }
22409    } else {
22410      this._reportError(`The animation trigger output event (@${eventName}) is missing its phase value name (start or done are currently supported)`, sourceSpan);
22411    }
22412  }
22413
22414  _parseRegularEvent(name, expression, isAssignmentEvent, sourceSpan, handlerSpan, targetMatchableAttrs, targetEvents, keySpan) {
22415    // long format: 'target: eventName'
22416    const [target, eventName] = splitAtColon(name, [null, name]);
22417
22418    const ast = this._parseAction(expression, isAssignmentEvent, handlerSpan);
22419
22420    targetMatchableAttrs.push([name, ast.source]);
22421    targetEvents.push(new ParsedEvent(eventName, target, 0
22422    /* ParsedEventType.Regular */
22423    , ast, sourceSpan, handlerSpan, keySpan)); // Don't detect directives for event names for now,
22424    // so don't add the event name to the matchableAttrs
22425  }
22426
22427  _parseAction(value, isAssignmentEvent, sourceSpan) {
22428    const sourceInfo = (sourceSpan && sourceSpan.start || '(unknown').toString();
22429    const absoluteOffset = sourceSpan && sourceSpan.start ? sourceSpan.start.offset : 0;
22430
22431    try {
22432      const ast = this._exprParser.parseAction(value, isAssignmentEvent, sourceInfo, absoluteOffset, this._interpolationConfig);
22433
22434      if (ast) {
22435        this._reportExpressionParserErrors(ast.errors, sourceSpan);
22436      }
22437
22438      if (!ast || ast.ast instanceof EmptyExpr) {
22439        this._reportError(`Empty expressions are not allowed`, sourceSpan);
22440
22441        return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
22442      }
22443
22444      return ast;
22445    } catch (e) {
22446      this._reportError(`${e}`, sourceSpan);
22447
22448      return this._exprParser.wrapLiteralPrimitive('ERROR', sourceInfo, absoluteOffset);
22449    }
22450  }
22451
22452  _reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) {
22453    this.errors.push(new ParseError(sourceSpan, message, level));
22454  }
22455
22456  _reportExpressionParserErrors(errors, sourceSpan) {
22457    for (const error of errors) {
22458      this._reportError(error.message, sourceSpan);
22459    }
22460  }
22461  /**
22462   * @param propName the name of the property / attribute
22463   * @param sourceSpan
22464   * @param isAttr true when binding to an attribute
22465   */
22466
22467
22468  _validatePropertyOrAttributeName(propName, sourceSpan, isAttr) {
22469    const report = isAttr ? this._schemaRegistry.validateAttribute(propName) : this._schemaRegistry.validateProperty(propName);
22470
22471    if (report.error) {
22472      this._reportError(report.msg, sourceSpan, ParseErrorLevel.ERROR);
22473    }
22474  }
22475
22476}
22477
22478class PipeCollector extends RecursiveAstVisitor {
22479  constructor() {
22480    super(...arguments);
22481    this.pipes = new Map();
22482  }
22483
22484  visitPipe(ast, context) {
22485    this.pipes.set(ast.name, ast);
22486    ast.exp.visit(this);
22487    this.visitAll(ast.args, context);
22488    return null;
22489  }
22490
22491}
22492
22493function isAnimationLabel(name) {
22494  return name[0] == '@';
22495}
22496
22497function calcPossibleSecurityContexts(registry, selector, propName, isAttribute) {
22498  const ctxs = [];
22499  CssSelector.parse(selector).forEach(selector => {
22500    const elementNames = selector.element ? [selector.element] : registry.allKnownElementNames();
22501    const notElementNames = new Set(selector.notSelectors.filter(selector => selector.isElementSelector()).map(selector => selector.element));
22502    const possibleElementNames = elementNames.filter(elementName => !notElementNames.has(elementName));
22503    ctxs.push(...possibleElementNames.map(elementName => registry.securityContext(elementName, propName, isAttribute)));
22504  });
22505  return ctxs.length === 0 ? [SecurityContext.NONE] : Array.from(new Set(ctxs)).sort();
22506}
22507/**
22508 * Compute a new ParseSourceSpan based off an original `sourceSpan` by using
22509 * absolute offsets from the specified `absoluteSpan`.
22510 *
22511 * @param sourceSpan original source span
22512 * @param absoluteSpan absolute source span to move to
22513 */
22514
22515
22516function moveParseSourceSpan(sourceSpan, absoluteSpan) {
22517  // The difference of two absolute offsets provide the relative offset
22518  const startDiff = absoluteSpan.start - sourceSpan.start.offset;
22519  const endDiff = absoluteSpan.end - sourceSpan.end.offset;
22520  return new ParseSourceSpan(sourceSpan.start.moveBy(startDiff), sourceSpan.end.moveBy(endDiff), sourceSpan.fullStart.moveBy(startDiff), sourceSpan.details);
22521}
22522/**
22523 * @license
22524 * Copyright Google LLC All Rights Reserved.
22525 *
22526 * Use of this source code is governed by an MIT-style license that can be
22527 * found in the LICENSE file at https://angular.io/license
22528 */
22529// Some of the code comes from WebComponents.JS
22530// https://github.com/webcomponents/webcomponentsjs/blob/master/src/HTMLImports/path.js
22531
22532
22533function isStyleUrlResolvable(url) {
22534  if (url == null || url.length === 0 || url[0] == '/') return false;
22535  const schemeMatch = url.match(URL_WITH_SCHEMA_REGEXP);
22536  return schemeMatch === null || schemeMatch[1] == 'package' || schemeMatch[1] == 'asset';
22537}
22538
22539const URL_WITH_SCHEMA_REGEXP = /^([^:/?#]+):/;
22540/**
22541 * @license
22542 * Copyright Google LLC All Rights Reserved.
22543 *
22544 * Use of this source code is governed by an MIT-style license that can be
22545 * found in the LICENSE file at https://angular.io/license
22546 */
22547
22548const NG_CONTENT_SELECT_ATTR$1 = 'select';
22549const LINK_ELEMENT = 'link';
22550const LINK_STYLE_REL_ATTR = 'rel';
22551const LINK_STYLE_HREF_ATTR = 'href';
22552const LINK_STYLE_REL_VALUE = 'stylesheet';
22553const STYLE_ELEMENT = 'style';
22554const SCRIPT_ELEMENT = 'script';
22555const NG_NON_BINDABLE_ATTR = 'ngNonBindable';
22556const NG_PROJECT_AS = 'ngProjectAs';
22557
22558function preparseElement(ast) {
22559  let selectAttr = null;
22560  let hrefAttr = null;
22561  let relAttr = null;
22562  let nonBindable = false;
22563  let projectAs = '';
22564  ast.attrs.forEach(attr => {
22565    const lcAttrName = attr.name.toLowerCase();
22566
22567    if (lcAttrName == NG_CONTENT_SELECT_ATTR$1) {
22568      selectAttr = attr.value;
22569    } else if (lcAttrName == LINK_STYLE_HREF_ATTR) {
22570      hrefAttr = attr.value;
22571    } else if (lcAttrName == LINK_STYLE_REL_ATTR) {
22572      relAttr = attr.value;
22573    } else if (attr.name == NG_NON_BINDABLE_ATTR) {
22574      nonBindable = true;
22575    } else if (attr.name == NG_PROJECT_AS) {
22576      if (attr.value.length > 0) {
22577        projectAs = attr.value;
22578      }
22579    }
22580  });
22581  selectAttr = normalizeNgContentSelect(selectAttr);
22582  const nodeName = ast.name.toLowerCase();
22583  let type = PreparsedElementType.OTHER;
22584
22585  if (isNgContent(nodeName)) {
22586    type = PreparsedElementType.NG_CONTENT;
22587  } else if (nodeName == STYLE_ELEMENT) {
22588    type = PreparsedElementType.STYLE;
22589  } else if (nodeName == SCRIPT_ELEMENT) {
22590    type = PreparsedElementType.SCRIPT;
22591  } else if (nodeName == LINK_ELEMENT && relAttr == LINK_STYLE_REL_VALUE) {
22592    type = PreparsedElementType.STYLESHEET;
22593  }
22594
22595  return new PreparsedElement(type, selectAttr, hrefAttr, nonBindable, projectAs);
22596}
22597
22598var PreparsedElementType;
22599
22600(function (PreparsedElementType) {
22601  PreparsedElementType[PreparsedElementType["NG_CONTENT"] = 0] = "NG_CONTENT";
22602  PreparsedElementType[PreparsedElementType["STYLE"] = 1] = "STYLE";
22603  PreparsedElementType[PreparsedElementType["STYLESHEET"] = 2] = "STYLESHEET";
22604  PreparsedElementType[PreparsedElementType["SCRIPT"] = 3] = "SCRIPT";
22605  PreparsedElementType[PreparsedElementType["OTHER"] = 4] = "OTHER";
22606})(PreparsedElementType || (PreparsedElementType = {}));
22607
22608class PreparsedElement {
22609  constructor(type, selectAttr, hrefAttr, nonBindable, projectAs) {
22610    this.type = type;
22611    this.selectAttr = selectAttr;
22612    this.hrefAttr = hrefAttr;
22613    this.nonBindable = nonBindable;
22614    this.projectAs = projectAs;
22615  }
22616
22617}
22618
22619function normalizeNgContentSelect(selectAttr) {
22620  if (selectAttr === null || selectAttr.length === 0) {
22621    return '*';
22622  }
22623
22624  return selectAttr;
22625}
22626/**
22627 * @license
22628 * Copyright Google LLC All Rights Reserved.
22629 *
22630 * Use of this source code is governed by an MIT-style license that can be
22631 * found in the LICENSE file at https://angular.io/license
22632 */
22633
22634
22635const BIND_NAME_REGEXP = /^(?:(bind-)|(let-)|(ref-|#)|(on-)|(bindon-)|(@))(.*)$/; // Group 1 = "bind-"
22636
22637const KW_BIND_IDX = 1; // Group 2 = "let-"
22638
22639const KW_LET_IDX = 2; // Group 3 = "ref-/#"
22640
22641const KW_REF_IDX = 3; // Group 4 = "on-"
22642
22643const KW_ON_IDX = 4; // Group 5 = "bindon-"
22644
22645const KW_BINDON_IDX = 5; // Group 6 = "@"
22646
22647const KW_AT_IDX = 6; // Group 7 = the identifier after "bind-", "let-", "ref-/#", "on-", "bindon-" or "@"
22648
22649const IDENT_KW_IDX = 7;
22650const BINDING_DELIMS = {
22651  BANANA_BOX: {
22652    start: '[(',
22653    end: ')]'
22654  },
22655  PROPERTY: {
22656    start: '[',
22657    end: ']'
22658  },
22659  EVENT: {
22660    start: '(',
22661    end: ')'
22662  }
22663};
22664const TEMPLATE_ATTR_PREFIX = '*';
22665
22666function htmlAstToRender3Ast(htmlNodes, bindingParser, options) {
22667  const transformer = new HtmlAstToIvyAst(bindingParser, options);
22668  const ivyNodes = visitAll(transformer, htmlNodes); // Errors might originate in either the binding parser or the html to ivy transformer
22669
22670  const allErrors = bindingParser.errors.concat(transformer.errors);
22671  const result = {
22672    nodes: ivyNodes,
22673    errors: allErrors,
22674    styleUrls: transformer.styleUrls,
22675    styles: transformer.styles,
22676    ngContentSelectors: transformer.ngContentSelectors
22677  };
22678
22679  if (options.collectCommentNodes) {
22680    result.commentNodes = transformer.commentNodes;
22681  }
22682
22683  return result;
22684}
22685
22686class HtmlAstToIvyAst {
22687  constructor(bindingParser, options) {
22688    this.bindingParser = bindingParser;
22689    this.options = options;
22690    this.errors = [];
22691    this.styles = [];
22692    this.styleUrls = [];
22693    this.ngContentSelectors = []; // This array will be populated if `Render3ParseOptions['collectCommentNodes']` is true
22694
22695    this.commentNodes = [];
22696    this.inI18nBlock = false;
22697  } // HTML visitor
22698
22699
22700  visitElement(element) {
22701    const isI18nRootElement = isI18nRootNode(element.i18n);
22702
22703    if (isI18nRootElement) {
22704      if (this.inI18nBlock) {
22705        this.reportError('Cannot mark an element as translatable inside of a translatable section. Please remove the nested i18n marker.', element.sourceSpan);
22706      }
22707
22708      this.inI18nBlock = true;
22709    }
22710
22711    const preparsedElement = preparseElement(element);
22712
22713    if (preparsedElement.type === PreparsedElementType.SCRIPT) {
22714      return null;
22715    } else if (preparsedElement.type === PreparsedElementType.STYLE) {
22716      const contents = textContents(element);
22717
22718      if (contents !== null) {
22719        this.styles.push(contents);
22720      }
22721
22722      return null;
22723    } else if (preparsedElement.type === PreparsedElementType.STYLESHEET && isStyleUrlResolvable(preparsedElement.hrefAttr)) {
22724      this.styleUrls.push(preparsedElement.hrefAttr);
22725      return null;
22726    } // Whether the element is a `<ng-template>`
22727
22728
22729    const isTemplateElement = isNgTemplate(element.name);
22730    const parsedProperties = [];
22731    const boundEvents = [];
22732    const variables = [];
22733    const references = [];
22734    const attributes = [];
22735    const i18nAttrsMeta = {};
22736    const templateParsedProperties = [];
22737    const templateVariables = []; // Whether the element has any *-attribute
22738
22739    let elementHasInlineTemplate = false;
22740
22741    for (const attribute of element.attrs) {
22742      let hasBinding = false;
22743      const normalizedName = normalizeAttributeName(attribute.name); // `*attr` defines template bindings
22744
22745      let isTemplateBinding = false;
22746
22747      if (attribute.i18n) {
22748        i18nAttrsMeta[attribute.name] = attribute.i18n;
22749      }
22750
22751      if (normalizedName.startsWith(TEMPLATE_ATTR_PREFIX)) {
22752        // *-attributes
22753        if (elementHasInlineTemplate) {
22754          this.reportError(`Can't have multiple template bindings on one element. Use only one attribute prefixed with *`, attribute.sourceSpan);
22755        }
22756
22757        isTemplateBinding = true;
22758        elementHasInlineTemplate = true;
22759        const templateValue = attribute.value;
22760        const templateKey = normalizedName.substring(TEMPLATE_ATTR_PREFIX.length);
22761        const parsedVariables = [];
22762        const absoluteValueOffset = attribute.valueSpan ? attribute.valueSpan.start.offset : // If there is no value span the attribute does not have a value, like `attr` in
22763        //`<div attr></div>`. In this case, point to one character beyond the last character of
22764        // the attribute name.
22765        attribute.sourceSpan.start.offset + attribute.name.length;
22766        this.bindingParser.parseInlineTemplateBinding(templateKey, templateValue, attribute.sourceSpan, absoluteValueOffset, [], templateParsedProperties, parsedVariables, true
22767        /* isIvyAst */
22768        );
22769        templateVariables.push(...parsedVariables.map(v => new Variable(v.name, v.value, v.sourceSpan, v.keySpan, v.valueSpan)));
22770      } else {
22771        // Check for variables, events, property bindings, interpolation
22772        hasBinding = this.parseAttribute(isTemplateElement, attribute, [], parsedProperties, boundEvents, variables, references);
22773      }
22774
22775      if (!hasBinding && !isTemplateBinding) {
22776        // don't include the bindings as attributes as well in the AST
22777        attributes.push(this.visitAttribute(attribute));
22778      }
22779    }
22780
22781    const children = visitAll(preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children);
22782    let parsedElement;
22783
22784    if (preparsedElement.type === PreparsedElementType.NG_CONTENT) {
22785      // `<ng-content>`
22786      if (element.children && !element.children.every(node => isEmptyTextNode(node) || isCommentNode(node))) {
22787        this.reportError(`<ng-content> element cannot have content.`, element.sourceSpan);
22788      }
22789
22790      const selector = preparsedElement.selectAttr;
22791      const attrs = element.attrs.map(attr => this.visitAttribute(attr));
22792      parsedElement = new Content(selector, attrs, element.sourceSpan, element.i18n);
22793      this.ngContentSelectors.push(selector);
22794    } else if (isTemplateElement) {
22795      // `<ng-template>`
22796      const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta);
22797      parsedElement = new Template(element.name, attributes, attrs.bound, boundEvents, [
22798        /* no template attributes */
22799      ], children, references, variables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
22800    } else {
22801      const attrs = this.extractAttributes(element.name, parsedProperties, i18nAttrsMeta);
22802      parsedElement = new Element$1(element.name, attributes, attrs.bound, boundEvents, children, references, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, element.i18n);
22803    }
22804
22805    if (elementHasInlineTemplate) {
22806      // If this node is an inline-template (e.g. has *ngFor) then we need to create a template
22807      // node that contains this node.
22808      // Moreover, if the node is an element, then we need to hoist its attributes to the template
22809      // node for matching against content projection selectors.
22810      const attrs = this.extractAttributes('ng-template', templateParsedProperties, i18nAttrsMeta);
22811      const templateAttrs = [];
22812      attrs.literal.forEach(attr => templateAttrs.push(attr));
22813      attrs.bound.forEach(attr => templateAttrs.push(attr));
22814      const hoistedAttrs = parsedElement instanceof Element$1 ? {
22815        attributes: parsedElement.attributes,
22816        inputs: parsedElement.inputs,
22817        outputs: parsedElement.outputs
22818      } : {
22819        attributes: [],
22820        inputs: [],
22821        outputs: []
22822      }; // For <ng-template>s with structural directives on them, avoid passing i18n information to
22823      // the wrapping template to prevent unnecessary i18n instructions from being generated. The
22824      // necessary i18n meta information will be extracted from child elements.
22825
22826      const i18n = isTemplateElement && isI18nRootElement ? undefined : element.i18n;
22827      const name = parsedElement instanceof Template ? null : parsedElement.name;
22828      parsedElement = new Template(name, hoistedAttrs.attributes, hoistedAttrs.inputs, hoistedAttrs.outputs, templateAttrs, [parsedElement], [
22829        /* no references */
22830      ], templateVariables, element.sourceSpan, element.startSourceSpan, element.endSourceSpan, i18n);
22831    }
22832
22833    if (isI18nRootElement) {
22834      this.inI18nBlock = false;
22835    }
22836
22837    return parsedElement;
22838  }
22839
22840  visitAttribute(attribute) {
22841    return new TextAttribute(attribute.name, attribute.value, attribute.sourceSpan, attribute.keySpan, attribute.valueSpan, attribute.i18n);
22842  }
22843
22844  visitText(text) {
22845    return this._visitTextWithInterpolation(text.value, text.sourceSpan, text.tokens, text.i18n);
22846  }
22847
22848  visitExpansion(expansion) {
22849    if (!expansion.i18n) {
22850      // do not generate Icu in case it was created
22851      // outside of i18n block in a template
22852      return null;
22853    }
22854
22855    if (!isI18nRootNode(expansion.i18n)) {
22856      throw new Error(`Invalid type "${expansion.i18n.constructor}" for "i18n" property of ${expansion.sourceSpan.toString()}. Expected a "Message"`);
22857    }
22858
22859    const message = expansion.i18n;
22860    const vars = {};
22861    const placeholders = {}; // extract VARs from ICUs - we process them separately while
22862    // assembling resulting message via goog.getMsg function, since
22863    // we need to pass them to top-level goog.getMsg call
22864
22865    Object.keys(message.placeholders).forEach(key => {
22866      const value = message.placeholders[key];
22867
22868      if (key.startsWith(I18N_ICU_VAR_PREFIX)) {
22869        // Currently when the `plural` or `select` keywords in an ICU contain trailing spaces (e.g.
22870        // `{count, select , ...}`), these spaces are also included into the key names in ICU vars
22871        // (e.g. "VAR_SELECT "). These trailing spaces are not desirable, since they will later be
22872        // converted into `_` symbols while normalizing placeholder names, which might lead to
22873        // mismatches at runtime (i.e. placeholder will not be replaced with the correct value).
22874        const formattedKey = key.trim();
22875        const ast = this.bindingParser.parseInterpolationExpression(value.text, value.sourceSpan);
22876        vars[formattedKey] = new BoundText(ast, value.sourceSpan);
22877      } else {
22878        placeholders[key] = this._visitTextWithInterpolation(value.text, value.sourceSpan, null);
22879      }
22880    });
22881    return new Icu$1(vars, placeholders, expansion.sourceSpan, message);
22882  }
22883
22884  visitExpansionCase(expansionCase) {
22885    return null;
22886  }
22887
22888  visitComment(comment) {
22889    if (this.options.collectCommentNodes) {
22890      this.commentNodes.push(new Comment$1(comment.value || '', comment.sourceSpan));
22891    }
22892
22893    return null;
22894  } // convert view engine `ParsedProperty` to a format suitable for IVY
22895
22896
22897  extractAttributes(elementName, properties, i18nPropsMeta) {
22898    const bound = [];
22899    const literal = [];
22900    properties.forEach(prop => {
22901      const i18n = i18nPropsMeta[prop.name];
22902
22903      if (prop.isLiteral) {
22904        literal.push(new TextAttribute(prop.name, prop.expression.source || '', prop.sourceSpan, prop.keySpan, prop.valueSpan, i18n));
22905      } else {
22906        // Note that validation is skipped and property mapping is disabled
22907        // due to the fact that we need to make sure a given prop is not an
22908        // input of a directive and directive matching happens at runtime.
22909        const bep = this.bindingParser.createBoundElementProperty(elementName, prop,
22910        /* skipValidation */
22911        true,
22912        /* mapPropertyName */
22913        false);
22914        bound.push(BoundAttribute.fromBoundElementProperty(bep, i18n));
22915      }
22916    });
22917    return {
22918      bound,
22919      literal
22920    };
22921  }
22922
22923  parseAttribute(isTemplateElement, attribute, matchableAttributes, parsedProperties, boundEvents, variables, references) {
22924    const name = normalizeAttributeName(attribute.name);
22925    const value = attribute.value;
22926    const srcSpan = attribute.sourceSpan;
22927    const absoluteOffset = attribute.valueSpan ? attribute.valueSpan.start.offset : srcSpan.start.offset;
22928
22929    function createKeySpan(srcSpan, prefix, identifier) {
22930      // We need to adjust the start location for the keySpan to account for the removed 'data-'
22931      // prefix from `normalizeAttributeName`.
22932      const normalizationAdjustment = attribute.name.length - name.length;
22933      const keySpanStart = srcSpan.start.moveBy(prefix.length + normalizationAdjustment);
22934      const keySpanEnd = keySpanStart.moveBy(identifier.length);
22935      return new ParseSourceSpan(keySpanStart, keySpanEnd, keySpanStart, identifier);
22936    }
22937
22938    const bindParts = name.match(BIND_NAME_REGEXP);
22939
22940    if (bindParts) {
22941      if (bindParts[KW_BIND_IDX] != null) {
22942        const identifier = bindParts[IDENT_KW_IDX];
22943        const keySpan = createKeySpan(srcSpan, bindParts[KW_BIND_IDX], identifier);
22944        this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
22945      } else if (bindParts[KW_LET_IDX]) {
22946        if (isTemplateElement) {
22947          const identifier = bindParts[IDENT_KW_IDX];
22948          const keySpan = createKeySpan(srcSpan, bindParts[KW_LET_IDX], identifier);
22949          this.parseVariable(identifier, value, srcSpan, keySpan, attribute.valueSpan, variables);
22950        } else {
22951          this.reportError(`"let-" is only supported on ng-template elements.`, srcSpan);
22952        }
22953      } else if (bindParts[KW_REF_IDX]) {
22954        const identifier = bindParts[IDENT_KW_IDX];
22955        const keySpan = createKeySpan(srcSpan, bindParts[KW_REF_IDX], identifier);
22956        this.parseReference(identifier, value, srcSpan, keySpan, attribute.valueSpan, references);
22957      } else if (bindParts[KW_ON_IDX]) {
22958        const events = [];
22959        const identifier = bindParts[IDENT_KW_IDX];
22960        const keySpan = createKeySpan(srcSpan, bindParts[KW_ON_IDX], identifier);
22961        this.bindingParser.parseEvent(identifier, value,
22962        /* isAssignmentEvent */
22963        false, srcSpan, attribute.valueSpan || srcSpan, matchableAttributes, events, keySpan);
22964        addEvents(events, boundEvents);
22965      } else if (bindParts[KW_BINDON_IDX]) {
22966        const identifier = bindParts[IDENT_KW_IDX];
22967        const keySpan = createKeySpan(srcSpan, bindParts[KW_BINDON_IDX], identifier);
22968        this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
22969        this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan);
22970      } else if (bindParts[KW_AT_IDX]) {
22971        const keySpan = createKeySpan(srcSpan, '', name);
22972        this.bindingParser.parseLiteralAttr(name, value, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
22973      }
22974
22975      return true;
22976    } // We didn't see a kw-prefixed property binding, but we have not yet checked
22977    // for the []/()/[()] syntax.
22978
22979
22980    let delims = null;
22981
22982    if (name.startsWith(BINDING_DELIMS.BANANA_BOX.start)) {
22983      delims = BINDING_DELIMS.BANANA_BOX;
22984    } else if (name.startsWith(BINDING_DELIMS.PROPERTY.start)) {
22985      delims = BINDING_DELIMS.PROPERTY;
22986    } else if (name.startsWith(BINDING_DELIMS.EVENT.start)) {
22987      delims = BINDING_DELIMS.EVENT;
22988    }
22989
22990    if (delims !== null && // NOTE: older versions of the parser would match a start/end delimited
22991    // binding iff the property name was terminated by the ending delimiter
22992    // and the identifier in the binding was non-empty.
22993    // TODO(ayazhafiz): update this to handle malformed bindings.
22994    name.endsWith(delims.end) && name.length > delims.start.length + delims.end.length) {
22995      const identifier = name.substring(delims.start.length, name.length - delims.end.length);
22996      const keySpan = createKeySpan(srcSpan, delims.start, identifier);
22997
22998      if (delims.start === BINDING_DELIMS.BANANA_BOX.start) {
22999        this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
23000        this.parseAssignmentEvent(identifier, value, srcSpan, attribute.valueSpan, matchableAttributes, boundEvents, keySpan);
23001      } else if (delims.start === BINDING_DELIMS.PROPERTY.start) {
23002        this.bindingParser.parsePropertyBinding(identifier, value, false, srcSpan, absoluteOffset, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan);
23003      } else {
23004        const events = [];
23005        this.bindingParser.parseEvent(identifier, value,
23006        /* isAssignmentEvent */
23007        false, srcSpan, attribute.valueSpan || srcSpan, matchableAttributes, events, keySpan);
23008        addEvents(events, boundEvents);
23009      }
23010
23011      return true;
23012    } // No explicit binding found.
23013
23014
23015    const keySpan = createKeySpan(srcSpan, ''
23016    /* prefix */
23017    , name);
23018    const hasBinding = this.bindingParser.parsePropertyInterpolation(name, value, srcSpan, attribute.valueSpan, matchableAttributes, parsedProperties, keySpan, attribute.valueTokens ?? null);
23019    return hasBinding;
23020  }
23021
23022  _visitTextWithInterpolation(value, sourceSpan, interpolatedTokens, i18n) {
23023    const valueNoNgsp = replaceNgsp(value);
23024    const expr = this.bindingParser.parseInterpolation(valueNoNgsp, sourceSpan, interpolatedTokens);
23025    return expr ? new BoundText(expr, sourceSpan, i18n) : new Text$3(valueNoNgsp, sourceSpan);
23026  }
23027
23028  parseVariable(identifier, value, sourceSpan, keySpan, valueSpan, variables) {
23029    if (identifier.indexOf('-') > -1) {
23030      this.reportError(`"-" is not allowed in variable names`, sourceSpan);
23031    } else if (identifier.length === 0) {
23032      this.reportError(`Variable does not have a name`, sourceSpan);
23033    }
23034
23035    variables.push(new Variable(identifier, value, sourceSpan, keySpan, valueSpan));
23036  }
23037
23038  parseReference(identifier, value, sourceSpan, keySpan, valueSpan, references) {
23039    if (identifier.indexOf('-') > -1) {
23040      this.reportError(`"-" is not allowed in reference names`, sourceSpan);
23041    } else if (identifier.length === 0) {
23042      this.reportError(`Reference does not have a name`, sourceSpan);
23043    } else if (references.some(reference => reference.name === identifier)) {
23044      this.reportError(`Reference "#${identifier}" is defined more than once`, sourceSpan);
23045    }
23046
23047    references.push(new Reference(identifier, value, sourceSpan, keySpan, valueSpan));
23048  }
23049
23050  parseAssignmentEvent(name, expression, sourceSpan, valueSpan, targetMatchableAttrs, boundEvents, keySpan) {
23051    const events = [];
23052    this.bindingParser.parseEvent(`${name}Change`, `${expression} =$event`,
23053    /* isAssignmentEvent */
23054    true, sourceSpan, valueSpan || sourceSpan, targetMatchableAttrs, events, keySpan);
23055    addEvents(events, boundEvents);
23056  }
23057
23058  reportError(message, sourceSpan, level = ParseErrorLevel.ERROR) {
23059    this.errors.push(new ParseError(sourceSpan, message, level));
23060  }
23061
23062}
23063
23064class NonBindableVisitor {
23065  visitElement(ast) {
23066    const preparsedElement = preparseElement(ast);
23067
23068    if (preparsedElement.type === PreparsedElementType.SCRIPT || preparsedElement.type === PreparsedElementType.STYLE || preparsedElement.type === PreparsedElementType.STYLESHEET) {
23069      // Skipping <script> for security reasons
23070      // Skipping <style> and stylesheets as we already processed them
23071      // in the StyleCompiler
23072      return null;
23073    }
23074
23075    const children = visitAll(this, ast.children, null);
23076    return new Element$1(ast.name, visitAll(this, ast.attrs),
23077    /* inputs */
23078    [],
23079    /* outputs */
23080    [], children,
23081    /* references */
23082    [], ast.sourceSpan, ast.startSourceSpan, ast.endSourceSpan);
23083  }
23084
23085  visitComment(comment) {
23086    return null;
23087  }
23088
23089  visitAttribute(attribute) {
23090    return new TextAttribute(attribute.name, attribute.value, attribute.sourceSpan, attribute.keySpan, attribute.valueSpan, attribute.i18n);
23091  }
23092
23093  visitText(text) {
23094    return new Text$3(text.value, text.sourceSpan);
23095  }
23096
23097  visitExpansion(expansion) {
23098    return null;
23099  }
23100
23101  visitExpansionCase(expansionCase) {
23102    return null;
23103  }
23104
23105}
23106
23107const NON_BINDABLE_VISITOR = new NonBindableVisitor();
23108
23109function normalizeAttributeName(attrName) {
23110  return /^data-/i.test(attrName) ? attrName.substring(5) : attrName;
23111}
23112
23113function addEvents(events, boundEvents) {
23114  boundEvents.push(...events.map(e => BoundEvent.fromParsedEvent(e)));
23115}
23116
23117function isEmptyTextNode(node) {
23118  return node instanceof Text && node.value.trim().length == 0;
23119}
23120
23121function isCommentNode(node) {
23122  return node instanceof Comment;
23123}
23124
23125function textContents(node) {
23126  if (node.children.length !== 1 || !(node.children[0] instanceof Text)) {
23127    return null;
23128  } else {
23129    return node.children[0].value;
23130  }
23131}
23132/**
23133 * @license
23134 * Copyright Google LLC All Rights Reserved.
23135 *
23136 * Use of this source code is governed by an MIT-style license that can be
23137 * found in the LICENSE file at https://angular.io/license
23138 */
23139
23140
23141var TagType;
23142
23143(function (TagType) {
23144  TagType[TagType["ELEMENT"] = 0] = "ELEMENT";
23145  TagType[TagType["TEMPLATE"] = 1] = "TEMPLATE";
23146})(TagType || (TagType = {}));
23147/**
23148 * Generates an object that is used as a shared state between parent and all child contexts.
23149 */
23150
23151
23152function setupRegistry() {
23153  return {
23154    getUniqueId: getSeqNumberGenerator(),
23155    icus: new Map()
23156  };
23157}
23158/**
23159 * I18nContext is a helper class which keeps track of all i18n-related as
23159pects
23160 * (accumulates placeholders, bindings, etc) between i18nStart and i18nEnd instructions.
23161 *
23162 * When we enter a nested template, the top-level context is being passed down
23163 * to the nested component, which uses this context to generate a child instance
23164 * of I18nContext class (to handle nested template) and at the end, reconciles it back
23165 * with the parent context.
23166 *
23167 * @param index Instruction index of i18nStart, which initiates this context
23168 * @param ref Reference to a translation const that represents the content if thus context
23169 * @param level Nesting level defined for child contexts
23170 * @param templateIndex Instruction index of a template which this context belongs to
23171 * @param meta Meta information (id, meaning, description, etc) associated with this context
23172 */
23173
23174
23175class I18nContext {
23176  constructor(index, ref, level = 0, templateIndex = null, meta, registry) {
23177    this.index = index;
23178    this.ref = ref;
23179    this.level = level;
23180    this.templateIndex = templateIndex;
23181    this.meta = meta;
23182    this.registry = registry;
23183    this.bindings = new Set();
23184    this.placeholders = new Map();
23185    this.isEmitted = false;
23186    this._unresolvedCtxCount = 0;
23187    this._registry = registry || setupRegistry();
23188    this.id = this._registry.getUniqueId();
23189  }
23190
23191  appendTag(type, node, index, closed) {
23192    if (node.isVoid && closed) {
23193      return; // ignore "close" for void tags
23194    }
23195
23196    const ph = node.isVoid || !closed ? node.startName : node.closeName;
23197    const content = {
23198      type,
23199      index,
23200      ctx: this.id,
23201      isVoid: node.isVoid,
23202      closed
23203    };
23204    updatePlaceholderMap(this.placeholders, ph, content);
23205  }
23206
23207  get icus() {
23208    return this._registry.icus;
23209  }
23210
23211  get isRoot() {
23212    return this.level === 0;
23213  }
23214
23215  get isResolved() {
23216    return this._unresolvedCtxCount === 0;
23217  }
23218
23219  getSerializedPlaceholders() {
23220    const result = new Map();
23221    this.placeholders.forEach((values, key) => result.set(key, values.map(serializePlaceholderValue)));
23222    return result;
23223  } // public API to accumulate i18n-related content
23224
23225
23226  appendBinding(binding) {
23227    this.bindings.add(binding);
23228  }
23229
23230  appendIcu(name, ref) {
23231    updatePlaceholderMap(this._registry.icus, name, ref);
23232  }
23233
23234  appendBoundText(node) {
23235    const phs = assembleBoundTextPlaceholders(node, this.bindings.size, this.id);
23236    phs.forEach((values, key) => updatePlaceholderMap(this.placeholders, key, ...values));
23237  }
23238
23239  appendTemplate(node, index) {
23240    // add open and close tags at the same time,
23241    // since we process nested templates separately
23242    this.appendTag(TagType.TEMPLATE, node, index, false);
23243    this.appendTag(TagType.TEMPLATE, node, index, true);
23244    this._unresolvedCtxCount++;
23245  }
23246
23247  appendElement(node, index, closed) {
23248    this.appendTag(TagType.ELEMENT, node, index, closed);
23249  }
23250
23251  appendProjection(node, index) {
23252    // Add open and close tags at the same time, since `<ng-content>` has no content,
23253    // so when we come across `<ng-content>` we can register both open and close tags.
23254    // Note: runtime i18n logic doesn't distinguish `<ng-content>` tag placeholders and
23255    // regular element tag placeholders, so we generate element placeholders for both types.
23256    this.appendTag(TagType.ELEMENT, node, index, false);
23257    this.appendTag(TagType.ELEMENT, node, index, true);
23258  }
23259  /**
23260   * Generates an instance of a child context based on the root one,
23261   * when we enter a nested template within I18n section.
23262   *
23263   * @param index Instruction index of corresponding i18nStart, which initiates this context
23264   * @param templateIndex Instruction index of a template which this context belongs to
23265   * @param meta Meta information (id, meaning, description, etc) associated with this context
23266   *
23267   * @returns I18nContext instance
23268   */
23269
23270
23271  forkChildContext(index, templateIndex, meta) {
23272    return new I18nContext(index, this.ref, this.level + 1, templateIndex, meta, this._registry);
23273  }
23274  /**
23275   * Reconciles child context into parent one once the end of the i18n block is reached (i18nEnd).
23276   *
23277   * @param context Child I18nContext instance to be reconciled with parent context.
23278   */
23279
23280
23281  reconcileChildContext(context) {
23282    // set the right context id for open and close
23283    // template tags, so we can use it as sub-block ids
23284    ['start', 'close'].forEach(op => {
23285      const key = context.meta[`${op}Name`];
23286      const phs = this.placeholders.get(key) || [];
23287      const tag = phs.find(findTemplateFn(this.id, context.templateIndex));
23288
23289      if (tag) {
23290        tag.ctx = context.id;
23291      }
23292    }); // reconcile placeholders
23293
23294    const childPhs = context.placeholders;
23295    childPhs.forEach((values, key) => {
23296      const phs = this.placeholders.get(key);
23297
23298      if (!phs) {
23299        this.placeholders.set(key, values);
23300        return;
23301      } // try to find matching template...
23302
23303
23304      const tmplIdx = phs.findIndex(findTemplateFn(context.id, context.templateIndex));
23305
23306      if (tmplIdx >= 0) {
23307        // ... if found - replace it with nested template content
23308        const isCloseTag = key.startsWith('CLOSE');
23309        const isTemplateTag = key.endsWith('NG-TEMPLATE');
23310
23311        if (isTemplateTag) {
23312          // current template's content is placed before or after
23313          // parent template tag, depending on the open/close attribute
23314          phs.splice(tmplIdx + (isCloseTag ? 0 : 1), 0, ...values);
23315        } else {
23316          const idx = isCloseTag ? values.length - 1 : 0;
23317          values[idx].tmpl = phs[tmplIdx];
23318          phs.splice(tmplIdx, 1, ...values);
23319        }
23320      } else {
23321        // ... otherwise just append content to placeholder value
23322        phs.push(...values);
23323      }
23324
23325      this.placeholders.set(key, phs);
23326    });
23327    this._unresolvedCtxCount--;
23328  }
23329
23330} //
23331// Helper methods
23332//
23333
23334
23335function wrap(symbol, index, contextId, closed) {
23336  const state = closed ? '/' : '';
23337  return wrapI18nPlaceholder(`${state}${symbol}${index}`, contextId);
23338}
23339
23340function wrapTag(symbol, {
23341  index,
23342  ctx,
23343  isVoid
23344}, closed) {
23345  return isVoid ? wrap(symbol, index, ctx) + wrap(symbol, index, ctx, true) : wrap(symbol, index, ctx, closed);
23346}
23347
23348function findTemplateFn(ctx, templateIndex) {
23349  return token => typeof token === 'object' && token.type === TagType.TEMPLATE && token.index === templateIndex && token.ctx === ctx;
23350}
23351
23352function serializePlaceholderValue(value) {
23353  const element = (data, closed) => wrapTag('#', data, closed);
23354
23355  const template = (data, closed) => wrapTag('*', data, closed);
23356
23357  const projection = (data, closed) => wrapTag('!', data, closed);
23358
23359  switch (value.type) {
23360    case TagType.ELEMENT:
23361      // close element tag
23362      if (value.closed) {
23363        return element(value, true) + (value.tmpl ? template(value.tmpl, true) : '');
23364      } // open element tag that also initiates a template
23365
23366
23367      if (value.tmpl) {
23368        return template(value.tmpl) + element(value) + (value.isVoid ? template(value.tmpl, true) : '');
23369      }
23370
23371      return element(value);
23372
23373    case TagType.TEMPLATE:
23374      return template(value, value.closed);
23375
23376    default:
23377      return value;
23378  }
23379}
23380/**
23381 * @license
23382 * Copyright Google LLC All Rights Reserved.
23383 *
23384 * Use of this source code is governed by an MIT-style license that can be
23385 * found in the LICENSE file at https://angular.io/license
23386 */
23387
23388
23389class IcuSerializerVisitor {
23390  visitText(text) {
23391    return text.value;
23392  }
23393
23394  visitContainer(container) {
23395    return container.children.map(child => child.visit(this)).join('');
23396  }
23397
23398  visitIcu(icu) {
23399    const strCases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`);
23400    const result = `{${icu.expressionPlaceholder}, ${icu.type}, ${strCases.join(' ')}}`;
23401    return result;
23402  }
23403
23404  visitTagPlaceholder(ph) {
23405    return ph.isVoid ? this.formatPh(ph.startName) : `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
23406  }
23407
23408  visitPlaceholder(ph) {
23409    return this.formatPh(ph.name);
23410  }
23411
23412  visitIcuPlaceholder(ph, context) {
23413    return this.formatPh(ph.name);
23414  }
23415
23416  formatPh(value) {
23417    return `{${formatI18nPlaceholderName(value,
23418    /* useCamelCase */
23419    false)}}`;
23420  }
23421
23422}
23423
23424const serializer = new IcuSerializerVisitor();
23425
23426function serializeIcuNode(icu) {
23427  return icu.visit(serializer);
23428}
23429/**
23430 * @license
23431 * Copyright Google LLC All Rights Reserved.
23432 *
23433 * Use of this source code is governed by an MIT-style license that can be
23434 * found in the LICENSE file at https://angular.io/license
23435 */
23436
23437
23438const TAG_TO_PLACEHOLDER_NAMES = {
23439  'A': 'LINK',
23440  'B': 'BOLD_TEXT',
23441  'BR': 'LINE_BREAK',
23442  'EM': 'EMPHASISED_TEXT',
23443  'H1': 'HEADING_LEVEL1',
23444  'H2': 'HEADING_LEVEL2',
23445  'H3': 'HEADING_LEVEL3',
23446  'H4': 'HEADING_LEVEL4',
23447  'H5': 'HEADING_LEVEL5',
23448  'H6': 'HEADING_LEVEL6',
23449  'HR': 'HORIZONTAL_RULE',
23450  'I': 'ITALIC_TEXT',
23451  'LI': 'LIST_ITEM',
23452  'LINK': 'MEDIA_LINK',
23453  'OL': 'ORDERED_LIST',
23454  'P': 'PARAGRAPH',
23455  'Q': 'QUOTATION',
23456  'S': 'STRIKETHROUGH_TEXT',
23457  'SMALL': 'SMALL_TEXT',
23458  'SUB': 'SUBSTRIPT',
23459  'SUP': 'SUPERSCRIPT',
23460  'TBODY': 'TABLE_BODY',
23461  'TD': 'TABLE_CELL',
23462  'TFOOT': 'TABLE_FOOTER',
23463  'TH': 'TABLE_HEADER_CELL',
23464  'THEAD': 'TABLE_HEADER',
23465  'TR': 'TABLE_ROW',
23466  'TT': 'MONOSPACED_TEXT',
23467  'U': 'UNDERLINED_TEXT',
23468  'UL': 'UNORDERED_LIST'
23469};
23470/**
23471 * Creates unique names for placeholder with different content.
23472 *
23473 * Returns the same placeholder name when the content is identical.
23474 */
23475
23476class PlaceholderRegistry {
23477  constructor() {
23478    // Count the occurrence of the base name top generate a unique name
23479    this._placeHolderNameCounts = {}; // Maps signature to placeholder names
23480
23481    this._signatureToName = {};
23482  }
23483
23484  getStartTagPlaceholderName(tag, attrs, isVoid) {
23485    const signature = this._hashTag(tag, attrs, isVoid);
23486
23487    if (this._signatureToName[signature]) {
23488      return this._signatureToName[signature];
23489    }
23490
23491    const upperTag = tag.toUpperCase();
23492    const baseName = TAG_TO_PLACEHOLDER_NAMES[upperTag] || `TAG_${upperTag}`;
23493
23494    const name = this._generateUniqueName(isVoid ? baseName : `START_${baseName}`);
23495
23496    this._signatureToName[signature] = name;
23497    return name;
23498  }
23499
23500  getCloseTagPlaceholderName(tag) {
23501    const signature = this._hashClosingTag(tag);
23502
23503    if (this._signatureToName[signature]) {
23504      return this._signatureToName[signature];
23505    }
23506
23507    const upperTag = tag.toUpperCase();
23508    const baseName = TAG_TO_PLACEHOLDER_NAMES[upperTag] || `TAG_${upperTag}`;
23509
23510    const name = this._generateUniqueName(`CLOSE_${baseName}`);
23511
23512    this._signatureToName[signature] = name;
23513    return name;
23514  }
23515
23516  getPlaceholderName(name, content) {
23517    const upperName = name.toUpperCase();
23518    const signature = `PH: ${upperName}=${content}`;
23519
23520    if (this._signatureToName[signature]) {
23521      return this._signatureToName[signature];
23522    }
23523
23524    const uniqueName = this._generateUniqueName(upperName);
23525
23526    this._signatureToName[signature] = uniqueName;
23527    return uniqueName;
23528  }
23529
23530  getUniquePlaceholder(name) {
23531    return this._generateUniqueName(name.toUpperCase());
23532  } // Generate a hash for a tag - does not take attribute order into account
23533
23534
23535  _hashTag(tag, attrs, isVoid) {
23536    const start = `<${tag}`;
23537    const strAttrs = Object.keys(attrs).sort().map(name => ` ${name}=${attrs[name]}`).join('');
23538    const end = isVoid ? '/>' : `></${tag}>`;
23539    return start + strAttrs + end;
23540  }
23541
23542  _hashClosingTag(tag) {
23543    return this._hashTag(`/${tag}`, {}, false);
23544  }
23545
23546  _generateUniqueName(base) {
23547    const seen = this._placeHolderNameCounts.hasOwnProperty(base);
23548
23549    if (!seen) {
23550      this._placeHolderNameCounts[base] = 1;
23551      return base;
23552    }
23553
23554    const id = this._placeHolderNameCounts[base];
23555    this._placeHolderNameCounts[base] = id + 1;
23556    return `${base}_${id}`;
23557  }
23558
23559}
23560/**
23561 * @license
23562 * Copyright Google LLC All Rights Reserved.
23563 *
23564 * Use of this source code is governed by an MIT-style license that can be
23565 * found in the LICENSE file at https://angular.io/license
23566 */
23567
23568
23569const _expParser = new Parser$1(new Lexer());
23570/**
23571 * Returns a function converting html nodes to an i18n Message given an interpolationConfig
23572 */
23573
23574
23575function createI18nMessageFactory(interpolationConfig) {
23576  const visitor = new _I18nVisitor(_expParser, interpolationConfig);
23577  return (nodes, meaning, description, customId, visitNodeFn) => visitor.toI18nMessage(nodes, meaning, description, customId, visitNodeFn);
23578}
23579
23580function noopVisitNodeFn(_html, i18n) {
23581  return i18n;
23582}
23583
23584class _I18nVisitor {
23585  constructor(_expressionParser, _interpolationConfig) {
23586    this._expressionParser = _expressionParser;
23587    this._interpolationConfig = _interpolationConfig;
23588  }
23589
23590  toI18nMessage(nodes, meaning = '', description = '', customId = '', visitNodeFn) {
23591    const context = {
23592      isIcu: nodes.length == 1 && nodes[0] instanceof Expansion,
23593      icuDepth: 0,
23594      placeholderRegistry: new PlaceholderRegistry(),
23595      placeholderToContent: {},
23596      placeholderToMessage: {},
23597      visitNodeFn: visitNodeFn || noopVisitNodeFn
23598    };
23599    const i18nodes = visitAll(this, nodes, context);
23600    return new Message(i18nodes, context.placeholderToContent, context.placeholderToMessage, meaning, description, customId);
23601  }
23602
23603  visitElement(el, context) {
23604    const children = visitAll(this, el.children, context);
23605    const attrs = {};
23606    el.attrs.forEach(attr => {
23607      // Do not visit the attributes, translatable ones are top-level ASTs
23608      attrs[attr.name] = attr.value;
23609    });
23610    const isVoid = getHtmlTagDefinition(el.name).isVoid;
23611    const startPhName = context.placeholderRegistry.getStartTagPlaceholderName(el.name, attrs, isVoid);
23612    context.placeholderToContent[startPhName] = {
23613      text: el.startSourceSpan.toString(),
23614      sourceSpan: el.startSourceSpan
23615    };
23616    let closePhName = '';
23617
23618    if (!isVoid) {
23619      closePhName = context.placeholderRegistry.getCloseTagPlaceholderName(el.name);
23620      context.placeholderToContent[closePhName] = {
23621        text: `</${el.name}>`,
23622        sourceSpan: el.endSourceSpan ?? el.sourceSpan
23623      };
23624    }
23625
23626    const node = new TagPlaceholder(el.name, attrs, startPhName, closePhName, children, isVoid, el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
23627    return context.visitNodeFn(el, node);
23628  }
23629
23630  visitAttribute(attribute, context) {
23631    const node = attribute.valueTokens === undefined || attribute.valueTokens.length === 1 ? new Text$2(attribute.value, attribute.valueSpan || attribute.sourceSpan) : this._visitTextWithInterpolation(attribute.valueTokens, attribute.valueSpan || attribute.sourceSpan, context, attribute.i18n);
23632    return context.visitNodeFn(attribute, node);
23633  }
23634
23635  visitText(text, context) {
23636    const node = text.tokens.length === 1 ? new Text$2(text.value, text.sourceSpan) : this._visitTextWithInterpolation(text.tokens, text.sourceSpan, context, text.i18n);
23637    return context.visitNodeFn(text, node);
23638  }
23639
23640  visitComment(comment, context) {
23641    return null;
23642  }
23643
23644  visitExpansion(icu, context) {
23645    context.icuDepth++;
23646    const i18nIcuCases = {};
23647    const i18nIcu = new Icu(icu.switchValue, icu.type, i18nIcuCases, icu.sourceSpan);
23648    icu.cases.forEach(caze => {
23649      i18nIcuCases[caze.value] = new Container(caze.expression.map(node => node.visit(this, context)), caze.expSourceSpan);
23650    });
23651    context.icuDepth--;
23652
23653    if (context.isIcu || context.icuDepth > 0) {
23654      // Returns an ICU node when:
23655      // - the message (vs a part of the message) is an ICU message, or
23656      // - the ICU message is nested.
23657      const expPh = context.placeholderRegistry.getUniquePlaceholder(`VAR_${icu.type}`);
23658      i18nIcu.expressionPlaceholder = expPh;
23659      context.placeholderToContent[expPh] = {
23660        text: icu.switchValue,
23661        sourceSpan: icu.switchValueSourceSpan
23662      };
23663      return context.visitNodeFn(icu, i18nIcu);
23664    } // Else returns a placeholder
23665    // ICU placeholders should not be replaced with their original content but with the their
23666    // translations.
23667    // TODO(vicb): add a html.Node -> i18n.Message cache to avoid having to re-create the msg
23668
23669
23670    const phName = context.placeholderRegistry.getPlaceholderName('ICU', icu.sourceSpan.toString());
23671    context.placeholderToMessage[phName] = this.toI18nMessage([icu], '', '', '', undefined);
23672    const node = new IcuPlaceholder(i18nIcu, phName, icu.sourceSpan);
23673    return context.visitNodeFn(icu, node);
23674  }
23675
23676  visitExpansionCase(_icuCase, _context) {
23677    throw new Error('Unreachable code');
23678  }
23679  /**
23680   * Convert, text and interpolated tokens up into text and placeholder pieces.
23681   *
23682   * @param tokens The text and interpolated tokens.
23683   * @param sourceSpan The span of the whole of the `text` string.
23684   * @param context The current context of the visitor, used to compute and store placeholders.
23685   * @param previousI18n Any i18n metadata associated with this `text` from a previous pass.
23686   */
23687
23688
23689  _visitTextWithInterpolation(tokens, sourceSpan, context, previousI18n) {
23690    // Return a sequence of `Text` and `Placeholder` nodes grouped in a `Container`.
23691    const nodes = []; // We will only create a container if there are actually interpolations,
23692    // so this flag tracks that.
23693
23694    let hasInterpolation = false;
23695
23696    for (const token of tokens) {
23697      switch (token.type) {
23698        case 8
23699        /* TokenType.INTERPOLATION */
23700        :
23701        case 17
23702        /* TokenType.ATTR_VALUE_INTERPOLATION */
23703        :
23704          hasInterpolation = true;
23705          const expression = token.parts[1];
23706          const baseName = extractPlaceholderName(expression) || 'INTERPOLATION';
23707          const phName = context.placeholderRegistry.getPlaceholderName(baseName, expression);
23708          context.placeholderToContent[phName] = {
23709            text: token.parts.join(''),
23710            sourceSpan: token.sourceSpan
23711          };
23712          nodes.push(new Placeholder(expression, phName, token.sourceSpan));
23713          break;
23714
23715        default:
23716          if (token.parts[0].length > 0) {
23717            // This token is text or an encoded entity.
23718            // If it is following on from a previous text node then merge it into that node
23719            // Otherwise, if it is following an interpolation, then add a new node.
23720            const previous = nodes[nodes.length - 1];
23721
23722            if (previous instanceof Text$2) {
23723              previous.value += token.parts[0];
23724              previous.sourceSpan = new ParseSourceSpan(previous.sourceSpan.start, token.sourceSpan.end, previous.sourceSpan.fullStart, previous.sourceSpan.details);
23725            } else {
23726              nodes.push(new Text$2(token.parts[0], token.sourceSpan));
23727            }
23728          }
23729
23730          break;
23731      }
23732    }
23733
23734    if (hasInterpolation) {
23735      // Whitespace removal may have invalidated the interpolation source-spans.
23736      reusePreviousSourceSpans(nodes, previousI18n);
23737      return new Container(nodes, sourceSpan);
23738    } else {
23739      return nodes[0];
23740    }
23741  }
23742
23743}
23744/**
23745 * Re-use the source-spans from `previousI18n` metadata for the `nodes`.
23746 *
23747 * Whitespace removal can invalidate the source-spans of interpolation nodes, so we
23748 * reuse the source-span stored from a previous pass before the whitespace was removed.
23749 *
23750 * @param nodes The `Text` and `Placeholder` nodes to be processed.
23751 * @param previousI18n Any i18n metadata for these `nodes` stored from a previous pass.
23752 */
23753
23754
23755function reusePreviousSourceSpans(nodes, previousI18n) {
23756  if (previousI18n instanceof Message) {
23757    // The `previousI18n` is an i18n `Message`, so we are processing an `Attribute` with i18n
23758    // metadata. The `Message` should consist only of a single `Container` that contains the
23759    // parts (`Text` and `Placeholder`) to process.
23760    assertSingleContainerMessage(previousI18n);
23761    previousI18n = previousI18n.nodes[0];
23762  }
23763
23764  if (previousI18n instanceof Container) {
23765    // The `previousI18n` is a `Container`, which means that this is a second i18n extraction pass
23766    // after whitespace has been removed from the AST nodes.
23767    assertEquivalentNodes(previousI18n.children, nodes); // Reuse the source-spans from the first pass.
23768
23769    for (let i = 0; i < nodes.length; i++) {
23770      nodes[i].sourceSpan = previousI18n.children[i].sourceSpan;
23771    }
23772  }
23773}
23774/**
23775 * Asserts that the `message` contains exactly one `Container` node.
23776 */
23777
23778
23779function assertSingleContainerMessage(message) {
23780  const nodes = message.nodes;
23781
23782  if (nodes.length !== 1 || !(nodes[0] instanceof Container)) {
23783    throw new Error('Unexpected previous i18n message - expected it to consist of only a single `Container` node.');
23784  }
23785}
23786/**
23787 * Asserts that the `previousNodes` and `node` collections have the same number of elements and
23788 * corresponding elements have the same node type.
23789 */
23790
23791
23792function assertEquivalentNodes(previousNodes, nodes) {
23793  if (previousNodes.length !== nodes.length) {
23794    throw new Error('The number of i18n message children changed between first and second pass.');
23795  }
23796
23797  if (previousNodes.some((node, i) => nodes[i].constructor !== node.constructor)) {
23798    throw new Error('The types of the i18n message children changed between first and second pass.');
23799  }
23800}
23801
23802const _CUSTOM_PH_EXP = /\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*("|')([\s\S]*?)\1[\s\S]*\)/g;
23803
23804function extractPlaceholderName(input) {
23805  return input.split(_CUSTOM_PH_EXP)[2];
23806}
23807/**
23808 * @license
23809 * Copyright Google LLC All Rights Reserved.
23810 *
23811 * Use of this source code is governed by an MIT-style license that can be
23812 * found in the LICENSE file at https://angular.io/license
23813 */
23814
23815/**
23816 * An i18n error.
23817 */
23818
23819
23820class I18nError extends ParseError {
23821  constructor(span, msg) {
23822    super(span, msg);
23823  }
23824
23825}
23826/**
23827 * @license
23828 * Copyright Google LLC All Rights Reserved.
23829 *
23830 * Use of this source code is governed by an MIT-style license that can be
23831 * found in the LICENSE file at https://angular.io/license
23832 */
23833
23834
23835const setI18nRefs = (htmlNode, i18nNode) => {
23836  if (htmlNode instanceof NodeWithI18n) {
23837    if (i18nNode instanceof IcuPlaceholder && htmlNode.i18n instanceof Message) {
23838      // This html node represents an ICU but this is a second processing pass, and the legacy id
23839      // was computed in the previous pass and stored in the `i18n` property as a message.
23840      // We are about to wipe out that property so capture the previous message to be reused when
23841      // generating the message for this ICU later. See `_generateI18nMessage()`.
23842      i18nNode.previousMessage = htmlNode.i18n;
23843    }
23844
23845    htmlNode.i18n = i18nNode;
23846  }
23847
23848  return i18nNode;
23849};
23850/**
23851 * This visitor walks over HTML parse tree and converts information stored in
23852 * i18n-related attributes ("i18n" and "i18n-*") into i18n meta object that is
23853 * stored with other element's and attribute's information.
23854 */
23855
23856
23857class I18nMetaVisitor {
23858  constructor(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG, keepI18nAttrs = false, enableI18nLegacyMessageIdFormat = false) {
23859    this.interpolationConfig = interpolationConfig;
23860    this.keepI18nAttrs = keepI18nAttrs;
23861    this.enableI18nLegacyMessageIdFormat = enableI18nLegacyMessageIdFormat; // whether visited nodes contain i18n information
23862
23863    this.hasI18nMeta = false;
23864    this._errors = []; // i18n message generation factory
23865
23866    this._createI18nMessage = createI18nMessageFactory(this.interpolationConfig);
23867  }
23868
23869  _generateI18nMessage(nodes, meta = '', visitNodeFn) {
23870    const {
23871      meaning,
23872      description,
23873      customId
23874    } = this._parseMetadata(meta);
23875
23876    const message = this._createI18nMessage(nodes, meaning, description, customId, visitNodeFn);
23877
23878    this._setMessageId(message, meta);
23879
23880    this._setLegacyIds(message, meta);
23881
23882    return message;
23883  }
23884
23885  visitAllWithErrors(nodes) {
23886    const result = nodes.map(node => node.visit(this, null));
23887    return new ParseTreeResult(result, this._errors);
23888  }
23889
23890  visitElement(element) {
23891    let message = undefined;
23892
23893    if (hasI18nAttrs(element)) {
23894      this.hasI18nMeta = true;
23895      const attrs = [];
23896      const attrsMeta = {};
23897
23898      for (const attr of element.attrs) {
23899        if (attr.name === I18N_ATTR) {
23900          // root 'i18n' node attribute
23901          const i18n = element.i18n || attr.value;
23902          message = this._generateI18nMessage(element.children, i18n, setI18nRefs);
23903
23904          if (message.nodes.length === 0) {
23905            // Ignore the message if it is empty.
23906            message = undefined;
23907          } // Store the message on the element
23908
23909
23910          element.i18n = message;
23911        } else if (attr.name.startsWith(I18N_ATTR_PREFIX)) {
23912          // 'i18n-*' attributes
23913          const name = attr.name.slice(I18N_ATTR_PREFIX.length);
23914
23915          if (isTrustedTypesSink(element.name, name)) {
23916            this._reportError(attr, `Translating attribute '${name}' is disallowed for security reasons.`);
23917          } else {
23918            attrsMeta[name] = attr.value;
23919          }
23920        } else {
23921          // non-i18n attributes
23922          attrs.push(attr);
23923        }
23924      } // set i18n meta for attributes
23925
23926
23927      if (Object.keys(attrsMeta).length) {
23928        for (const attr of attrs) {
23929          const meta = attrsMeta[attr.name]; // do not create translation for empty attributes
23930
23931          if (meta !== undefined && attr.value) {
23932            attr.i18n = this._generateI18nMessage([attr], attr.i18n || meta);
23933          }
23934        }
23935      }
23936
23937      if (!this.keepI18nAttrs) {
23938        // update element's attributes,
23939        // keeping only non-i18n related ones
23940        element.attrs = attrs;
23941      }
23942    }
23943
23944    visitAll(this, element.children, message);
23945    return element;
23946  }
23947
23948  visitExpansion(expansion, currentMessage) {
23949    let message;
23950    const meta = expansion.i18n;
23951    this.hasI18nMeta = true;
23952
23953    if (meta instanceof IcuPlaceholder) {
23954      // set ICU placeholder name (e.g. "ICU_1"),
23955      // generated while processing root element contents,
23956      // so we can reference it when we output translation
23957      const name = meta.name;
23958      message = this._generateI18nMessage([expansion], meta);
23959      const icu = icuFromI18nMessage(message);
23960      icu.name = name;
23961
23962      if (currentMessage !== null) {
23963        // Also update the placeholderToMessage map with this new message
23964        currentMessage.placeholderToMessage[name] = message;
23965      }
23966    } else {
23967      // ICU is a top level message, try to use metadata from container element if provided via
23968      // `context` argument. Note: context may not be available for standalone ICUs (without
23969      // wrapping element), so fallback to ICU metadata in this case.
23970      message = this._generateI18nMessage([expansion], currentMessage || meta);
23971    }
23972
23973    expansion.i18n = message;
23974    return expansion;
23975  }
23976
23977  visitText(text) {
23978    return text;
23979  }
23980
23981  visitAttribute(attribute) {
23982    return attribute;
23983  }
23984
23985  visitComment(comment) {
23986    return comment;
23987  }
23988
23989  visitExpansionCase(expansionCase) {
23990    return expansionCase;
23991  }
23992  /**
23993   * Parse the general form `meta` passed into extract the explicit metadata needed to create a
23994   * `Message`.
23995   *
23996   * There are three possibilities for the `meta` variable
23997   * 1) a string from an `i18n` template attribute: parse it to extract the metadata values.
23998   * 2) a `Message` from a previous processing pass: reuse the metadata values in the message.
23999   * 4) other: ignore this and just process the message metadata as normal
24000   *
24001   * @param meta the bucket that holds information about the message
24002   * @returns the parsed metadata.
24003   */
24004
24005
24006  _parseMetadata(meta) {
24007    return typeof meta === 'string' ? parseI18nMeta(meta) : meta instanceof Message ? meta : {};
24008  }
24009  /**
24010   * Generate (or restore) message id if not specified already.
24011   */
24012
24013
24014  _setMessageId(message, meta) {
24015    if (!message.id) {
24016      message.id = meta instanceof Message && meta.id || decimalDigest(message);
24017    }
24018  }
24019  /**
24020   * Update the `message` with a `legacyId` if necessary.
24021   *
24022   * @param message the message whose legacy id should be set
24023   * @param meta information about the message being processed
24024   */
24025
24026
24027  _setLegacyIds(message, meta) {
24028    if (this.enableI18nLegacyMessageIdFormat) {
24029      message.legacyIds = [computeDigest(message), computeDecimalDigest(message)];
24030    } else if (typeof meta !== 'string') {
24031      // This occurs if we are doing the 2nd pass after whitespace removal (see `parseTemplate()` in
24032      // `packages/compiler/src/render3/view/template.ts`).
24033      // In that case we want to reuse the legacy message generated in the 1st pass (see
24034      // `setI18nRefs()`).
24035      const previousMessage = meta instanceof Message ? meta : meta instanceof IcuPlaceholder ? meta.previousMessage : undefined;
24036      message.legacyIds = previousMessage ? previousMessage.legacyIds : [];
24037    }
24038  }
24039
24040  _reportError(node, msg) {
24041    this._errors.push(new I18nError(node.sourceSpan, msg));
24042  }
24043
24044}
24045/** I18n separators for metadata **/
24046
24047
24048const I18N_MEANING_SEPARATOR = '|';
24049const I18N_ID_SEPARATOR = '@@';
24050/**
24051 * Parses i18n metas like:
24052 *  - "@@id",
24053 *  - "description[@@id]",
24054 *  - "meaning|description[@@id]"
24055 * and returns an object with parsed output.
24056 *
24057 * @param meta String that represents i18n meta
24058 * @returns Object with id, meaning and description fields
24059 */
24060
24061function parseI18nMeta(meta = '') {
24062  let customId;
24063  let meaning;
24064  let description;
24065  meta = meta.trim();
24066
24067  if (meta) {
24068    const idIndex = meta.indexOf(I18N_ID_SEPARATOR);
24069    const descIndex = meta.indexOf(I18N_MEANING_SEPARATOR);
24070    let meaningAndDesc;
24071    [meaningAndDesc, customId] = idIndex > -1 ? [meta.slice(0, idIndex), meta.slice(idIndex + 2)] : [meta, ''];
24072    [meaning, description] = descIndex > -1 ? [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] : ['', meaningAndDesc];
24073  }
24074
24075  return {
24076    customId,
24077    meaning,
24078    description
24079  };
24080} // Converts i18n meta information for a message (id, description, meaning)
24081// to a JsDoc statement formatted as expected by the Closure compiler.
24082
24083
24084function i18nMetaToJSDoc(meta) {
24085  const tags = [];
24086
24087  if (meta.description) {
24088    tags.push({
24089      tagName: "desc"
24090      /* o.JSDocTagName.Desc */
24091      ,
24092      text: meta.description
24093    });
24094  } else {
24095    // Suppress the JSCompiler warning that a `@desc` was not given for this message.
24096    tags.push({
24097      tagName: "suppress"
24098      /* o.JSDocTagName.Suppress */
24099      ,
24100      text: '{msgDescriptions}'
24101    });
24102  }
24103
24104  if (meta.meaning) {
24105    tags.push({
24106      tagName: "meaning"
24107      /* o.JSDocTagName.Meaning */
24108      ,
24109      text: meta.meaning
24110    });
24111  }
24112
24113  return jsDocComment(tags);
24114}
24115/** Closure uses `goog.getMsg(message)` to lookup translations */
24116
24117
24118const GOOG_GET_MSG = 'goog.getMsg';
24119/**
24120 * Generates a `goog.getMsg()` statement and reassignment. The template:
24121 *
24122 * ```html
24123 * <div i18n>Sent from {{ sender }} to <span class="receiver">{{ receiver }}</span></div>
24124 * ```
24125 *
24126 * Generates:
24127 *
24128 * ```typescript
24129 * const MSG_FOO = goog.getMsg(
24130 *   // Message template.
24131 *   'Sent from {$interpolation} to {$startTagSpan}{$interpolation_1}{$closeTagSpan}.',
24132 *   // Placeholder values, set to magic strings which get replaced by the Angular runtime.
24133 *   {
24134 *     'interpolation': '\uFFFD0\uFFFD',
24135 *     'startTagSpan': '\uFFFD1\uFFFD',
24136 *     'interpolation_1': '\uFFFD2\uFFFD',
24137 *     'closeTagSpan': '\uFFFD3\uFFFD',
24138 *   },
24139 *   // Options bag.
24140 *   {
24141 *     // Maps each placeholder to the original Angular source code which generates it's value.
24142 *     original_code: {
24143 *       'interpolation': '{{ sender }}',
24144 *       'startTagSpan': '<span class="receiver">',
24145 *       'interpolation_1': '{{ receiver }}',
24146 *       'closeTagSpan': '</span>',
24147 *     },
24148 *   },
24149 * );
24150 * const I18N_0 = MSG_FOO;
24151 * ```
24152 */
24153
24154function createGoogleGetMsgStatements(variable$1, message, closureVar, placeholderValues) {
24155  const messageString = serializeI18nMessageForGetMsg(message);
24156  const args = [literal(messageString)];
24157
24158  if (Object.keys(placeholderValues).length) {
24159    // Message template parameters containing the magic strings replaced by the Angular runtime with
24160    // real data, e.g. `{'interpolation': '\uFFFD0\uFFFD'}`.
24161    args.push(mapLiteral(formatI18nPlaceholderNamesInMap(placeholderValues, true
24162    /* useCamelCase */
24163    ), true
24164    /* quoted */
24165    )); // Message options object, which contains original source code for placeholders (as they are
24166    // present in a template, e.g.
24167    // `{original_code: {'interpolation': '{{ name }}', 'startTagSpan': '<span>'}}`.
24168
24169    args.push(mapLiteral({
24170      original_code: literalMap(Object.keys(placeholderValues).map(param => ({
24171        key: formatI18nPlaceholderName(param),
24172        quoted: true,
24173        value: message.placeholders[param] ? // Get source span for typical placeholder if it exists.
24174        literal(message.placeholders[param].sourceSpan.toString()) : // Otherwise must be an ICU expression, get it's source span.
24175        literal(message.placeholderToMessage[param].nodes.map(node => node.sourceSpan.toString()).join(''))
24176      })))
24177    }));
24178  } // /**
24179  //  * @desc description of message
24180  //  * @meaning meaning of message
24181  //  */
24182  // const MSG_... = goog.getMsg(..);
24183  // I18N_X = MSG_...;
24184
24185
24186  const googGetMsgStmt = closureVar.set(variable(GOOG_GET_MSG).callFn(args)).toConstDecl();
24187  googGetMsgStmt.addLeadingComment(i18nMetaToJSDoc(message));
24188  const i18nAssignmentStmt = new ExpressionStatement(variable$1.set(closureVar));
24189  return [googGetMsgStmt, i18nAssignmentStmt];
24190}
24191/**
24192 * This visitor walks over i18n tree and generates its string representation, including ICUs and
24193 * placeholders in `{$placeholder}` (for plain messages) or `{PLACEHOLDER}` (inside ICUs) format.
24194 */
24195
24196
24197class GetMsgSerializerVisitor {
24198  formatPh(value) {
24199    return `{$${formatI18nPlaceholderName(value)}}`;
24200  }
24201
24202  visitText(text) {
24203    return text.value;
24204  }
24205
24206  visitContainer(container) {
24207    return container.children.map(child => child.visit(this)).join('');
24208  }
24209
24210  visitIcu(icu) {
24211    return serializeIcuNode(icu);
24212  }
24213
24214  visitTagPlaceholder(ph) {
24215    return ph.isVoid ? this.formatPh(ph.startName) : `${this.formatPh(ph.startName)}${ph.children.map(child => child.visit(this)).join('')}${this.formatPh(ph.closeName)}`;
24216  }
24217
24218  visitPlaceholder(ph) {
24219    return this.formatPh(ph.name);
24220  }
24221
24222  visitIcuPlaceholder(ph, context) {
24223    return this.formatPh(ph.name);
24224  }
24225
24226}
24227
24228const serializerVisitor = new GetMsgSerializerVisitor();
24229
24230function serializeI18nMessageForGetMsg(message) {
24231  return message.nodes.map(node => node.visit(serializerVisitor, null)).join('');
24232}
24233
24234function createLocalizeStatements(variable, message, params) {
24235  const {
24236    messageParts,
24237    placeHolders
24238  } = serializeI18nMessageForLocalize(message);
24239  const sourceSpan = getSourceSpan(message);
24240  const expressions = placeHolders.map(ph => params[ph.text]);
24241  const localizedString$1 = localizedString(message, messageParts, placeHolders, expressions, sourceSpan);
24242  const variableInitialization = variable.set(localizedString$1);
24243  return [new ExpressionStatement(variableInitialization)];
24244}
24245/**
24246 * This visitor walks over an i18n tree, capturing literal strings and placeholders.
24247 *
24248 * The result can be used for generating the `$localize` tagged template literals.
24249 */
24250
24251
24252class LocalizeSerializerVisitor {
24253  constructor(placeholderToMessage, pieces) {
24254    this.placeholderToMessage = placeholderToMessage;
24255    this.pieces = pieces;
24256  }
24257
24258  visitText(text) {
24259    if (this.pieces[this.pieces.length - 1] instanceof LiteralPiece) {
24260      // Two literal pieces in a row means that there was some comment node in-between.
24261      this.pieces[this.pieces.length - 1].text += text.value;
24262    } else {
24263      const sourceSpan = new ParseSourceSpan(text.sourceSpan.fullStart, text.sourceSpan.end, text.sourceSpan.fullStart, text.sourceSpan.details);
24264      this.pieces.push(new LiteralPiece(text.value, sourceSpan));
24265    }
24266  }
24267
24268  visitContainer(container) {
24269    container.children.forEach(child => child.visit(this));
24270  }
24271
24272  visitIcu(icu) {
24273    this.pieces.push(new LiteralPiece(serializeIcuNode(icu), icu.sourceSpan));
24274  }
24275
24276  visitTagPlaceholder(ph) {
24277    this.pieces.push(this.createPlaceholderPiece(ph.startName, ph.startSourceSpan ?? ph.sourceSpan));
24278
24279    if (!ph.isVoid) {
24280      ph.children.forEach(child => child.visit(this));
24281      this.pieces.push(this.createPlaceholderPiece(ph.closeName, ph.endSourceSpan ?? ph.sourceSpan));
24282    }
24283  }
24284
24285  visitPlaceholder(ph) {
24286    this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan));
24287  }
24288
24289  visitIcuPlaceholder(ph) {
24290    this.pieces.push(this.createPlaceholderPiece(ph.name, ph.sourceSpan, this.placeholderToMessage[ph.name]));
24291  }
24292
24293  createPlaceholderPiece(name, sourceSpan, associatedMessage) {
24294    return new PlaceholderPiece(formatI18nPlaceholderName(name,
24295    /* useCamelCase */
24296    false), sourceSpan, associatedMessage);
24297  }
24298
24299}
24300/**
24301 * Serialize an i18n message into two arrays: messageParts and placeholders.
24302 *
24303 * These arrays will be used to generate `$localize` tagged template literals.
24304 *
24305 * @param message The message to be serialized.
24306 * @returns an object containing the messageParts and placeholders.
24307 */
24308
24309
24310function serializeI18nMessageForLocalize(message) {
24311  const pieces = [];
24312  const serializerVisitor = new LocalizeSerializerVisitor(message.placeholderToMessage, pieces);
24313  message.nodes.forEach(node => node.visit(serializerVisitor));
24314  return processMessagePieces(pieces);
24315}
24316
24317function getSourceSpan(message) {
24318  const startNode = message.nodes[0];
24319  const endNode = message.nodes[message.nodes.length - 1];
24320  return new ParseSourceSpan(startNode.sourceSpan.fullStart, endNode.sourceSpan.end, startNode.sourceSpan.fullStart, startNode.sourceSpan.details);
24321}
24322/**
24323 * Convert the list of serialized MessagePieces into two arrays.
24324 *
24325 * One contains the literal string pieces and the other the placeholders that will be replaced by
24326 * expressions when rendering `$localize` tagged template literals.
24327 *
24328 * @param pieces The pieces to process.
24329 * @returns an object containing the messageParts and placeholders.
24330 */
24331
24332
24333function processMessagePieces(pieces) {
24334  const messageParts = [];
24335  const placeHolders = [];
24336
24337  if (pieces[0] instanceof PlaceholderPiece) {
24338    // The first piece was a placeholder so we need to add an initial empty message part.
24339    messageParts.push(createEmptyMessagePart(pieces[0].sourceSpan.start));
24340  }
24341
24342  for (let i = 0; i < pieces.length; i++) {
24343    const part = pieces[i];
24344
24345    if (part instanceof LiteralPiece) {
24346      messageParts.push(part);
24347    } else {
24348      placeHolders.push(part);
24349
24350      if (pieces[i - 1] instanceof PlaceholderPiece) {
24351        // There were two placeholders in a row, so we need to add an empty message part.
24352        messageParts.push(createEmptyMessagePart(pieces[i - 1].sourceSpan.end));
24353      }
24354    }
24355  }
24356
24357  if (pieces[pieces.length - 1] instanceof PlaceholderPiece) {
24358    // The last piece was a placeholder so we need to add a final empty message part.
24359    messageParts.push(createEmptyMessagePart(pieces[pieces.length - 1].sourceSpan.end));
24360  }
24361
24362  return {
24363    messageParts,
24364    placeHolders
24365  };
24366}
24367
24368function createEmptyMessagePart(location) {
24369  return new LiteralPiece('', new ParseSourceSpan(location, location));
24370}
24371/**
24372 * @license
24373 * Copyright Google LLC All Rights Reserved.
24374 *
24375 * Use of this source code is governed by an MIT-style license that can be
24376 * found in the LICENSE file at https://angular.io/license
24377 */
24378// Selector attribute name of `<ng-content>`
24379
24380
24381const NG_CONTENT_SELECT_ATTR = 'select'; // Attribute name of `ngProjectAs`.
24382
24383const NG_PROJECT_AS_ATTR_NAME = 'ngProjectAs'; // Global symbols available only inside event bindings.
24384
24385const EVENT_BINDING_SCOPE_GLOBALS = new Set(['$event']); // List of supported global targets for event listeners
24386
24387const GLOBAL_TARGET_RESOLVERS = new Map([['window', Identifiers.resolveWindow], ['document', Identifiers.resolveDocument], ['body', Identifiers.resolveBody]]);
24388const LEADING_TRIVIA_CHARS = [' ', '\n', '\r', '\t']; //  if (rf & flags) { .. }
24389
24390function renderFlagCheckIfStmt(flags, statements) {
24391  return ifStmt(variable(RENDER_FLAGS).bitwiseAnd(literal(flags), null, false), statements);
24392}
24393
24394function prepareEventListenerParameters(eventAst, handlerName = null, scope = null) {
24395  const {
24396    type,
24397    name,
24398    target,
24399    phase,
24400    handler
24401  } = eventAst;
24402
24403  if (target && !GLOBAL_TARGET_RESOLVERS.has(target)) {
24404    throw new Error(`Unexpected global target '${target}' defined for '${name}' event.
24405        Supported list of global targets: ${Array.from(GLOBAL_TARGET_RESOLVERS.keys())}.`);
24406  }
24407
24408  const eventArgumentName = '$event';
24409  const implicitReceiverAccesses = new Set();
24410  const implicitReceiverExpr = scope === null || scope.bindingLevel === 0 ? variable(CONTEXT_NAME) : scope.getOrCreateSharedContextVar(0);
24411  const bindingStatements = convertActionBinding(scope, implicitReceiverExpr, handler, 'b', eventAst.handlerSpan, implicitReceiverAccesses, EVENT_BINDING_SCOPE_GLOBALS);
24412  const statements = [];
24413  const variableDeclarations = scope?.variableDeclarations();
24414  const restoreViewStatement = scope?.restoreViewStatement();
24415
24416  if (variableDeclarations) {
24417    // `variableDeclarations` needs to run first, because
24418    // `restoreViewStatement` depends on the result.
24419    statements.push(...variableDeclarations);
24420  }
24421
24422  statements.push(...bindingStatements);
24423
24424  if (restoreViewStatement) {
24425    statements.unshift(restoreViewStatement); // If there's a `restoreView` call, we need to reset the view at the end of the listener
24426    // in order to avoid a leak. If there's a `return` statement already, we wrap it in the
24427    // call, e.g. `return resetView(ctx.foo())`. Otherwise we add the call as the last statement.
24428
24429    const lastStatement = statements[statements.length - 1];
24430
24431    if (lastStatement instanceof ReturnStatement) {
24432      statements[statements.length - 1] = new ReturnStatement(invokeInstruction(lastStatement.value.sourceSpan, Identifiers.resetView, [lastStatement.value]));
24433    } else {
24434      statements.push(new ExpressionStatement(invokeInstruction(null, Identifiers.resetView, [])));
24435    }
24436  }
24437
24438  const eventName = type === 1
24439  /* ParsedEventType.Animation */
24440  ? prepareSyntheticListenerName(name, phase) : name;
24441  const fnName = handlerName && sanitizeIdentifier(handlerName);
24442  const fnArgs = [];
24443
24444  if (implicitReceiverAccesses.has(eventArgumentName)) {
24445    fnArgs.push(new FnParam(eventArgumentName, DYNAMIC_TYPE));
24446  }
24447
24448  const handlerFn = fn(fnArgs, statements, INFERRED_TYPE, null, fnName);
24449  const params = [literal(eventName), handlerFn];
24450
24451  if (target) {
24452    params.push(literal(false), // `useCapture` flag, defaults to `false`
24453    importExpr(GLOBAL_TARGET_RESOLVERS.get(target)));
24454  }
24455
24456  return params;
24457}
24458
24459function createComponentDefConsts() {
24460  return {
24461    prepareStatements: [],
24462    constExpressions: [],
24463    i18nVarRefsCache: new Map()
24464  };
24465}
24466
24467class TemplateDefinitionBuilder {
24468  constructor(constantPool, parentBindingScope, level = 0, contextName, i18nContext, templateIndex, templateName, _namespace, relativeContextFilePath, i18nUseExternalIds, _constants = createComponentDefConsts()) {
24469    this.constantPool = constantPool;
24470    this.level = level;
24471    this.contextName = contextName;
24472    this.i18nContext = i18nContext;
24473    this.templateIndex = templateIndex;
24474    this.templateName = templateName;
24475    this._namespace = _namespace;
24476    this.i18nUseExternalIds = i18nUseExternalIds;
24477    this._constants = _constants;
24478    this._dataIndex = 0;
24479    this._bindingContext = 0;
24480    this._prefixCode = [];
24481    /**
24482     * List of callbacks to generate creation mode instructions. We store them here as we process
24483     * the template so bindings in listeners are resolved only once all nodes have been visited.
24484     * This ensures all local refs and context variables are available for matching.
24485     */
24486
24487    this._creationCodeFns = [];
24488    /**
24489     * List of callbacks to generate update mode instructions. We store them here as we process
24490     * the template so bindings are resolved only once all nodes have been visited. This ensures
24491     * all local refs and context variables are available for matching.
24492     */
24493
24494    this._updateCodeFns = [];
24495    /** Index of the currently-selected node. */
24496
24497    this._currentIndex = 0;
24498    /** Temporary variable declarations generated from visiting pipes, literals, etc. */
24499
24500    this._tempVariables = [];
24501    /**
24502     * List of callbacks to build nested templates. Nested templates must not be visited until
24503     * after the parent template has finished visiting all of its nodes. This ensures that all
24504     * local ref bindings in nested templates are able to find local ref values if the refs
24505     * are defined after the template declaration.
24506     */
24507
24508    this._nestedTemplateFns = []; // i18n context local to this template
24509
24510    this.i18n = null; // Number of slots to reserve for pureFunctions
24511
24512    this._pureFunctionSlots = 0; // Number of binding slots
24513
24514    this._bindingSlots = 0; // Projection slots found in the template. Projection slots can distribute projected
24515    // nodes based on a selector, or can just use the wildcard selector to match
24516    // all nodes which aren't matching any selector.
24517
24518    this._ngContentReservedSlots = []; // Number of non-default selectors found in all parent templates of this template. We need to
24519    // track it to properly adjust projection slot index in the `projection` instruction.
24520
24521    this._ngContentSelectorsOffset = 0; // Expression that should be used as implicit receiver when convert
24521ing template
24522    // expressions to output AST.
24523
24524    this._implicitReceiverExpr = null; // These should be handled in the template or element directly.
24525
24526    this.visitReference = invalid;
24527    this.visitVariable = invalid;
24528    this.visitTextAttribute = invalid;
24529    this.visitBoundAttribute = invalid;
24530    this.visitBoundEvent = invalid;
24531    this._bindingScope = parentBindingScope.nestedScope(level); // Turn the relative context file path into an identifier by replacing non-alphanumeric
24532    // characters with underscores.
24533
24534    this.fileBasedI18nSuffix = relativeContextFilePath.replace(/[^A-Za-z0-9]/g, '_') + '_';
24535    this._valueConverter = new ValueConverter(constantPool, () => this.allocateDataSlot(), numSlots => this.allocatePureFunctionSlots(numSlots), (name, localName, slot, value) => {
24536      this._bindingScope.set(this.level, localName, value);
24537
24538      this.creationInstruction(null, Identifiers.pipe, [literal(slot), literal(name)]);
24539    });
24540  }
24541
24542  buildTemplateFunction(nodes, variables, ngContentSelectorsOffset = 0, i18n) {
24543    this._ngContentSelectorsOffset = ngContentSelectorsOffset;
24544
24545    if (this._namespace !== Identifiers.namespaceHTML) {
24546      this.creationInstruction(null, this._namespace);
24547    } // Create variable bindings
24548
24549
24550    variables.forEach(v => this.registerContextVariables(v)); // Initiate i18n context in case:
24551    // - this template has parent i18n context
24552    // - or the template has i18n meta associated with it,
24553    //   but it's not initiated by the Element (e.g. <ng-template i18n>)
24554
24555    const initI18nContext = this.i18nContext || isI18nRootNode(i18n) && !isSingleI18nIcu(i18n) && !(isSingleElementTemplate(nodes) && nodes[0].i18n === i18n);
24556    const selfClosingI18nInstruction = hasTextChildrenOnly(nodes);
24557
24558    if (initI18nContext) {
24559      this.i18nStart(null, i18n, selfClosingI18nInstruction);
24560    } // This is the initial pass through the nodes of this template. In this pass, we
24561    // queue all creation mode and update mode instructions for generation in the second
24562    // pass. It's necessary to separate the passes to ensure local refs are defined before
24563    // resolving bindings. We also count bindings in this pass as we walk bound expressions.
24564
24565
24566    visitAll$1(this, nodes); // Add total binding count to pure function count so pure function instructions are
24567    // generated with the correct slot offset when update instructions are processed.
24568
24569    this._pureFunctionSlots += this._bindingSlots; // Pipes are walked in the first pass (to enqueue `pipe()` creation instructions and
24570    // `pipeBind` update instructions), so we have to update the slot offsets manually
24571    // to account for bindings.
24572
24573    this._valueConverter.updatePipeSlotOffsets(this._bindingSlots); // Nested templates must be processed before creation instructions so template()
24574    // instructions can be generated with the correct internal const count.
24575
24576
24577    this._nestedTemplateFns.forEach(buildTemplateFn => buildTemplateFn()); // Output the `projectionDef` instruction when some `<ng-content>` tags are present.
24578    // The `projectionDef` instruction is only emitted for the component template and
24579    // is skipped for nested templates (<ng-template> tags).
24580
24581
24582    if (this.level === 0 && this._ngContentReservedSlots.length) {
24583      const parameters = []; // By default the `projectionDef` instructions creates one slot for the wildcard
24584      // selector if no parameters are passed. Therefore we only want to allocate a new
24585      // array for the projection slots if the default projection slot is not sufficient.
24586
24587      if (this._ngContentReservedSlots.length > 1 || this._ngContentReservedSlots[0] !== '*') {
24588        const r3ReservedSlots = this._ngContentReservedSlots.map(s => s !== '*' ? parseSelectorToR3Selector(s) : s);
24589
24590        parameters.push(this.constantPool.getConstLiteral(asLiteral(r3ReservedSlots), true));
24591      } // Since we accumulate ngContent selectors while processing template elements,
24592      // we *prepend* `projectionDef` to creation instructions block, to put it before
24593      // any `projection` instructions
24594
24595
24596      this.creationInstruction(null, Identifiers.projectionDef, parameters,
24597      /* prepend */
24598      true);
24599    }
24600
24601    if (initI18nContext) {
24602      this.i18nEnd(null, selfClosingI18nInstruction);
24603    } // Generate all the creation mode instructions (e.g. resolve bindings in listeners)
24604
24605
24606    const creationStatements = getInstructionStatements(this._creationCodeFns); // Generate all the update mode instructions (e.g. resolve property or text bindings)
24607
24608    const updateStatements = getInstructionStatements(this._updateCodeFns); //  Variable declaration must occur after binding resolution so we can generate context
24609    //  instructions that build on each other.
24610    // e.g. const b = nextContext().$implicit(); const b = nextContext();
24611
24612    const creationVariables = this._bindingScope.viewSnapshotStatements();
24613
24614    const updateVariables = this._bindingScope.variableDeclarations().concat(this._tempVariables);
24615
24616    const creationBlock = creationStatements.length > 0 ? [renderFlagCheckIfStmt(1
24617    /* core.RenderFlags.Create */
24618    , creationVariables.concat(creationStatements))] : [];
24619    const updateBlock = updateStatements.length > 0 ? [renderFlagCheckIfStmt(2
24620    /* core.RenderFlags.Update */
24621    , updateVariables.concat(updateStatements))] : [];
24622    return fn( // i.e. (rf: RenderFlags, ctx: any)
24623    [new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], [// Temporary variable declarations for query refresh (i.e. let _t: any;)
24624    ...this._prefixCode, // Creating mode (i.e. if (rf & RenderFlags.
24624Create) { ... })
24625    ...creationBlock, // Binding and refresh mode (i.e. if (rf & RenderFlags.Update) {...})
24626    ...updateBlock], INFERRED_TYPE, null, this.templateName);
24627  } // LocalResolver
24628
24629
24630  getLocal(name) {
24631    return this._bindingScope.get(name);
24632  } // LocalResolver
24633
24634
24635  notifyImplicitReceiverUse() {
24636    this._bindingScope.notifyImplicitReceiverUse();
24637  } // LocalResolver
24638
24639
24640  maybeRestoreView() {
24641    this._bindingScope.maybeRestoreView();
24642  }
24643
24644  i18nTranslate(message, params = {}, ref, transformFn) {
24645    const _ref = ref || this.i18nGenerateMainBlockVar(); // Closure Compiler requires const names to start with `MSG_` but disallows any other const to
24646    // start with `MSG_`. We define a variable starting with `MSG_` just for the `goog.getMsg` call
24647
24648
24649    const closureVar = this.i18nGenerateClosureVar(message.id);
24650    const statements = getTranslationDeclStmts(message, _ref, closureVar, params, transformFn);
24651
24652    this._constants.prepareStatements.push(...statements);
24653
24654    return _ref;
24655  }
24656
24657  registerContextVariables(variable$1) {
24658    const scopedName = this._bindingScope.freshReferenceName();
24659
24660    const retrievalLevel = this.level;
24661    const lhs = variable(variable$1.name + scopedName);
24662
24663    this._bindingScope.set(retrievalLevel, variable$1.name, lhs, 1
24664    /* DeclarationPriority.CONTEXT */
24665    , (scope, relativeLevel) => {
24666      let rhs;
24667
24668      if (scope.bindingLevel === retrievalLevel) {
24669        if (scope.isListenerScope() && scope.hasRestoreViewVariable()) {
24670          // e.g. restoredCtx.
24671          // We have to get the context from a view reference, if one is available, because
24672          // the context that was passed in during creation may not be correct anymore.
24673          // For more information see: https://github.com/angular/angular/pull/40360.
24674          rhs = variable(RESTORED_VIEW_CONTEXT_NAME);
24675          scope.notifyRestoredViewContextUse();
24676        } else {
24677          // e.g. ctx
24678          rhs = variable(CONTEXT_NAME);
24679        }
24680      } else {
24681        const sharedCtxVar = scope.getSharedContextName(retrievalLevel); // e.g. ctx_r0   OR  x(2);
24682
24683        rhs = sharedCtxVar ? sharedCtxVar : generateNextContextExpr(relativeLevel);
24684      } // e.g. const $item$ = x(2).$implicit;
24685
24686
24687      return [lhs.set(rhs.prop(variable$1.value || IMPLICIT_REFERENCE)).toConstDecl()];
24688    });
24689  }
24690
24691  i18nAppendBindings(expressions) {
24692    if (expressions.length > 0) {
24693      expressions.forEach(expression => this.i18n.appendBinding(expression));
24694    }
24695  }
24696
24697  i18nBindProps(props) {
24698    const bound = {};
24699    Object.keys(props).forEach(key => {
24700      const prop = props[key];
24701
24702      if (prop instanceof Text$3) {
24703        bound[key] = literal(prop.value);
24704      } else {
24705        const value = prop.value.visit(this._valueConverter);
24706        this.allocateBindingSlots(value);
24707
24708        if (value instanceof Interpolation) {
24709          const {
24710            strings,
24711            expressions
24712          } = value;
24713          const {
24714            id,
24715            bindings
24716          } = this.i18n;
24717          const label = assembleI18nBoundString(strings, bindings.size, id);
24718          this.i18nAppendBindings(expressions);
24719          bound[key] = literal(label);
24720        }
24721      }
24722    });
24723    return bound;
24724  } // Generates top level vars for i18n blocks (i.e. `i18n_N`).
24725
24726
24727  i18nGenerateMainBlockVar() {
24728    return variable(this.constantPool.uniqueName(TRANSLATION_VAR_PREFIX));
24729  } // Generates vars with Closure-specific names for i18n blocks (i.e. `MSG_XXX`).
24730
24731
24732  i18nGenerateClosureVar(messageId) {
24733    let name;
24734    const suffix = this.fileBasedI18nSuffix.toUpperCase();
24735
24736    if (this.i18nUseExternalIds) {
24737      const prefix = getTranslationConstPrefix(`EXTERNAL_`);
24738      const uniqueSuffix = this.constantPool.uniqueName(suffix);
24739      name = `${prefix}${sanitizeIdentifier(messageId)}$$${uniqueSuffix}`;
24740    } else {
24741      const prefix = getTranslationConstPrefix(suffix);
24742      name = this.constantPool.uniqueName(prefix);
24743    }
24744
24745    return variable(name);
24746  }
24747
24748  i18nUpdateRef(context) {
24749    const {
24750      icus,
24751      meta,
24752      isRoot,
24753      isResolved,
24754      isEmitted
24755    } = context;
24756
24757    if (isRoot && isResolved && !isEmitted && !isSingleI18nIcu(meta)) {
24758      context.isEmitted = true;
24759      const placeholders = context.getSerializedPlaceholders();
24760      let icuMapping = {};
24761      let params = placeholders.size ? placeholdersToParams(placeholders) : {};
24762
24763      if (icus.size) {
24764        icus.forEach((refs, key) => {
24765          if (refs.length === 1) {
24766            // if we have one ICU defined for a given
24767            // placeholder - just output its reference
24768            params[key] = refs[0];
24769          } else {
24770            // ... otherwise we need to activate post-processing
24771            // to replace ICU placeholders with proper values
24772            const placeholder = wrapI18nPlaceholder(`${I18N_ICU_MAPPING_PREFIX}${key}`);
24773            params[key] = literal(placeholder);
24774            icuMapping[key] = literalArr(refs);
24775          }
24776        });
24777      } // translation requires post processing in 2 cases:
24778      // - if we have placeholders with multiple values (ex. `START_DIV`: [�#1�, �#2�, ...])
24779      // - if we have multiple ICUs that refer to the same placeholder name
24780
24781
24782      const needsPostprocessing = Array.from(placeholders.values()).some(value => value.length > 1) || Object.keys(icuMapping).length;
24783      let transformFn;
24784
24785      if (needsPostprocessing) {
24786        transformFn = raw => {
24787          const args = [raw];
24788
24789          if (Object.keys(icuMapping).length) {
24790            args.push(mapLiteral(icuMapping, true));
24791          }
24792
24793          return invokeInstruction(null, Identifiers.i18nPostprocess, args);
24794        };
24795      }
24796
24797      this.i18nTranslate(meta, params, context.ref, transformFn);
24798    }
24799  }
24800
24801  i18nStart(span = null, meta, selfClosing) {
24802    const index = this.allocateDataSlot();
24803    this.i18n = this.i18nContext ? this.i18nContext.forkChildContext(index, this.templateIndex, meta) : new I18nContext(index, this.i18nGenerateMainBlockVar(), 0, this.templateIndex, meta); // generate i18nStart instruction
24804
24805    const {
24806      id,
24807      ref
24808    } = this.i18n;
24809    const params = [literal(index), this.addToConsts(ref)];
24810
24811    if (id > 0) {
24812      // do not push 3rd argument (sub-block id)
24813      // into i18nStart call for top level i18n context
24814      params.push(literal(id));
24815    }
24816
24817    this.creationInstruction(span, selfClosing ? Identifiers.i18n : Identifiers.i18nStart, params);
24818  }
24819
24820  i18nEnd(span = null, selfClosing) {
24821    if (!this.i18n) {
24822      throw new Error('i18nEnd is executed with no i18n context present');
24823    }
24824
24825    if (this.i18nContext) {
24826      this.i18nContext.reconcileChildContext(this.i18n);
24827      this.i18nUpdateRef(this.i18nContext);
24828    } else {
24829      this.i18nUpdateRef(this.i18n);
24830    } // setup accumulated bindings
24831
24832
24833    const {
24834      index,
24835      bindings
24836    } = this.i18n;
24837
24838    if (bindings.size) {
24839      for (const binding of bindings) {
24840        // for i18n block, advance to the most recent element index (by taking the current number of
24841        // elements and subtracting one) before invoking `i18nExp` instructions, to make sure the
24842        // necessary lifecycle hooks of components/directives are properly flushed.
24843        this.updateInstructionWithAdvance(this.getConstCount() - 1, span, Identifiers.i18nExp, () => this.convertPropertyBinding(binding));
24844      }
24845
24846      this.updateInstruction(span, Identifiers.i18nApply, [literal(index)]);
24847    }
24848
24849    if (!selfClosing) {
24850      this.creationInstruction(span, Identifiers.i18nEnd);
24851    }
24852
24853    this.i18n = null; // reset local i18n context
24854  }
24855
24856  i18nAttributesInstruction(nodeIndex, attrs, sourceSpan) {
24857    let hasBindings = false;
24858    const i18nAttrArgs = [];
24859    attrs.forEach(attr => {
24860      const message = attr.i18n;
24861      const converted = attr.value.visit(this._valueConverter);
24862      this.allocateBindingSlots(converted);
24863
24864      if (converted instanceof Interpolation) {
24865        const placeholders = assembleBoundTextPlaceholders(message);
24866        const params = placeholdersToParams(placeholders);
24867        i18nAttrArgs.push(literal(attr.name), this.i18nTranslate(message, params));
24868        converted.expressions.forEach(expression => {
24869          hasBindings = true;
24870          this.updateInstructionWithAdvance(nodeIndex, sourceSpan, Identifiers.i18nExp, () => this.convertPropertyBinding(expression));
24871        });
24872      }
24873    });
24874
24875    if (i18nAttrArgs.length > 0) {
24876      const index = literal(this.allocateDataSlot());
24877      const constIndex = this.addToConsts(literalArr(i18nAttrArgs));
24878      this.creationInstruction(sourceSpan, Identifiers.i18nAttributes, [index, constIndex]);
24879
24880      if (hasBindings) {
24881        this.updateInstruction(sourceSpan, Identifiers.i18nApply, [index]);
24882      }
24883    }
24884  }
24885
24886  getNamespaceInstruction(namespaceKey) {
24887    switch (namespaceKey) {
24888      case 'math':
24889        return Identifiers.namespaceMathML;
24890
24891      case 'svg':
24892        return Identifiers.namespaceSVG;
24893
24894      default:
24895        return Identifiers.namespaceHTML;
24896    }
24897  }
24898
24899  addNamespaceInstruction(nsInstruction, element) {
24900    this._namespace = nsInstruction;
24901    this.creationInstruction(element.startSourceSpan, nsInstruction);
24902  }
24903  /**
24904   * Adds an update instruction for an interpolated property or attribute, such as
24905   * `prop="{{value}}"` or `attr.title="{{value}}"`
24906   */
24907
24908
24909  interpolatedUpdateInstruction(instruction, elementIndex, attrName, input, value, params) {
24910    this.updateInstructionWithAdvance(elementIndex, input.sourceSpan, instruction, () => [literal(attrName), ...this.getUpdateInstructionArguments(value), ...params]);
24911  }
24912
24913  visitContent(ngContent) {
24914    const slot = this.allocateDataSlot();
24915    const projectionSlotIdx = this._ngContentSelectorsOffset + this._ngContentReservedSlots.length;
24916    const parameters = [literal(slot)];
24917
24918    this._ngContentReservedSlots.push(ngContent.selector);
24919
24920    const nonContentSelectAttributes = ngContent.attributes.filter(attr => attr.name.toLowerCase() !== NG_CONTENT_SELECT_ATTR);
24921    const attributes = this.getAttributeExpressions(ngContent.name, nonContentSelectAttributes, [], []);
24922
24923    if (attributes.length > 0) {
24924      parameters.push(literal(projectionSlotIdx), literalArr(attributes));
24925    } else if (projectionSlotIdx !== 0) {
24926      parameters.push(literal(projectionSlotIdx));
24927    }
24928
24929    this.creationInstruction(ngContent.sourceSpan, Identifiers.projection, parameters);
24930
24931    if (this.i18n) {
24932      this.i18n.appendProjection(ngContent.i18n, slot);
24933    }
24934  }
24935
24936  visitElement(element) {
24937    const elementIndex = this.allocateDataSlot();
24938    const stylingBuilder = new StylingBuilder(null);
24939    let isNonBindableMode = false;
24940    const isI18nRootElement = isI18nRootNode(element.i18n) && !isSingleI18nIcu(element.i18n);
24941    const outputAttrs = [];
24942    const [namespaceKey, elementName] = splitNsName(element.name);
24943    const isNgContainer$1 = isNgContainer(element.name); // Handle styling, i18n, ngNonBindable attributes
24944
24945    for (const attr of element.attributes) {
24946      const {
24947        name,
24948        value
24949      } = attr;
24950
24951      if (name === NON_BINDABLE_ATTR) {
24952        isNonBindableMode = true;
24953      } else if (name === 'style') {
24954        stylingBuilder.registerStyleAttr(value);
24955      } else if (name === 'class') {
24956        stylingBuilder.registerClassAttr(value);
24957      } else {
24958        outputAttrs.push(attr);
24959      }
24960    } // Regular element or ng-container creation mode
24961
24962
24963    const parameters = [literal(elementIndex)];
24964
24965    if (!isNgContainer$1) {
24966      parameters.push(literal(elementName));
24967    } // Add the attributes
24968
24969
24970    const allOtherInputs = [];
24971    const boundI18nAttrs = [];
24972    element.inputs.forEach(input => {
24973      const stylingInputWasSet = stylingBuilder.registerBoundInput(input);
24974
24975      if (!stylingInputWasSet) {
24976        if (input.type === 0
24977        /* BindingType.Property */
24978        && input.i18n) {
24979          boundI18nAttrs.push(input);
24980        } else {
24981          allOtherInputs.push(input);
24982        }
24983      }
24984    }); // add attributes for directive and projection matching purposes
24985
24986    const attributes = this.getAttributeExpressions(element.name, outputAttrs, allOtherInputs, element.outputs, stylingBuilder, [], boundI18nAttrs);
24987    parameters.push(this.addAttrsToConsts(attributes)); // local refs (ex.: <div #foo #bar="baz">)
24988
24989    const refs = this.prepareRefsArray(element.references);
24990    parameters.push(this.addToConsts(refs));
24991    const wasInNamespace = this._namespace;
24992    const currentNamespace = this.getNamespaceInstruction(namespaceKey); // If the namespace is changing now, include an instruction to change it
24993    // during element creation.
24994
24995    if (currentNamespace !== wasInNamespace) {
24996      this.addNamespaceInstruction(currentNamespace, element);
24997    }
24998
24999    if (this.i18n) {
25000      this.i18n.appendElement(element.i18n, elementIndex);
25001    } // Note that we do not append text node instructions and ICUs inside i18n section,
25002    // so we exclude them while calculating whether current element has children
25003
25004
25005    const hasChildren = !isI18nRootElement && this.i18n ? !hasTextChildrenOnly(element.children) : element.children.length > 0;
25006    const createSelfClosingInstruction = !stylingBuilder.hasBindingsWithPipes && element.outputs.length === 0 && boundI18nAttrs.length === 0 && !hasChildren;
25007    const createSelfClosingI18nInstruction = !createSelfClosingInstruction && hasTextChildrenOnly(element.children);
25008
25009    if (createSelfClosingInstruction) {
25010      this.creationInstruction(element.sourceSpan, isNgContainer$1 ? Identifiers.elementContainer : Identifiers.element, trimTrailingNulls(parameters));
25011    } else {
25012      this.creationInstruction(element.startSourceSpan, isNgContainer$1 ? Identifiers.elementContainerStart : Identifiers.elementStart, trimTrailingNulls(parameters));
25013
25014      if (isNonBindableMode) {
25015        this.creationInstruction(element.startSourceSpan, Identifiers.disableBindings);
25016      }
25017
25018      if (boundI18nAttrs.length > 0) {
25019        this.i18nAttributesInstruction(elementIndex, boundI18nAttrs, element.startSourceSpan ?? element.sourceSpan);
25020      } // Generate Listeners (outputs)
25021
25022
25023      if (element.outputs.length > 0) {
25024        for (const outputAst of element.outputs) {
25025          this.creationInstruction(outputAst.sourceSpan, Identifiers.listener, this.prepareListenerParameter(element.name, outputAst, elementIndex));
25026        }
25027      } // Note: it's important to keep i18n/i18nStart instructions after i18nAttributes and
25028      // listeners, to make sure i18nAttributes instruction targets current element at runtime.
25029
25030
25031      if (isI18nRootElement) {
25032        this.i18nStart(element.startSourceSpan, element.i18n, createSelfClosingI18nInstruction);
25033      }
25034    } // the code here will collect all update-level styling instructions and add them to the
25035    // update block of the template function AOT code. Instructions like `styleProp`,
25036    // `styleMap`, `classMap`, `classProp`
25037    // are all generated and assigned in the code below.
25038
25039
25040    const stylingInstructions = stylingBuilder.buildUpdateLevelInstructions(this._valueConverter);
25041    const limit = stylingInstructions.length - 1;
25042
25043    for (let i = 0; i <= limit; i++) {
25044      const instruction = stylingInstructions[i];
25045      this._bindingSlots += this.processStylingUpdateInstruction(elementIndex, instruction);
25046    } // the reason why `undefined` is used is because the renderer understands this as a
25047    // special value to symbolize that there is no RHS to this binding
25048    // TODO (matsko): revisit this once FW-959 is approached
25049
25050
25051    const emptyValueBindInstruction = literal(undefined);
25052    const propertyBindings = [];
25053    const attributeBindings = []; // Generate element input bindings
25054
25055    allOtherInputs.forEach(input => {
25056      const inputType = input.type;
25057
25058      if (inputType === 4
25059      /* BindingType.Animation */
25060      ) {
25061        const value = input.value.visit(this._valueConverter); // animation bindings can be presented in the following formats:
25062        // 1. [@binding]="fooExp"
25063        // 2. [@binding]="{value:fooExp, params:{...}}"
25064        // 3. [@binding]
25065        // 4. @binding
25066        // All formats will be valid for when a synthetic binding is created.
25067        // The reasoning for this is because the renderer should get each
25068        // synthetic binding value in the order of the array that they are
25069        // defined in...
25070
25071        const hasValue = value instanceof LiteralPrimitive ? !!value.value : true;
25072        this.allocateBindingSlots(value);
25073        propertyBindings.push({
25074          span: input.sourceSpan,
25075          paramsOrFn: getBindingFunctionParams(() => hasValue ? this.convertPropertyBinding(value) : emptyValueBindInstruction, prepareSyntheticPropertyName(input.name))
25076        });
25077      } else {
25078        // we must skip attributes with associated i18n context, since these attributes are handled
25079        // separately and corresponding `i18nExp` and `i18nApply` instructions will be generated
25080        if (input.i18n) return;
25081        const value = input.value.visit(this._valueConverter);
25082
25083        if (value !== undefined) {
25084          const params = [];
25085          const [attrNamespace, attrName] = splitNsName(input.name);
25086          const isAttributeBinding = inputType === 1
25087          /* BindingType.Attribute */
25088          ;
25089          let sanitizationRef = resolveSanitizationFn(input.securityContext, isAttributeBinding);
25090
25091          if (!sanitizationRef) {
25092            // If there was no sanitization function found based on the security context
25093            // of an attribute/property - check whether this attribute/property is
25094            // one of the security-sensitive <iframe> attributes (and that the current
25095            // element is actually an <iframe>).
25096            if (isIframeElement(element.name) && isIframeSecuritySensitiveAttr(input.name)) {
25097              sanitizationRef = importExpr(Identifiers.validateIframeAttribute);
25098            }
25099          }
25100
25101          if (sanitizationRef) {
25102            params.push(sanitizationRef);
25103          }
25104
25105          if (attrNamespace) {
25106            const namespaceLiteral = literal(attrNamespace);
25107
25108            if (sanitizationRef) {
25109              params.push(namespaceLiteral);
25110            } else {
25111              // If there wasn't a sanitization ref, we need to add
25112              // an extra param so that we can pass in the namespace.
25113              params.push(literal(null), namespaceLiteral);
25114            }
25115          }
25116
25117          this.allocateBindingSlots(value);
25118
25119          if (inputType === 0
25120          /* BindingType.Property */
25121          ) {
25122            if (value instanceof Interpolation) {
25123              // prop="{{value}}" and friends
25124              this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), elementIndex, attrName, input, value, params);
25125            } else {
25126              // [prop]="value"
25127              // Collect all the properties so that we can chain into a single function at the end.
25128              propertyBindings.push({
25129                span: input.sourceSpan,
25130                paramsOrFn: getBindingFunctionParams(() => this.convertPropertyBinding(value), attrName, params)
25131              });
25132            }
25133          } else if (inputType === 1
25134          /* BindingType.Attribute */
25135          ) {
25136            if (value instanceof Interpolation && getInterpolationArgsLength(value) > 1) {
25137              // attr.name="text{{value}}" and friends
25138              this.interpolatedUpdateInstruction(getAttributeInterpolationExpression(value), elementIndex, attrName, input, value, params);
25139            } else {
25140              const boundValue = value instanceof Interpolation ? value.expressions[0] : value; // [attr.name]="value" or attr.name="{{value}}"
25141              // Collect the attribute bindings so that they can be chained at the end.
25142
25143              attributeBindings.push({
25144                span: input.sourceSpan,
25145                paramsOrFn: getBindingFunctionParams(() => this.convertPropertyBinding(boundValue), attrName, params)
25146              });
25147            }
25148          } else {
25149            // class prop
25150            this.updateInstructionWithAdvance(elementIndex, input.sourceSpan, Identifiers.classProp, () => {
25151              return [literal(elementIndex), literal(attrName), this.convertPropertyBinding(value), ...params];
25152            });
25153          }
25154        }
25155      }
25156    });
25157
25158    for (const propertyBinding of propertyBindings) {
25159      this.updateInstructionWithAdvance(elementIndex, propertyBinding.span, Identifiers.property, propertyBinding.paramsOrFn);
25160    }
25161
25162    for (const attributeBinding of attributeBindings) {
25163      this.updateInstructionWithAdvance(elementIndex, attributeBinding.span, Identifiers.attribute, attributeBinding.paramsOrFn);
25164    } // Traverse element child nodes
25165
25166
25167    visitAll$1(this, element.children);
25168
25169    if (!isI18nRootElement && this.i18n) {
25170      this.i18n.appendElement(element.i18n, elementIndex, true);
25171    }
25172
25173    if (!createSelfClosingInstruction) {
25174      // Finish element construction mode.
25175      const span = element.endSourceSpan ?? element.sourceSpan;
25176
25177      if (isI18nRootElement) {
25178        this.i18nEnd(span, createSelfClosingI18nInstruction);
25179      }
25180
25181      if (isNonBindableMode) {
25182        this.creationInstruction(span, Identifiers.enableBindings);
25183      }
25184
25185      this.creationInstruction(span, isNgContainer$1 ? Identifiers.elementContainerEnd : Identifiers.elementEnd);
25186    }
25187  }
25188
25189  visitTemplate(template) {
25190    const NG_TEMPLATE_TAG_NAME = 'ng-template';
25191    const templateIndex = this.allocateDataSlot();
25192
25193    if (this.i18n) {
25194      this.i18n.appendTemplate(template.i18n, templateIndex);
25195    }
25196
25197    const tagNameWithoutNamespace = template.tagName ? splitNsName(template.tagName)[1] : template.tagName;
25198    const contextName = `${this.contextName}${template.tagName ? '_' + sanitizeIdentifier(template.tagName) : ''}_${templateIndex}`;
25199    const templateName = `${contextName}_Template`;
25200    const parameters = [literal(templateIndex), variable(templateName), // We don't care about the tag's namespace here, because we infer
25201    // it based on the parent nodes inside the template instruction.
25202    literal(tagNameWithoutNamespace)]; // prepare attributes parameter (including attributes used for directive matching)
25203
25204    const attrsExprs = this.getAttributeExpressions(NG_TEMPLATE_TAG_NAME, template.attributes, template.inputs, template.outputs, undefined
25205    /* styles */
25206    , template.templateAttrs);
25207    parameters.push(this.addAttrsToConsts(attrsExprs)); // local refs (ex.: <ng-template #foo>)
25208
25209    if (template.references && template.references.length) {
25210      const refs = this.prepareRefsArray(template.references);
25211      parameters.push(this.addToConsts(refs));
25212      parameters.push(importExpr(Identifiers.templateRefExtractor));
25213    } // Create the template function
25214
25215
25216    const templateVisitor = new TemplateDefinitionBuilder(this.constantPool, this._bindingScope, this.level + 1, contextName, this.i18n, templateIndex, templateName, this._namespace, this.fileBasedI18nSuffix, this.i18nUseExternalIds, this._constants); // Nested templates must not be visited until after their parent templates have completed
25217    // processing, so they are queued here until after the initial pass. Otherwise, we wouldn't
25218    // be able to support bindings in nested templates to local refs that occur after the
25219    // template definition. e.g. <div *ngIf="showing">{{ foo }}</div>  <div #foo></div>
25220
25221    this._nestedTemplateFns.push(() => {
25222      const templateFunctionExpr = templateVisitor.buildTemplateFunction(template.children, template.variables, this._ngContentReservedSlots.length + this._ngContentSelectorsOffset, template.i18n);
25223      this.constantPool.statements.push(templateFunctionExpr.toDeclStmt(templateName));
25224
25225      if (templateVisitor._ngContentReservedSlots.length) {
25226        this._ngContentReservedSlots.push(...templateVisitor._ngContentReservedSlots);
25227      }
25228    }); // e.g. template(1, MyComp_Template_1)
25229
25230
25231    this.creationInstruction(template.sourceSpan, Identifiers.templateCreate, () => {
25232      parameters.splice(2, 0, literal(templateVisitor.getConstCount()), literal(templateVisitor.getVarCount()));
25233      return trimTrailingNulls(parameters);
25234    }); // handle property bindings e.g. ɵɵproperty('ngForOf', ctx.items), et al;
25235
25236    this.templatePropertyBindings(templateIndex, template.templateAttrs); // Only add normal input/output binding instructions on explicit <ng-template> elements.
25237
25238    if (tagNameWithoutNamespace === NG_TEMPLATE_TAG_NAME) {
25239      const [i18nInputs, inputs] = partitionArray(template.inputs, hasI18nMeta); // Add i18n attributes that may act as inputs to directives. If such attributes are present,
25240      // generate `i18nAttributes` instruction. Note: we generate it only for explicit <ng-template>
25241      // elements, in case of inline templates, corresponding instructions will be generated in the
25242      // nested template function.
25243
25244      if (i18nInputs.length > 0) {
25245        this.i18nAttributesInstruction(templateIndex, i18nInputs, template.startSourceSpan ?? template.sourceSpan);
25246      } // Add the input bindings
25247
25248
25249      if (inputs.length > 0) {
25250        this.templatePropertyBindings(templateIndex, inputs);
25251      } // Generate listeners for directive output
25252
25253
25254      for (const outputAst of template.outputs) {
25255        this.creationInstruction(outputAst.sourceSpan, Identifiers.listener, this.prepareListenerParameter('ng_template', outputAst, templateIndex));
25256      }
25257    }
25258  }
25259
25260  visitBoundText(text) {
25261    if (this.i18n) {
25262      const value = text.value.visit(this._valueConverter);
25263      this.allocateBindingSlots(value);
25264
25265      if (value instanceof Interpolation) {
25266        this.i18n.appendBoundText(text.i18n);
25267        this.i18nAppendBindings(value.expressions);
25268      }
25269
25270      return;
25271    }
25272
25273    const nodeIndex = this.allocateDataSlot();
25274    this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(nodeIndex)]);
25275    const value = text.value.visit(this._valueConverter);
25276    this.allocateBindingSlots(value);
25277
25278    if (value instanceof Interpolation) {
25279      this.updateInstructionWithAdvance(nodeIndex, text.sourceSpan, getTextInterpolationExpression(value), () => this.getUpdateInstructionArguments(value));
25280    } else {
25281      error('Text nodes should be interpolated and never bound directly.');
25282    }
25283  }
25284
25285  visitText(text) {
25286    // when a text element is located within a translatable
25287    // block, we exclude this text element from instructions set,
25288    // since it will be captured in i18n content and processed at runtime
25289    if (!this.i18n) {
25290      this.creationInstruction(text.sourceSpan, Identifiers.text, [literal(this.allocateDataSlot()), literal(text.value)]);
25291    }
25292  }
25293
25294  visitIcu(icu) {
25295    let initWasInvoked = false; // if an ICU was created outside of i18n block, we still treat
25296    // it as a translatable entity and invoke i18nStart and i18nEnd
25297    // to generate i18n context and the necessary instructions
25298
25299    if (!this.i18n) {
25300      initWasInvoked = true;
25301      this.i18nStart(null, icu.i18n, true);
25302    }
25303
25304    const i18n = this.i18n;
25305    const vars = this.i18nBindProps(icu.vars);
25306    const placeholders = this.i18nBindProps(icu.placeholders); // output ICU directly and keep ICU reference in context
25307
25308    const message = icu.i18n; // we always need post-processing function for ICUs, to make sure that:
25309    // - all placeholders in a form of {PLACEHOLDER} are replaced with actual values (note:
25310    // `goog.getMsg` does not process ICUs and uses the `{PLACEHOLDER}` format for placeholders
25311    // inside ICUs)
25312    // - all ICU vars (such as `VAR_SELECT` or `VAR_PLURAL`) are replaced with correct values
25313
25314    const transformFn = raw => {
25315      const params = { ...vars,
25316        ...placeholders
25317      };
25318      const formatted = formatI18nPlaceholderNamesInMap(params,
25319      /* useCamelCase */
25320      false);
25321      return invokeInstruction(null, Identifiers.i18nPostprocess, [raw, mapLiteral(formatted, true)]);
25322    }; // in case the whole i18n message is a single ICU - we do not need to
25323    // create a separate top-level translation, we can use the root ref instead
25324    // and make this ICU a top-level translation
25325    // note: ICU placeholders are replaced with actual values in `i18nPostprocess` function
25326    // separately, so we do not pass placeholders into `i18nTranslate` function.
25327
25328
25329    if (isSingleI18nIcu(i18n.meta)) {
25330      this.i18nTranslate(message,
25331      /* placeholders */
25332      {}, i18n.ref, transformFn);
25333    } else {
25334      // output ICU directly and keep ICU reference in context
25335      const ref = this.i18nTranslate(message,
25336      /* placeholders */
25337      {},
25338      /* ref */
25339      undefined, transformFn);
25340      i18n.appendIcu(icuFromI18nMessage(message).name, ref);
25341    }
25342
25343    if (initWasInvoked) {
25344      this.i18nEnd(null, true);
25345    }
25346
25347    return null;
25348  }
25349
25350  allocateDataSlot() {
25351    return this._dataIndex++;
25352  }
25353
25354  getConstCount() {
25355    return this._dataIndex;
25356  }
25357
25358  getVarCount() {
25359    return this._pureFunctionSlots;
25360  }
25361
25362  getConsts() {
25363    return this._constants;
25364  }
25365
25366  getNgContentSelectors() {
25367    return this._ngContentReservedSlots.length ? this.constantPool.getConstLiteral(asLiteral(this._ngContentReservedSlots), true) : null;
25368  }
25369
25370  bindingContext() {
25371    return `${this._bindingContext++}`;
25372  }
25373
25374  templatePropertyBindings(templateIndex, attrs) {
25375    const propertyBindings = [];
25376
25377    for (const input of attrs) {
25378      if (!(input instanceof BoundAttribute)) {
25379        continue;
25380      }
25381
25382      const value = input.value.visit(this._valueConverter);
25383
25384      if (value === undefined) {
25385        continue;
25386      }
25387
25388      this.allocateBindingSlots(value);
25389
25390      if (value instanceof Interpolation) {
25391        // Params typically contain attribute namespace and value sanitizer, which is applicable
25392        // for regular HTML elements, but not applicable for <ng-template> (since props act as
25393        // inputs to directives), so keep params array empty.
25394        const params = []; // prop="{{value}}" case
25395
25396        this.interpolatedUpdateInstruction(getPropertyInterpolationExpression(value), templateIndex, input.name, input, value, params);
25397      } else {
25398        // [prop]="value" case
25399        propertyBindings.push({
25400          span: input.sourceSpan,
25401          paramsOrFn: getBindingFunctionParams(() => this.convertPropertyBinding(value), input.name)
25402        });
25403      }
25404    }
25405
25406    for (const propertyBinding of propertyBindings) {
25407      this.updateInstructionWithAdvance(templateIndex, propertyBinding.span, Identifiers.property, propertyBinding.paramsOrFn);
25408    }
25409  } // Bindings must only be resolved after all local refs have been visited, so all
25410  // instructions are queued in callbacks that execute once the initial pass has completed.
25411  // Otherwise, we wouldn't be able to support local refs that are defined after their
25412  // bindings. e.g. {{ foo }} <div #foo></div>
25413
25414
25415  instructionFn(fns, span, reference, paramsOrFn, prepend = false) {
25416    fns[prepend ? 'unshift' : 'push']({
25417      span,
25418      reference,
25419      paramsOrFn
25420    });
25421  }
25422
25423  processStylingUpdateInstruction(elementIndex, instruction) {
25424    let allocateBindingSlots = 0;
25425
25426    if (instruction) {
25427      for (const call of instruction.calls) {
25428        allocateBindingSlots += call.allocateBindingSlots;
25429        this.updateInstructionWithAdvance(elementIndex, call.sourceSpan, instruction.reference, () => call.params(value =>
25429 call.supportsInterpolation && value instanceof Interpolation ? this.getUpdateInstructionArguments(value) : this.convertPropertyBinding(value)));
25430      }
25431    }
25432
25433    return allocateBindingSlots;
25434  }
25435
25436  creationInstruction(span, reference, paramsOrFn, prepend) {
25437    this.instructionFn(this._creationCodeFns, span, reference, paramsOrFn || [], prepend);
25438  }
25439
25440  updateInstructionWithAdvance(nodeIndex, span, reference, paramsOrFn) {
25441    this.addAdvanceInstructionIfNecessary(nodeIndex, span);
25442    this.updateInstruction(span, reference, paramsOrFn);
25443  }
25444
25445  updateInstruction(span, reference, paramsOrFn) {
25446    this.instructionFn(this._updateCodeFns, span, reference, paramsOrFn || []);
25447  }
25448
25449  addAdvanceInstructionIfNecessary(nodeIndex, span) {
25450    if (nodeIndex !== this._currentIndex) {
25451      const delta = nodeIndex - this._currentIndex;
25452
25453      if (delta < 1) {
25454        throw new Error('advance instruction can only go forwards');
25455      }
25456
25457      this.instructionFn(this._updateCodeFns, span, Identifiers.advance, [literal(delta)]);
25458      this._currentIndex = nodeIndex;
25459    }
25460  }
25461
25462  allocatePureFunctionSlots(numSlots) {
25463    const originalSlots = this._pureFunctionSlots;
25464    this._pureFunctionSlots += numSlots;
25465    return originalSlots;
25466  }
25467
25468  allocateBindingSlots(value) {
25469    this._bindingSlots += value instanceof Interpolation ? value.expressions.length : 1;
25470  }
25471  /**
25472   * Gets an expression that refers to the implicit receiver. The implicit
25473   * receiver is always the root level context.
25474   */
25475
25476
25477  getImplicitReceiverExpr() {
25478    if (this._implicitReceiverExpr) {
25479      return this._implicitReceiverExpr;
25480    }
25481
25482    return this._implicitReceiverExpr = this.level === 0 ? variable(CONTEXT_NAME) : this._bindingScope.getOrCreateSharedContextVar(0);
25483  }
25484
25485  convertPropertyBinding(value) {
25486    const convertedPropertyBinding = convertPropertyBinding(this, this.getImplicitReceiverExpr(), value, this.bindingContext());
25487    const valExpr = convertedPropertyBinding.currValExpr;
25488
25489    this._tempVariables.push(...convertedPropertyBinding.stmts);
25490
25491    return valExpr;
25492  }
25493  /**
25494   * Gets a list of argument expressions to pass to an update instruction expression. Also updates
25495   * the temp variables state with temp variables that were identified as needing to be created
25496   * while visiting the arguments.
25497   * @param value The original expression we will be resolving an arguments list from.
25498   */
25499
25500
25501  getUpdateInstructionArguments(value) {
25502    const {
25503      args,
25504      stmts
25505    } = convertUpdateArguments(this, this.getImplicitReceiverExpr(), value, this.bindingContext());
25506
25507    this._tempVariables.push(...stmts);
25508
25509    return args;
25510  }
25511  /**
25512   * Prepares all attribute expression values for the `TAttributes` array.
25513   *
25514   * The purpose of this function is to properly construct an attributes array that
25515   * is passed into the `elementStart` (or just `element`) functions. Because there
25516   * are many different types of attributes, the array needs to be constructed in a
25517   * special way so that `elementStart` can properly evaluate them.
25518   *
25519   * The format looks like this:
25520   *
25521   * ```
25522   * attrs = [prop, value, prop2, value2,
25523   *   PROJECT_AS, selector,
25524   *   CLASSES, class1, class2,
25525   *   STYLES, style1, value1, style2, value2,
25526   *   BINDINGS, name1, name2, name3,
25527   *   TEMPLATE, name4, name5, name6,
25528   *   I18N, name7, name8, ...]
25529   * ```
25530   *
25531   * Note that this function will fully ignore all synthetic (@foo) attribute values
25532   * because those values are intended to always be generated as property instructions.
25533   */
25534
25535
25536  getAttributeExpressions(elementName, renderAttributes, inputs, outputs, styles, templateAttrs = [], boundI18nAttrs = []) {
25537    const alreadySeen = new Set();
25538    const attrExprs = [];
25539    let ngProjectAsAttr;
25540
25541    for (const attr of renderAttributes) {
25542      if (attr.name === NG_PROJECT_AS_ATTR_NAME) {
25543        ngProjectAsAttr = attr;
25544      } // Note that static i18n attributes aren't in the i18n array,
25545      // because they're treated in the same way as regular attributes.
25546
25547
25548      if (attr.i18n) {
25549        // When i18n attributes are present on elements with structural directives
25550        // (e.g. `<div *ngIf title="Hello" i18n-title>`), we want to avoid generating
25551        // duplicate i18n translation blocks for `ɵɵtemplate` and `ɵɵelement` instruction
25552        // attributes. So we do a cache lookup to see if suitable i18n translation block
25553        // already exists.
25554        const {
25555          i18nVarRefsCache
25556        } = this._constants;
25557        let i18nVarRef;
25558
25559        if (i18nVarRefsCache.has(attr.i18n)) {
25560          i18nVarRef = i18nVarRefsCache.get(attr.i18n);
25561        } else {
25562          i18nVarRef = this.i18nTranslate(attr.i18n);
25563          i18nVarRefsCache.set(attr.i18n, i18nVarRef);
25564        }
25565
25566        attrExprs.push(literal(attr.name), i18nVarRef);
25567      } else {
25568        attrExprs.push(...getAttributeNameLiterals(attr.name), trustedConstAttribute(elementName, attr));
25569      }
25570    } // Keep ngProjectAs next to the other name, value pairs so we can verify that we match
25571    // ngProjectAs marker in the attribute name slot.
25572
25573
25574    if (ngProjectAsAttr) {
25575      attrExprs.push(...getNgProjectAsLiteral(ngProjectAsAttr));
25576    }
25577
25578    function addAttrExpr(key, value) {
25579      if (typeof key === 'string') {
25580        if (!alreadySeen.has(key)) {
25581          attrExprs.push(...getAttributeNameLiterals(key));
25582          value !== undefined && attrExprs.push(value);
25583          alreadySeen.add(key);
25584        }
25585      } else {
25586        attrExprs.push(literal(key));
25587      }
25588    } // it's important that this occurs before BINDINGS and TEMPLATE because once `elementStart`
25589    // comes across the BINDINGS or TEMPLATE markers then it will continue reading each value as
25590    // as single property value cell by cell.
25591
25592
25593    if (styles) {
25594      styles.populateInitialStylingAttrs(attrExprs);
25595    }
25596
25597    if (inputs.length || outputs.length) {
25598      const attrsLengthBeforeInputs = attrExprs.length;
25599
25600      for (let i = 0; i < inputs.length; i++) {
25601        const input = inputs[i]; // We don't want the animation and attribute bindings in the
25602        // attributes array since they aren't used for directive matching.
25603
25604        if (input.type !== 4
25605        /* BindingType.Animation */
25606        && input.type !== 1
25607        /* BindingType.Attribute */
25608        ) {
25609          addAttrExpr(input.name);
25610        }
25611      }
25612
25613      for (let i = 0; i < outputs.length; i++) {
25614        const output = outputs[i];
25615
25616        if (output.type !== 1
25617        /* ParsedEventType.Animation */
25618        ) {
25619          addAttrExpr(output.name);
25620        }
25621      } // this is a cheap way of adding the marker only after all the input/output
25622      // values have been filtered (by not including the animation ones) and added
25623      // to the expressions. The marker is important because it tells the runtime
25624      // code that this is where attributes without values start...
25625
25626
25627      if (attrExprs.length !== attrsLengthBeforeInputs) {
25628        attrExprs.splice(attrsLengthBeforeInputs, 0, literal(3
25629        /* core.AttributeMarker.Bindings */
25630        ));
25631      }
25632    }
25633
25634    if (templateAttrs.length) {
25635      attrExprs.push(literal(4
25636      /* core.AttributeMarker.Template */
25637      ));
25638      templateAttrs.forEach(attr => addAttrExpr(attr.name));
25639    }
25640
25641    if (boundI18nAttrs.length) {
25642      attrExprs.push(literal(6
25643      /* core.AttributeMarker.I18n */
25644      ));
25645      boundI18nAttrs.forEach(attr => addAttrExpr(attr.name));
25646    }
25647
25648    return attrExprs;
25649  }
25650
25651  addToConsts(expression) {
25652    if (isNull(expression)) {
25653      return TYPED_NULL_EXPR;
25654    }
25655
25656    const consts = this._constants.constExpressions; // Try to reuse a literal that's already in the array, if possible.
25657
25658    for (let i = 0; i < consts.length; i++) {
25659      if (consts[i].isEquivalent(expression)) {
25660        return literal(i);
25661      }
25662    }
25663
25664    return literal(consts.push(expression) - 1);
25665  }
25666
25667  addAttrsToConsts(attrs) {
25668    return attrs.length > 0 ? this.addToConsts(literalArr(attrs)) : TYPED_NULL_EXPR;
25669  }
25670
25671  prepareRefsArray(references) {
25672    if (!references || references.length === 0) {
25673      return TYPED_NULL_EXPR;
25674    }
25675
25676    const refsParam = flatten(references.map(reference => {
25677      const slot = this.allocateDataSlot(); // Generate the update temporary.
25678
25679      const variableName = this._bindingScope.freshReferenceName();
25680
25681      const retrievalLevel = this.level;
25682      const lhs = variable(variableName);
25683
25684      this._bindingScope.set(retrievalLevel, reference.name, lhs, 0
25685      /* DeclarationPriority.DEFAULT */
25686      , (scope, relativeLevel) => {
25687        // e.g. nextContext(2);
25688        const nextContextStmt = relativeLevel > 0 ? [generateNextContextExpr(relativeLevel).toStmt()] : []; // e.g. const $foo$ = reference(1);
25689
25690        const refExpr = lhs.set(importExpr(Identifiers.reference).callFn([literal(slot)]));
25691        return nextContextStmt.concat(refExpr.toConstDecl());
25692      }, true);
25693
25694      return [reference.name, reference.value];
25695    }));
25696    return asLiteral(refsParam);
25697  }
25698
25699  prepareListenerParameter(tagName, outputAst, index) {
25700    return () => {
25701      const eventName = outputAst.name;
25702      const bindingFnName = outputAst.type === 1
25703      /* ParsedEventType.Animation */
25704      ? // synthetic @listener.foo values are treated the exact same as are standard listeners
25705      prepareSyntheticListenerFunctionName(eventName, outputAst.phase) : sanitizeIdentifier(eventName);
25706      const handlerName = `${this.templateName}_${tagName}_${bindingFnName}_${index}_listener`;
25707
25708      const scope = this._bindingScope.nestedScope(this._bindingScope.bindingLevel, EVENT_BINDING_SCOPE_GLOBALS);
25709
25710      return prepareEventListenerParameters(outputAst, handlerName, scope);
25711    };
25712  }
25713
25714}
25715
25716class ValueConverter extends AstMemoryEfficientTransformer {
25717  constructor(constantPool, allocateSlot, allocatePureFunctionSlots, definePipe) {
25718    super();
25719    this.constantPool = constantPool;
25720    this.allocateSlot = allocateSlot;
25721    this.allocatePureFunctionSlots = allocatePureFunctionSlots;
25722    this.definePipe = definePipe;
25723    this._pipeBindExprs = [];
25724  } // AstMemoryEfficientTransformer
25725
25726
25727  visitPipe(pipe, context) {
25728    // Allocate a slot to create the pipe
25729    const slot = this.allocateSlot();
25730    const slotPseudoLocal = `PIPE:${slot}`; // Allocate one slot for the result plus one slot per pipe argument
25731
25732    const pureFunctionSlot = this.allocatePureFunctionSlots(2 + pipe.args.length);
25733    const target = new PropertyRead(pipe.span, pipe.sourceSpan, pipe.nameSpan, new ImplicitReceiver(pipe.span, pipe.sourceSpan), slotPseudoLocal);
25734    const {
25735      identifier,
25736      isVarLength
25737    } = pipeBindingCallInfo(pipe.args);
25738    this.definePipe(pipe.name, slotPseudoLocal, slot, importExpr(identifier));
25739    const args = [pipe.exp, ...pipe.args];
25740    const convertedArgs = isVarLength ? this.visitAll([new LiteralArray(pipe.span, pipe.sourceSpan, args)]) : this.visitAll(args);
25741    const pipeBindExpr = new Call(pipe.span, pipe.sourceSpan, target, [new LiteralPrimitive(pipe.span, pipe.sourceSpan, slot), new LiteralPrimitive(pipe.span, pipe.sourceSpan, pureFunctionSlot), ...convertedArgs], null);
25742
25743    this._pipeBindExprs.push(pipeBindExpr);
25744
25745    return pipeBindExpr;
25746  }
25747
25748  updatePipeSlotOffsets(bindingSlots) {
25749    this._pipeBindExprs.forEach(pipe => {
25750      // update the slot offset arg (index 1) to account for binding slots
25751      const slotOffset = pipe.args[1];
25752      slotOffset.value += bindingSlots;
25753    });
25754  }
25755
25756  visitLiteralArray(array, context) {
25757    return new BuiltinFunctionCall(array.span, array.sourceSpan, this.visitAll(array.expressions), values => {
25758      // If the literal has calculated (non-literal) elements transform it into
25759      // calls to literal factories that compose the literal and will cache intermediate
25760      // values.
25761      const literal = literalArr(values);
25762      return getLiteralFactory(this.constantPool, literal, this.allocatePureFunctionSlots);
25763    });
25764  }
25765
25766  visitLiteralMap(map, context) {
25767    return new BuiltinFunctionCall(map.span, map.sourceSpan, this.visitAll(map.values), values => {
25768      // If the literal has calculated (non-literal) elements  transform it into
25769      // calls to literal factories that compose the literal and will cache intermediate
25770      // values.
25771      const literal = literalMap(values.map((value, index) => ({
25772        key: map.keys[index].key,
25773        value,
25774        quoted: map.keys[index].quoted
25775      })));
25776      return getLiteralFactory(this.constantPool, literal, this.allocatePureFunctionSlots);
25777    });
25778  }
25779
25780} // Pipes always have at least one parameter, the value they operate on
25781
25782
25783const pipeBindingIdentifiers = [Identifiers.pipeBind1, Identifiers.pipeBind2, Identifiers.pipeBind3, Identifiers.pipeBind4];
25784
25785function pipeBindingCallInfo(args) {
25786  const identifier = pipeBindingIdentifiers[args.length];
25787  return {
25788    identifier: identifier || Identifiers.pipeBindV,
25789    isVarLength: !identifier
25790  };
25791}
25792
25793const pureFunctionIdentifiers = [Identifiers.pureFunction0, Identifiers.pureFunction1, Identifiers.pureFunction2, Identifiers.pureFunction3, Identifiers.pureFunction4, Identifiers.pureFunction5, Identifiers.pureFunction6, Identifiers.pureFunction7, Identifiers.pureFunction8];
25794
25795function pureFunctionCallInfo(args) {
25796  const identifier = pureFunctionIdentifiers[args.length];
25797  return {
25798    identifier: identifier || Identifiers.pureFunctionV,
25799    isVarLength: !identifier
25800  };
25801} // e.g. x(2);
25802
25803
25804function generateNextContextExpr(relativeLevelDiff) {
25805  return importExpr(Identifiers.nextContext).callFn(relativeLevelDiff > 1 ? [literal(relativeLevelDiff)] : []);
25806}
25807
25808function getLiteralFactory(constantPool, literal$1, allocateSlots) {
25809  const {
25810    literalFactory,
25811    literalFactoryArguments
25812  } = constantPool.getLiteralFactory(literal$1); // Allocate 1 slot for the result plus 1 per argument
25813
25814  const startSlot = allocateSlots(1 + literalFactoryArguments.length);
25815  const {
25816    identifier,
25817    isVarLength
25818  } = pureFunctionCallInfo(literalFactoryArguments); // Literal factories are pure functions that only need to be re-invoked when the parameters
25819  // change.
25820
25821  const args = [literal(startSlot), literalFactory];
25822
25823  if (isVarLength) {
25824    args.push(literalArr(literalFactoryArguments));
25825  } else {
25826    args.push(...literalFactoryArguments);
25827  }
25828
25829  return importExpr(identifier).callFn(args);
25830}
25831/**
25832 * Gets an array of literals that can be added to an expression
25833 * to represent the name and namespace of an attribute. E.g.
25834 * `:xlink:href` turns into `[AttributeMarker.NamespaceURI, 'xlink', 'href']`.
25835 *
25836 * @param name Name of the attribute, including the namespace.
25837 */
25838
25839
25840function getAttributeNameLiterals(name) {
25841  const [attributeNamespace, attributeName] = splitNsName(name);
25842  const nameLiteral = literal(attributeName);
25843
25844  if (attributeNamespace) {
25845    return [literal(0
25846    /* core.AttributeMarker.NamespaceURI */
25847    ), literal(attributeNamespace), nameLiteral];
25848  }
25849
25850  return [nameLiteral];
25851}
25852/** The prefix used to get a shared context in BindingScope's map. */
25853
25854
25855const SHARED_CONTEXT_KEY = '$$shared_ctx$$';
25856
25857class BindingScope {
25858  constructor(bindingLevel = 0, parent = null, globals) {
25859    this.bindingLevel = bindingLevel;
25860    this.parent = parent;
25861    this.globals = globals;
25862    /** Keeps a map from local variables to their BindingData. */
25863
25864    this.map = new Map();
25865    this.referenceNameIndex = 0;
25866    this.restoreViewVariable = null;
25867    this.usesRestoredViewContext = false;
25868
25869    if (globals !== undefined) {
25870      for (const name of globals) {
25871        this.set(0, name, variable(name));
25872      }
25873    }
25874  }
25875
25876  static createRootScope() {
25877    return new BindingScope();
25878  }
25879
25880  get(name) {
25881    let current = this;
25882
25883    while (current) {
25884      let value = current.map.get(name);
25885
25886      if (value != null) {
25887        if (current !== this) {
25888          // make a local copy and reset the `declare` state
25889          value = {
25890            retrievalLevel: value.retrievalLevel,
25891            lhs: value.lhs,
25892            declareLocalCallback: value.declareLocalCallback,
25893            declare: false,
25894            priority: value.priority
25895          }; // Cache the value locally.
25896
25897          this.map.set(name, value); // Possibly generate a shared context var
25898
25899          this.maybeGenerateSharedContextVar(value);
25900          this.maybeRestoreView();
25901        }
25902
25903        if (value.declareLocalCallback && !value.declare) {
25904          value.declare = true;
25905        }
25906
25907        return value.lhs;
25908      }
25909
25910      current = current.parent;
25911    } // If we get to this point, we are looking for a property on the top level component
25912    // - If level === 0, we are on the top and don't need to re-declare `ctx`.
25913    // - If level > 0, we are in an embedded view. We need to retrieve the name of the
25914    // local var we used to store the component context, e.g. const $comp$ = x();
25915
25916
25917    return this.bindingLevel === 0 ? null : this.getComponentProperty(name);
25918  }
25919  /**
25920   * Create a local variable for later reference.
25921   *
25922   * @param retrievalLevel The level from which this value can be retrieved
25923   * @param name Name of the variable.
25924   * @param lhs AST representing the left hand side of the `let lhs = rhs;`.
25925   * @param priority The sorting priority of this var
25926   * @param declareLocalCallback The callback to invoke when declaring this local var
25927   * @param localRef Whether or not this is a local ref
25928   */
25929
25930
25931  set(retrievalLevel, name, lhs, priority = 0
25932  /* DeclarationPriority.DEFAULT */
25933  , declareLocalCallback, localRef) {
25934    if (this.map.has(name)) {
25935      if (localRef) {
25936        // Do not throw an error if it's a local ref and do not update existing value,
25937        // so the first defined ref is always returned.
25938        return this;
25939      }
25940
25941      error(`The name ${name} is already defined in scope to be ${this.map.get(name)}`);
25942    }
25943
25944    this.map.set(name, {
25945      retrievalLevel: retrievalLevel,
25946      lhs: lhs,
25947      declare: false,
25948      declareLocalCallback: declareLocalCallback,
25949      priority: priority
25950    });
25951    return this;
25952  } // Implemented as part of LocalResolver.
25953
25954
25955  getLocal(name) {
25956    return this.get(name);
25957  } // Implemented as part of LocalResolver.
25958
25959
25960  notifyImplicitReceiverUse() {
25961    if (this.bindingLevel !== 0) {
25962      // Since the implicit receiver is accessed in an embedded view, we need to
25963      // ensure that we declare a shared context variable for the current template
25964      // in the update variables.
25965      this.map.get(SHARED_CONTEXT_KEY + 0).declare = true;
25966    }
25967  }
25968
25969  nestedScope(level, globals) {
25970    const newScope = new BindingScope(level, this, globals);
25971    if (level > 0) newScope.generateSharedContextVar(0);
25972    return newScope;
25973  }
25974  /**
25975   * Gets or creates a shared context variable and returns its expression. Note that
25976   * this does not mean that the shared variable will be declared. Variables in the
25977   * binding scope will be only declared if they are used.
25978   */
25979
25980
25981  getOrCreateSharedContextVar(retrievalLevel) {
25982    const bindingKey = SHARED_CONTEXT_KEY + retrievalLevel;
25983
25984    if (!this.map.has(bindingKey)) {
25985      this.generateSharedContextVar(retrievalLevel);
25986    } // Shared context variables are always generated as "ReadVarExpr".
25987
25988
25989    return this.map.get(bindingKey).lhs;
25990  }
25991
25992  getSharedContextName(retrievalLevel) {
25993    const sharedCtxObj = this.map.get(SHARED_CONTEXT_KEY + retrievalLevel); // Shared context variables are always generated as "ReadVarExpr".
25994
25995    return sharedCtxObj && sharedCtxObj.declare ? sharedCtxObj.lhs : null;
25996  }
25997
25998  maybeGenerateSharedContextVar(value) {
25999    if (value.priority === 1
26000    /* DeclarationPriority.CONTEXT */
26001    && value.retrievalLevel < this.bindingLevel) {
26002      const sharedCtxObj = this.map.get(SHARED_CONTEXT_KEY + value.retrievalLevel);
26003
26004      if (sharedCtxObj) {
26005        sharedCtxObj.declare = true;
26006      } else {
26007        this.generateSharedContextVar(value.retrievalLevel);
26008      }
26009    }
26010  }
26011
26012  generateSharedContextVar(retrievalLevel) {
26013    const lhs = variable(CONTEXT_NAME + this.freshReferenceName());
26014    this.map.set(SHARED_CONTEXT_KEY + retrievalLevel, {
26015      retrievalLevel: retrievalLevel,
26016      lhs: lhs,
26017      declareLocalCallback: (scope, relativeLevel) => {
26018        // const ctx_r0 = nextContext(2);
26019        return [lhs.set(generateNextContextExpr(relativeLevel)).toConstDecl()];
26020      },
26021      declare: false,
26022      priority: 2
26023      /* DeclarationPriority.SHARED_CONTEXT */
26024
26025    });
26026  }
26027
26028  getComponentProperty(name) {
26029    const componentValue = this.map.get(SHARED_CONTEXT_KEY + 0);
26030    componentValue.declare = true;
26031    this.maybeRestoreView();
26032    return componentValue.lhs.prop(name);
26033  }
26034
26035  maybeRestoreView() {
26036    // View restoration is required for listener instructions inside embedded views, because
26037    // they only run in creation mode and they can have references to the context object.
26038    // If the context object changes in update mode, the reference will be incorrect, because
26039    // it was established during creation.
26040    if (this.isListenerScope()) {
26041      if (!this.parent.restoreViewVariable) {
26042        // parent saves variable to generate a shared `const $s$ = getCurrentView();` instruction
26043        this.parent.restoreViewVariable = variable(this.parent.freshReferenceName());
26044      }
26045
26046      this.restoreViewVariable = this.parent.restoreViewVariable;
26047    }
26048  }
26049
26050  restoreViewStatement() {
26051    if (this.restoreViewVariable) {
26052      const restoreCall = invokeInstruction(null, Identifiers.restoreView, [this.restoreViewVariable]); // Either `const restoredCtx = restoreView($state$);` or `restoreView($state$);`
26053      // depending on whether it is being used.
26054
26055      return this.usesRestoredViewContext ? variable(RESTORED_VIEW_CONTEXT_NAME).set(restoreCall).toConstDecl() : restoreCall.toStmt();
26056    }
26057
26058    return null;
26059  }
26060
26061  viewSnapshotStatements() {
26062    // const $state$ = getCurrentView();
26063    return this.restoreViewVariable ? [this.restoreViewVariable.set(invokeInstruction(null, Identifiers.getCurrentView, [])).toConstDecl()] : [];
26064  }
26065
26066  isListenerScope() {
26067    return this.parent && this.parent.bindingLevel === this.bindingLevel;
26068  }
26069
26070  variableDeclarations() {
26071    let currentContextLevel = 0;
26072    return Array.from(this.map.values()).filter(value => value.declare).sort((a, b) => b.retrievalLevel - a.retrievalLevel || b.priority - a.priority).reduce((stmts, value) => {
26073      const levelDiff = this.bindingLevel - value.retrievalLevel;
26074      const currStmts = value.declareLocalCallback(this, levelDiff - currentContextLevel);
26075      currentContextLevel = levelDiff;
26076      return stmts.concat(currStmts);
26077    }, []);
26078  }
26079
26080  freshReferenceName() {
26081    let current = this; // Find the top scope as it maintains the global reference count
26082
26083    while (current.parent) current = current.parent;
26084
26085    const ref = `${REFERENCE_PREFIX}${current.referenceNameIndex++}`;
26086    return ref;
26087  }
26088
26089  hasRestoreViewVariable() {
26090    return !!this.restoreViewVariable;
26091  }
26092
26093  notifyRestoredViewContextUse() {
26094    this.usesRestoredViewContext = true;
26095  }
26096
26097}
26098/**
26099 * Creates a `CssSelector` given a tag name and a map of attributes
26100 */
26101
26102
26103function createCssSelector(elementName, attributes) {
26104  const cssSelector = new CssSelector();
26105  const elementNameNoNs = splitNsName(elementName)[1];
26106  cssSelector.setElement(elementNameNoNs);
26107  Object.getOwnPropertyNames(attributes).forEach(name => {
26108    const nameNoNs = splitNsName(name)[1];
26109    const value = attributes[name];
26110    cssSelector.addAttribute(nameNoNs, value);
26111
26112    if (name.toLowerCase() === 'class') {
26113      const classes = value.trim().split(/\s+/);
26114      classes.forEach(className => cssSelector.addClassName(className));
26115    }
26116  });
26117  return cssSelector;
26118}
26119/**
26120 * Creates an array of expressions out of an `ngProjectAs` attributes
26121 * which can be added to the instruction parameters.
26122 */
26123
26124
26125function getNgProjectAsLiteral(attribute) {
26126  // Parse the attribute value into a CssSelectorList. Note that we only take the
26127  // first selector, because we don't support multiple selectors in ngProjectAs.
26128  const parsedR3Selector = parseSelectorToR3Selector(attribute.value)[0];
26129  return [literal(5
26130  /* core.AttributeMarker.ProjectAs */
26131  ), asLiteral(parsedR3Selector)];
26132}
26133/**
26134 * Gets the instruction to generate for an interpolated property
26135 * @param interpolation An Interpolation AST
26136 */
26137
26138
26139function getPropertyInterpolationExpression(interpolation) {
26140  switch (getInterpolationArgsLength(interpolation)) {
26141    case 1:
26142      return Identifiers.propertyInterpolate;
26143
26144    case 3:
26145      return Identifiers.propertyInterpolate1;
26146
26147    case 5:
26148      return Identifiers.propertyInterpolate2;
26149
26150    case 7:
26151      return Identifiers.propertyInterpolate3;
26152
26153    case 9:
26154      return Identifiers.propertyInterpolate4;
26155
26156    case 11:
26157      return Identifiers.propertyInterpolate5;
26158
26159    case 13:
26160      return Identifiers.propertyInterpolate6;
26161
26162    case 15:
26163      return Identifiers.propertyInterpolate7;
26164
26165    case 17:
26166      return Identifiers.propertyInterpolate8;
26167
26168    default:
26169      return Identifiers.propertyInterpolateV;
26170  }
26171}
26172/**
26173 * Gets the instruction to generate for an interpolated attribute
26174 * @param interpolation An Interpolation AST
26175 */
26176
26177
26178function getAttributeInterpolationExpression(interpolation) {
26179  switch (getInterpolationArgsLength(interpolation)) {
26180    case 3:
26181      return Identifiers.attributeInterpolate1;
26182
26183    case 5:
26184      return Identifiers.attributeInterpolate2;
26185
26186    case 7:
26187      return Identifiers.attributeInterpolate3;
26188
26189    case 9:
26190      return Identifiers.attributeInterpolate4;
26191
26192    case 11:
26193      return Identifiers.attributeInterpolate5;
26194
26195    case 13:
26196      return Identifiers.attributeInterpolate6;
26197
26198    case 15:
26199      return Identifiers.attributeInterpolate7;
26200
26201    case 17:
26202      return Identifiers.attributeInterpolate8;
26203
26204    default:
26205      return Identifiers.attributeInterpolateV;
26206  }
26207}
26208/**
26209 * Gets the instruction to generate for interpolated text.
26210 * @param interpolation An Interpolation AST
26211 */
26212
26213
26214function getTextInterpolationExpression(interpolation) {
26215  switch (getInterpolationArgsLength(interpolation)) {
26216    case 1:
26217      return Identifiers.textInterpolate;
26218
26219    case 3:
26220      return Identifiers.textInterpolate1;
26221
26222    case 5:
26223      return Identifiers.textInterpolate2;
26224
26225    case 7:
26226      return Identifiers.textInterpolate3;
26227
26228    case 9:
26229      return Identifiers.textInterpolate4;
26230
26231    case 11:
26232      return Identifiers.textInterpolate5;
26233
26234    case 13:
26235      return Identifiers.textInterpolate6;
26236
26237    case 15:
26238      return Identifiers.textInterpolate7;
26239
26240    case 17:
26241      return Identifiers.textInterpolate8;
26242
26243    default:
26244      return Identifiers.textInterpolateV;
26245  }
26246}
26247/**
26248 * Parse a template into render3 `Node`s and additional metadata, with no other dependencies.
26249 *
26250 * @param template text of the template to parse
26251 * @param templateUrl URL to use for source mapping of the parsed template
26252 * @param options options to modify how the template is parsed
26253 */
26254
26255
26256function parseTemplate(template, templateUrl, options = {}) {
26257  const {
26258    interpolationConfig,
26259    preserveWhitespaces,
26260    enableI18nLegacyMessageIdFormat
26261  } = options;
26262  const bindingParser = makeBindingParser(interpolationConfig);
26263  const htmlParser = new HtmlParser();
26264  const parseResult = htmlParser.parse(template, templateUrl, {
26265    leadingTriviaChars: LEADING_TRIVIA_CHARS,
26266    ...options,
26267    tokenizeExpansionForms: true
26268  });
26269
26270  if (!options.alwaysAttemptHtmlToR3AstConversion && parseResult.errors && parseResult.errors.length > 0) {
26271    const parsedTemplate = {
26272      interpolationConfig,
26273      preserveWhitespaces,
26274      errors: parseResult.errors,
26275      nodes: [],
26276      styleUrls: [],
26277      styles: [],
26278      ngContentSelectors: []
26279    };
26280
26281    if (options.collectCommentNodes) {
26282      parsedTemplate.commentNodes = [];
26283    }
26284
26285    return parsedTemplate;
26286  }
26287
26288  let rootNodes = parseResult.rootNodes; // process i18n meta information (scan attributes, generate ids)
26289  // before we run whitespace removal process, because existing i18n
26290  // extraction process (ng extract-i18n) relies on a raw content to generate
26291  // message ids
26292
26293  const i18nMetaVisitor = new I18nMetaVisitor(interpolationConfig,
26294  /* keepI18nAttrs */
26295  !preserveWhitespaces, enableI18nLegacyMessageIdFormat);
26296  const i18nMetaResult = i18nMetaVisitor.visitAllWithErrors(rootNodes);
26297
26298  if (!options.alwaysAttemptHtmlToR3AstConversion && i18nMetaResult.errors && i18nMetaResult.errors.length > 0) {
26299    const parsedTemplate = {
26300      interpolationConfig,
26301      preserveWhitespaces,
26302      errors: i18nMetaResult.errors,
26303      nodes: [],
26304      styleUrls: [],
26305      styles: [],
26306      ngContentSelectors: []
26307    };
26308
26309    if (options.collectCommentNodes) {
26310      parsedTemplate.commentNodes = [];
26311    }
26312
26313    return parsedTemplate;
26314  }
26315
26316  rootNodes = i18nMetaResult.rootNodes;
26317
26318  if (!preserveWhitespaces) {
26319    rootNodes = visitAll(new WhitespaceVisitor(), rootNodes); // run i18n meta visitor again in case whitespaces are removed (because that might affect
26320    // generated i18n message content) and first pass indicated that i18n content is present in a
26321    // template. During this pass i18n IDs generated at the first pass will be preserved, so we can
26322    // mimic existing extraction process (ng extract-i18n)
26323
26324    if (i18nMetaVisitor.hasI18nMeta) {
26325      rootNodes = visitAll(new I18nMetaVisitor(interpolationConfig,
26326      /* keepI18nAttrs */
26327      false), rootNodes);
26328    }
26329  }
26330
26331  const {
26332    nodes,
26333    errors,
26334    styleUrls,
26335    styles,
26336    ngContentSelectors,
26337    commentNodes
26338  } = htmlAstToRender3Ast(rootNodes, bindingParser, {
26339    collectCommentNodes: !!options.collectCommentNodes
26340  });
26341  errors.push(...parseResult.errors, ...i18nMetaResult.errors);
26342  const parsedTemplate = {
26343    interpolationConfig,
26344    preserveWhitespaces,
26345    errors: errors.length > 0 ? errors : null,
26346    nodes,
26347    styleUrls,
26348    styles,
26349    ngContentSelectors
26350  };
26351
26352  if (options.collectCommentNodes) {
26353    parsedTemplate.commentNodes = commentNodes;
26354  }
26355
26356  return parsedTemplate;
26357}
26358
26359const elementRegistry = new DomElementSchemaRegistry();
26360/**
26361 * Construct a `BindingParser` with a default configuration.
26362 */
26363
26364function makeBindingParser(interpolationConfig = DEFAULT_INTERPOLATION_CONFIG) {
26365  return new BindingParser(new Parser$1(new Lexer()), interpolationConfig, elementRegistry, []);
26366}
26367
26368function resolveSanitizationFn(context, isAttribute) {
26369  switch (context) {
26370    case SecurityContext.HTML:
26371      return importExpr(Identifiers.sanitizeHtml);
26372
26373    case SecurityContext.SCRIPT:
26374      return importExpr(Identifiers.sanitizeScript);
26375
26376    case SecurityContext.STYLE:
26377      // the compiler does not fill in an instruction for [style.prop?] binding
26378      // values because the style algorithm knows internally what props are subject
26379      // to sanitization (only [attr.style] values are explicitly sanitized)
26380      return isAttribute ? importExpr(Identifiers.sanitizeStyle) : null;
26381
26382    case SecurityContext.URL:
26383      return importExpr(Identifiers.sanitizeUrl);
26384
26385    case SecurityContext.RESOURCE_URL:
26386      return importExpr(Identifiers.sanitizeResourceUrl);
26387
26388    default:
26389      return null;
26390  }
26391}
26392
26393function trustedConstAttribute(tagName, attr) {
26394  const value = asLiteral(attr.value);
26395
26396  if (isTrustedTypesSink(tagName, attr.name)) {
26397    switch (elementRegistry.securityContext(tagName, attr.name,
26398    /* isAttribute */
26399    true)) {
26400      case SecurityContext.HTML:
26401        return taggedTemplate(importExpr(Identifiers.trustConstantHtml), new TemplateLiteral([new TemplateLiteralElement(attr.value)], []), undefined, attr.valueSpan);
26402      // NB: no SecurityContext.SCRIPT here, as the corresponding tags are stripped by the compiler.
26403
26404      case SecurityContext.RESOURCE_URL:
26405        return taggedTemplate(importExpr(Identifiers.trustConstantResourceUrl), new TemplateLiteral([new TemplateLiteralElement(attr.value)], []), undefined, attr.valueSpan);
26406
26407      default:
26408        return value;
26409    }
26410  } else {
26411    return value;
26412  }
26413}
26414
26415function isSingleElementTemplate(children) {
26416  return children.length === 1 && children[0] instanceof Element$1;
26417}
26418
26419function isTextNode(node) {
26420  return node instanceof Text$3 || node instanceof BoundText || node instanceof Icu$1;
26421}
26422
26423function isIframeElement(tagName) {
26424  return tagName.toLowerCase() === 'iframe';
26425}
26426
26427function hasTextChildrenOnly(children) {
26428  return children.every(isTextNode);
26429}
26430
26431function getBindingFunctionParams(deferredParams, name, eagerParams) {
26432  return () => {
26433    const value = deferredParams();
26434    const fnParams = Array.isArray(value) ? value : [value];
26435
26436    if (eagerParams) {
26437      fnParams.push(...eagerParams);
26438    }
26439
26440    if (name) {
26441      // We want the property name to always be the first function parameter.
26442      fnParams.unshift(literal(name));
26443    }
26444
26445    return fnParams;
26446  };
26447}
26448/** Name of the global variable that is used to determine if we use Closure translations or not */
26449
26450
26451const NG_I18N_CLOSURE_MODE = 'ngI18nClosureMode';
26452/**
26453 * Generate statements that define a given translation message.
26454 *
26455 * ```
26456 * var I18N_1;
26457 * if (typeof ngI18nClosureMode !== undefined && ngI18nClosureMode) {
26458 *     var MSG_EXTERNAL_XXX = goog.getMsg(
26459 *          "Some message with {$interpolation}!",
26460 *          { "interpolation": "\uFFFD0\uFFFD" }
26461 *     );
26462 *     I18N_1 = MSG_EXTERNAL_XXX;
26463 * }
26464 * else {
26465 *     I18N_1 = $localize`Some message with ${'\uFFFD0\uFFFD'}!`;
26466 * }
26467 * ```
26468 *
26469 * @param message The original i18n AST message node
26470 * @param variable The variable that will be assigned the translation, e.g. `I18N_1`.
26471 * @param closureVar The variable for Closure `goog.getMsg` calls, e.g. `MSG_EXTERNAL_XXX`.
26472 * @param params Object mapping placeholder names to their values (e.g.
26473 * `{ "interpolation": "\uFFFD0\uFFFD" }`).
26474 * @param transformFn Optional transformation function that will be applied to the translation (e.g.
26475 * post-processing).
26476 * @returns An array of statements that defined a given translation.
26477 */
26478
26479function getTranslationDeclStmts(message, variable, closureVar, params = {}, transformFn) {
26480  const statements = [declareI18nVariable(variable), ifStmt(createClosureModeGuard(), createGoogleGetMsgStatements(variable, message, closureVar, params), createLocalizeStatements(variable, message, formatI18nPlaceholderNamesInMap(params,
26481  /* useCamelCase */
26482  false)))];
26483
26484  if (transformFn) {
26485    statements.push(new ExpressionStatement(variable.set(transformFn(variable))));
26486  }
26487
26488  return statements;
26489}
26490/**
26491 * Create the expression that will be used to guard the closure mode block
26492 * It is equivalent to:
26493 *
26494 * ```
26495 * typeof ngI18nClosureMode !== undefined && ngI18nClosureMode
26496 * ```
26497 */
26498
26499
26500function createClosureModeGuard() {
26501  return typeofExpr(variable(NG_I18N_CLOSURE_MODE)).notIdentical(literal('undefined', STRING_TYPE)).and(variable(NG_I18N_CLOSURE_MODE));
26502}
26503
26504function flatten(list) {
26505  return list.reduce((flat, item) => {
26506    const flatItem = Array.isArray(item) ? flatten(item) : item;
26507    return flat.concat(flatItem);
26508  }, []);
26509}
26510/**
26511 * @license
26512 * Copyright Google LLC All Rights Reserved.
26513 *
26514 * Use of this source code is governed by an MIT-style license that can be
26515 * found in the LICENSE file at https://angular.io/license
26516 */
26517// This regex matches any binding names that contain the "attr." prefix, e.g. "attr.required"
26518// If there is a match, the first matching group will contain the attribute name to bind.
26519
26520
26521const ATTR_REGEX = /attr\.([^\]]+)/;
26522const COMPONENT_VARIABLE = '%COMP%';
26523const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`;
26524const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`;
26525
26526function baseDirectiveFields(meta, constantPool, bindingParser) {
26527  const definitionMap = new DefinitionMap();
26528  const selectors = parseSelectorToR3Selector(meta.selector); // e.g. `type: MyDirective`
26529
26530  definitionMap.set('type', meta.internalType); // e.g. `selectors: [['', 'someDir', '']]`
26531
26532  if (selectors.length > 0) {
26533    definitionMap.set('selectors', asLiteral(selectors));
26534  }
26535
26536  if (meta.queries.length > 0) {
26537    // e.g. `contentQueries: (rf, ctx, dirIndex) => { ... }
26538    definitionMap.set('contentQueries', createContentQueriesFunction(meta.queries, constantPool, meta.name));
26539  }
26540
26541  if (meta.viewQueries.length) {
26542    definitionMap.set('viewQuery', createViewQueriesFunction(meta.viewQueries, constantPool, meta.name));
26543  } // e.g. `hostBindings: (rf, ctx) => { ... }
26544
26545
26546  definitionMap.set('hostBindings', createHostBindingsFunction(meta.host, meta.typeSourceSpan, bindingParser, constantPool, meta.selector || '', meta.name, definitionMap)); // e.g 'inputs: {a: 'a'}`
26547
26548  definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true)); // e.g 'outputs: {a: 'a'}`
26549
26550  definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));
26551
26552  if (meta.exportAs !== null) {
26553    definitionMap.set('exportAs', literalArr(meta.exportAs.map(e => literal(e))));
26554  }
26555
26556  if (meta.isStandalone) {
26557    definitionMap.set('standalone', literal(true));
26558  }
26559
26560  return definitionMap;
26561}
26562/**
26563 * Add features to the definition map.
26564 */
26565
26566
26567function addFeatures(definitionMap, meta) {
26568  // e.g. `features: [NgOnChangesFeature]`
26569  const features = [];
26570  const providers = meta.providers;
26571  const viewProviders = meta.viewProviders;
26572
26573  if (providers || viewProviders) {
26574    const args = [providers || new LiteralArrayExpr([])];
26575
26576    if (viewProviders) {
26577      args.push(viewProviders);
26578    }
26579
26580    features.push(importExpr(Identifiers.ProvidersFeature).callFn(args));
26581  }
26582
26583  if (meta.usesInheritance) {
26584    features.push(importExpr(Identifiers.InheritDefinitionFeature));
26585  }
26586
26587  if (meta.fullInheritance) {
26588    features.push(importExpr(Identifiers.CopyDefinitionFeature));
26589  }
26590
26591  if (meta.lifecycle.usesOnChanges) {
26592    features.push(importExpr(Identifiers.NgOnChangesFeature));
26593  } // TODO: better way of differentiating component vs directive metadata.
26594
26595
26596  if (meta.hasOwnProperty('template') && meta.isStandalone) {
26597    features.push(importExpr(Identifiers.StandaloneFeature));
26598  }
26599
26600  if (features.length) {
26601    definitionMap.set('features', literalArr(features));
26602  }
26603}
26604/**
26605 * Compile a directive for the render3 runtime as defined by the `R3DirectiveMetadata`.
26606 */
26607
26608
26609function compileDirectiveFromMetadata(meta, constantPool, bindingParser) {
26610  const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
26611  addFeatures(definitionMap, meta);
26612  const expression = importExpr(Identifiers.defineDirective).callFn([definitionMap.toLiteralMap()], undefined, true);
26613  const type = createDirectiveType(meta);
26614  return {
26615    expression,
26616    type,
26617    statements: []
26618  };
26619}
26620/**
26621 * Compile a component for the render3 runtime as defined by the `R3ComponentMetadata`.
26622 */
26623
26624
26625function compileComponentFromMetadata(meta, constantPool, bindingParser) {
26626  const definitionMap = baseDirectiveFields(meta, constantPool, bindingParser);
26627  addFeatures(definitionMap, meta);
26628  const selector = meta.selector && CssSelector.parse(meta.selector);
26629  const firstSelector = selector && selector[0]; // e.g. `attr: ["class", ".my.app"]`
26630  // This is optional an only included if the first selector of a component specifies attributes.
26631
26632  if (firstSelector) {
26633    const selectorAttributes = firstSelector.getAttrs();
26634
26635    if (selectorAttributes.length) {
26636      definitionMap.set('attrs', constantPool.getConstLiteral(literalArr(selectorAttributes.map(value => value != null ? literal(value) : literal(undefined))),
26637      /* forceShared */
26638      true));
26639    }
26640  } // e.g. `template: function MyComponent_Template(_ctx, _cm) {...}`
26641
26642
26643  const templateTypeName = meta.name;
26644  const templateName = templateTypeName ? `${templateTypeName}_Template` : null;
26645  const changeDetection = meta.changeDetection;
26646  const template = meta.template;
26647  const templateBuilder = new TemplateDefinitionBuilder(constantPool, BindingScope.createRootScope(), 0, templateTypeName, null, null, templateName, Identifiers.namespaceHTML, meta.relativeContextFilePath, meta.i18nUseExternalIds);
26648  const templateFunctionExpression = templateBuilder.buildTemplateFunction(template.nodes, []); // We need to provide this so that dynamically generated components know what
26649  // projected content blocks to pass through to the component when it is instantiated.
26650
26651  const ngContentSelectors = templateBuilder.getNgContentSelectors();
26652
26653  if (ngContentSelectors) {
26654    definitionMap.set('ngContentSelectors', ngContentSelectors);
26655  } // e.g. `decls: 2`
26656
26657
26658  definitionMap.set('decls', literal(templateBuilder.getConstCount())); // e.g. `vars: 2`
26659
26660  definitionMap.set('vars', literal(templateBuilder.getVarCount())); // Generate `consts` section of ComponentDef:
26661  // - either as an array:
26662  //   `consts: [['one', 'two'], ['three', 'four']]`
26663  // - or as a factory function in case additional statements are present (to support i18n):
26664  //   `consts: function() { var i18n_0; if (ngI18nClosureMode) {...} else {...} return [i18n_0]; }`
26665
26666  const {
26667    constExpressions,
26668    prepareStatements
26669  } = templateBuilder.getConsts();
26670
26671  if (constExpressions.length > 0) {
26672    let constsExpr = literalArr(constExpressions); // Prepare statements are present - turn `consts` into a function.
26673
26674    if (prepareStatements.length > 0) {
26675      constsExpr = fn([], [...prepareStatements, new ReturnStatement(constsExpr)]);
26676    }
26677
26678    definitionMap.set('consts', constsExpr);
26679  }
26680
26681  definitionMap.set('template', templateFunctionExpression);
26682
26683  if (meta.declarations.length > 0) {
26684    definitionMap.set('dependencies', compileDeclarationList(literalArr(meta.declarations.map(decl => decl.type)), meta.declarationListEmitMode));
26685  }
26686
26687  if (meta.encapsulation === null) {
26688    meta.encapsulation = ViewEncapsulation.Emulated;
26689  } // e.g. `styles: [str1, str2]`
26690
26691
26692  if (meta.styles && meta.styles.length) {
26693    const styleValues = meta.encapsulation == ViewEncapsulation.Emulated ? compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) : meta.styles;
26694    const styleNodes = styleValues.reduce((result, style) => {
26695      if (style.trim().length > 0) {
26696        result.push(constantPool.getConstLiteral(literal(style)));
26697      }
26698
26699      return result;
26700    }, []);
26701
26702    if (styleNodes.length > 0) {
26703      definitionMap.set('styles', literalArr(styleNodes));
26704    }
26705  } else if (meta.encapsulation === ViewEncapsulation.Emulated) {
26706    // If there is no style, don't generate css selectors on elements
26707    meta.encapsulation = ViewEncapsulation.None;
26708  } // Only set view encapsulation if it's not the default value
26709
26710
26711  if (meta.encapsulation !== ViewEncapsulation.Emulated) {
26712    definitionMap.set('encapsulation', literal(meta.encapsulation));
26713  } // e.g. `animation: [trigger('123', [])]`
26714
26715
26716  if (meta.animations !== null) {
26717    definitionMap.set('data', literalMap([{
26718      key: 'animation',
26719      value: meta.animations,
26720      quoted: false
26721    }]));
26722  } // Only set the change detection flag if it's defined and it's not the default.
26723
26724
26725  if (changeDetection != null && changeDetection !== ChangeDetectionStrategy.Default) {
26726    definitionMap.set('changeDetection', literal(changeDetection));
26727  }
26728
26729  const expression = importExpr(Identifiers.defineComponent).callFn([definitionMap.toLiteralMap()], undefined, true);
26730  const type = createComponentType(meta);
26731  return {
26732    expression,
26733    type,
26734    statements: []
26735  };
26736}
26737/**
26738 * Creates the type specification from the component meta. This type is inserted into .d.ts files
26739 * to be consumed by upstream compilations.
26740 */
26741
26742
26743function createComponentType(meta) {
26744  const typeParams = createBaseDirectiveTypeParams(meta);
26745  typeParams.push(stringArrayAsType(meta.template.ngContentSelectors));
26746  typeParams.push(expressionType(literal(meta.isStandalone)));
26747  return expressionType(importExpr(Identifiers.ComponentDeclaration, typeParams));
26748}
26749/**
26750 * Compiles the array literal of declarations into an expression according to the provided emit
26751 * mode.
26752 */
26753
26754
26755function compileDeclarationList(list, mode) {
26756  switch (mode) {
26757    case 0
26758    /* DeclarationListEmitMode.Direct */
26759    :
26760      // directives: [MyDir],
26761      return list;
26762
26763    case 1
26764    /* DeclarationListEmitMode.Closure */
26765    :
26766      // directives: function () { return [MyDir]; }
26767      return fn([], [new ReturnStatement(list)]);
26768
26769    case 2
26770    /* DeclarationListEmitMode.ClosureResolved */
26771    :
26772      // directives: function () { return [MyDir].map(ng.resolveForwardRef); }
26773      const resolvedList = list.prop('map').callFn([importExpr(Identifiers.resolveForwardRef)]);
26774      return fn([], [new ReturnStatement(resolvedList)]);
26775  }
26776}
26777
26778function prepareQueryParams(query, constantPool) {
26779  const parameters = [getQueryPredicate(query, constantPool), literal(toQueryFlags(query))];
26780
26781  if (query.read) {
26782    parameters.push(query.read);
26783  }
26784
26785  return parameters;
26786}
26787/**
26788 * Translates query flags into `TQueryFlags` type in packages/core/src/render3/interfaces/query.ts
26789 * @param query
26790 */
26791
26792
26793function toQueryFlags(query) {
26794  return (query.descendants ? 1
26795  /* QueryFlags.descendants */
26796  : 0
26797  /* QueryFlags.none */
26798  ) | (query.static ? 2
26799  /* QueryFlags.isStatic */
26800  : 0
26801  /* QueryFlags.none */
26802  ) | (query.emitDistinctChangesOnly ? 4
26803  /* QueryFlags.emitDistinctChangesOnly */
26804  : 0
26805  /* QueryFlags.none */
26806  );
26807}
26808
26809function convertAttributesToExpressions(attributes) {
26810  const values = [];
26811
26812  for (let key of Object.getOwnPropertyNames(attributes)) {
26813    const value = attributes[key];
26814    values.push(literal(key), value);
26815  }
26816
26817  return values;
26818} // Define and update any content queries
26819
26820
26821function createContentQueriesFunction(queries, constantPool, name) {
26822  const createStatements = [];
26823  const updateStatements = [];
26824  const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
26825
26826  for (const query of queries) {
26827    // creation, e.g. r3.contentQuery(dirIndex, somePredicate, true, null);
26828    createStatements.push(importExpr(Identifiers.contentQuery).callFn([variable('dirIndex'), ...prepareQueryParams(query, constantPool)]).toStmt()); // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
26829
26830    const temporary = tempAllocator();
26831    const getQueryList = importExpr(Identifiers.loadQuery).callFn([]);
26832    const refresh = importExpr(Identifiers.queryRefresh).callFn([temporary.set(getQueryList)]);
26833    const updateDirective = variable(CONTEXT_NAME).prop(query.propertyName).set(query.first ? temporary.prop('first') : temporary);
26834    updateStatements.push(refresh.and(updateDirective).toStmt());
26835  }
26836
26837  const contentQueriesFnName = name ? `${name}_ContentQueries` : null;
26838  return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null), new FnParam('dirIndex', null)], [renderFlagCheckIfStmt(1
26839  /* core.RenderFlags.Create */
26840  , createStatements), renderFlagCheckIfStmt(2
26841  /* core.RenderFlags.Update */
26842  , updateStatements)], INFERRED_TYPE, null, contentQueriesFnName);
26843}
26844
26845function stringAsType(str) {
26846  return expressionType(literal(str));
26847}
26848
26849function stringMapAsType(map) {
26850  const mapValues = Object.keys(map).map(key => {
26851    const value = Array.isArray(map[key]) ? map[key][0] : map[key];
26852    return {
26853      key,
26854      value: literal(value),
26855      quoted: true
26856    };
26857  });
26858  return expressionType(literalMap(mapValues));
26859}
26860
26861function stringArrayAsType(arr) {
26862  return arr.length > 0 ? expressionType(literalArr(arr.map(value => literal(value)))) : NONE_TYPE;
26863}
26864
26865function createBaseDirectiveTypeParams(meta) {
26866  // On the type side, remove newlines from the selector as it will need to fit into a TypeScript
26867  // string literal, which must be on one line.
26868  const selectorForType = meta.selector !== null ? meta.selector.replace(/\n/g, '') : null;
26869  return [typeWithParameters(meta.type.type, meta.typeArgumentCount), selectorForType !== null ? stringAsType(selectorForType) : NONE_TYPE, meta.exportAs !== null ? stringArrayAsType(meta.exportAs) : NONE_TYPE, stringMapAsType(meta.inputs), stringMapAsType(meta.outputs), stringArrayAsType(meta.queries.map(q => q.propertyName))];
26870}
26871/**
26872 * Creates the type specification from the directive meta. This type is inserted into .d.ts files
26873 * to be consumed by upstream compilations.
26874 */
26875
26876
26877function createDirectiveType(meta) {
26878  const typeParams = createBaseDirectiveTypeParams(meta); // Directives have no NgContentSelectors slot, but instead express a `never` type
26879  // so that future fields align.
26880
26881  typeParams.push(NONE_TYPE);
26882  typeParams.push(expressionType(literal(meta.isStandalone)));
26883  return expressionType(importExpr(Identifiers.DirectiveDeclaration, typeParams));
26884} // Define and update any view queries
26885
26886
26887function createViewQueriesFunction(viewQueries, constantPool, name) {
26888  const createStatements = [];
26889  const updateStatements = [];
26890  const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
26891  viewQueries.forEach(query => {
26892    // creation, e.g. r3.viewQuery(somePredicate, true);
26893    const queryDefinition = importExpr(Identifiers.viewQuery).callFn(prepareQueryParams(query, constantPool));
26894    createStatements.push(queryDefinition.toStmt()); // update, e.g. (r3.queryRefresh(tmp = r3.loadQuery()) && (ctx.someDir = tmp));
26895
26896    const temporary = tempAllocator();
26897    const getQueryList = importExpr(Identifiers.loadQuery).callFn([]);
26898    const refresh = importExpr(Identifiers.queryRefresh).callFn([temporary.set(getQueryList)]);
26899    const updateDirective = variable(CONTEXT_NAME).prop(query.propertyName).set(query.first ? temporary.prop('first') : temporary);
26900    updateStatements.push(refresh.and(updateDirective).toStmt());
26901  });
26902  const viewQueryFnName = name ? `${name}_Query` : null;
26903  return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], [renderFlagCheckIfStmt(1
26904  /* core.RenderFlags.Create */
26905  , createStatements), renderFlagCheckIfStmt(2
26906  /* core.RenderFlags.Update */
26907  , updateStatements)], INFERRED_TYPE, null, viewQueryFnName);
26908} // Return a host binding function or null if one is not necessary.
26909
26910
26911function createHostBindingsFunction(hostBindingsMetadata, typeSourceSpan, bindingParser, constantPool, selector, name, definitionMap) {
26912  const bindingContext = variable(CONTEXT_NAME);
26913  const styleBuilder = new StylingBuilder(bindingContext);
26914  const {
26915    styleAttr,
26916    classAttr
26917  } = hostBindingsMetadata.specialAttributes;
26918
26919  if (styleAttr !== undefined) {
26920    styleBuilder.registerStyleAttr(styleAttr);
26921  }
26922
26923  if (classAttr !== undefined) {
26924    styleBuilder.registerClassAttr(classAttr);
26925  }
26926
26927  const createInstructions = [];
26928  const updateInstructions = [];
26929  const updateVariables = [];
26930  const hostBindingSourceSpan = typeSourceSpan; // Calculate host event bindings
26931
26932  const eventBindings = bindingParser.createDirectiveHostEventAsts(hostBindingsMetadata.listeners, hostBindingSourceSpan);
26933
26934  if (eventBindings && eventBindings.length) {
26935    createInstructions.push(...createHostListeners(eventBindings, name));
26936  } // Calculate the host property bindings
26937
26938
26939  const bindings = bindingParser.createBoundHostProperties(hostBindingsMetadata.properties, hostBindingSourceSpan);
26940  const allOtherBindings = []; // We need to calculate the total amount of binding slots required by
26941  // all the instructions together before any value conversions happen.
26942  // Value conversions may require additional slots for interpolation and
26943  // bindings with pipes. These calculates happen after this block.
26944
26945  let totalHostVarsCount = 0;
26946  bindings && bindings.forEach(binding => {
26947    const stylingInputWasSet = styleBuilder.registerInputBasedOnName(binding.name, binding.expression, hostBindingSourceSpan);
26948
26949    if (stylingInputWasSet) {
26950      totalHostVarsCount += MIN_STYLING_BINDING_SLOTS_REQUIRED;
26951    } else {
26952      allOtherBindings.push(binding);
26953      totalHostVarsCount++;
26954    }
26955  });
26956  let valueConverter;
26957
26958  const getValueConverter = () => {
26959    if (!valueConverter) {
26960      const hostVarsCountFn = numSlots => {
26961        const originalVarsCount = totalHostVarsCount;
26962        totalHostVarsCount += numSlots;
26963        return originalVarsCount;
26964      };
26965
26966      valueConverter = new ValueConverter(constantPool, () => error('Unexpected node'), // new nodes are illegal here
26967      hostVarsCountFn, () => error('Unexpected pipe')); // pipes are illegal here
26968    }
26969
26970    return valueConverter;
26971  };
26972
26973  const propertyBindings = [];
26974  const attributeBindings = [];
26975  const syntheticHostBindings = [];
26976
26977  for (const binding of allOtherBindings) {
26978    // resolve literal arrays and literal objects
26979    const value = binding.expression.visit(getValueConverter());
26980    const bindingExpr = bindingFn(bindingContext, value);
26981    const {
26982      bindingName,
26983      instruction,
26984      isAttribute
26985    } = getBindingNameAndInstruction(binding);
26986    const securityContexts = bindingParser.calcPossibleSecurityContexts(selector, bindingName, isAttribute).filter(context => context !== SecurityContext.NONE);
26987    let sanitizerFn = null;
26988
26989    if (securityContexts.length) {
26990      if (securityContexts.length === 2 && securityContexts.indexOf(SecurityContext.URL) > -1 && securityContexts.indexOf(SecurityContext.RESOURCE_URL) > -1) {
26991        // Special case for some URL attributes (such as "src" and "href") that may be a part
26992        // of different security contexts. In this case we use special sanitization function and
26993        // select the actual sanitizer at runtime based on a tag name that is provided while
26994        // invoking sanitization function.
26995        sanitizerFn = importExpr(Identifiers.sanitizeUrlOrResourceUrl);
26996      } else {
26997        sanitizerFn = resolveSanitizationFn(securityContexts[0], isAttribute);
26998      }
26999    }
27000
27001    const instructionParams = [literal(bindingName), bindingExpr.currValExpr];
27002
27003    if (sanitizerFn) {
27004      instructionParams.push(sanitizerFn);
27005    } else {
27006      // If there was no sanitization function found based on the security context
27007      // of an attribute/property binding - check whether this attribute/property is
27008      // one of the security-sensitive <iframe> attributes.
27009      // Note: for host bindings defined on a directive, we do not try to find all
27010      // possible places where it can be matched, so we can not determine whether
27011      // the host element is an <iframe>. In this case, if an attribute/binding
27012      // name is in the `IFRAME_SECURITY_SENSITIVE_ATTRS` set - append a validation
27013      // function, which would be invoked at runtime and would have access to the
27014      // underlying DOM element, check if it's an <iframe> and if so - runs extra checks.
27015      if (isIframeSecuritySensitiveAttr(bindingName)) {
27016        instructionParams.push(importExpr(Identifiers.validateIframeAttribute));
27017      }
27018    }
27019
27020    updateVariables.push(...bindingExpr.stmts);
27021
27022    if (instruction === Identifiers.hostProperty) {
27023      propertyBindings.push(instructionParams);
27024    } else if (instruction === Identifiers.attribute) {
27025      attributeBindings.push(instructionParams);
27026    } else if (instruction === Identifiers.syntheticHostProperty) {
27027      syntheticHostBindings.push(instructionParams);
27028    } else {
27029      updateInstructions.push({
27030        reference: instruction,
27031        paramsOrFn: instructionParams,
27032        span: null
27033      });
27034    }
27035  }
27036
27037  for (const bindingParams of propertyBindings) {
27038    updateInstructions.push({
27039      reference: Identifiers.hostProperty,
27040      paramsOrFn: bindingParams,
27041      span: null
27042    });
27043  }
27044
27045  for (const bindingParams of attributeBindings) {
27046    updateInstructions.push({
27047      reference: Identifiers.attribute,
27048      paramsOrFn: bindingParams,
27049      span: null
27050    });
27051  }
27052
27053  for (const bindingParams of syntheticHostBindings) {
27054    updateInstructions.push({
27055      reference: Identifiers.syntheticHostProperty,
27056      paramsOrFn: bindingParams,
27057      span: null
27058    });
27059  } // since we're dealing with directives/components and both have hostBinding
27060  // functions, we need to generate a special hostAttrs instruction that deals
27061  // with both the assignment of styling as well as static attributes to the host
27062  // element. The instruction below will instruct all initial styling (styling
27063  // that is inside of a host binding within a directive/component) to be attached
27064  // to the host element alongside any of the provided host attributes that were
27065  // collected earlier.
27066
27067
27068  const hostAttrs = convertAttributesToExpressions(hostBindingsMetadata.attributes);
27069  styleBuilder.assignHostAttrs(hostAttrs, definitionMap);
27070
27071  if (styleBuilder.hasBindings) {
27072    // finally each binding that was registered in the statement above will need to be added to
27073    // the update block of a component/directive templateFn/hostBindingsFn so that the bindings
27074    // are evaluated and updated for the element.
27075    styleBuilder.buildUpdateLevelInstructions(getValueConverter()).forEac
27075h(instruction => {
27076      for (const call of instruction.calls) {
27077        // we subtract a value of `1` here because the binding slot was already allocated
27078        // at the top of this method when all the input bindings were counted.
27079        totalHostVarsCount += Math.max(call.allocateBindingSlots - MIN_STYLING_BINDING_SLOTS_REQUIRED, 0);
27080        updateInstructions.push({
27081          reference: instruction.reference,
27082          paramsOrFn: convertStylingCall(call, bindingContext, bindingFn),
27083          span: null
27084        });
27085      }
27086    });
27087  }
27088
27089  if (totalHostVarsCount) {
27090    definitionMap.set('hostVars', literal(totalHostVarsCount));
27091  }
27092
27093  if (createInstructions.length > 0 || updateInstructions.length > 0) {
27094    const hostBindingsFnName = name ? `${name}_HostBindings` : null;
27095    const statements = [];
27096
27097    if (createInstructions.length > 0) {
27098      statements.push(renderFlagCheckIfStmt(1
27099      /* core.RenderFlags.Create */
27100      , getInstructionStatements(createInstructions)));
27101    }
27102
27103    if (updateInstructions.length > 0) {
27104      statements.push(renderFlagCheckIfStmt(2
27105      /* core.RenderFlags.Update */
27106      , updateVariables.concat(getInstructionStatements(updateInstructions))));
27107    }
27108
27109    return fn([new FnParam(RENDER_FLAGS, NUMBER_TYPE), new FnParam(CONTEXT_NAME, null)], statements, INFERRED_TYPE, null, hostBindingsFnName);
27110  }
27111
27112  return null;
27113}
27114
27115function bindingFn(implicit, value) {
27116  return convertPropertyBinding(null, implicit, value, 'b');
27117}
27118
27119function convertStylingCall(call, bindingContext, bindingFn) {
27120  return call.params(value => bindingFn(bindingContext, value).currValExpr);
27121}
27122
27123function getBindingNameAndInstruction(binding) {
27124  let bindingName = binding.name;
27125  let instruction; // Check to see if this is an attr binding or a property binding
27126
27127  const attrMatches = bindingName.match(ATTR_REGEX);
27128
27129  if (attrMatches) {
27130    bindingName = attrMatches[1];
27131    instruction = Identifiers.attribute;
27132  } else {
27133    if (binding.isAnimation) {
27134      bindingName = prepareSyntheticPropertyName(bindingName); // host bindings that have a synthetic property (e.g. @foo) should always be rendered
27135      // in the context of the component and not the parent. Therefore there is a special
27136      // compatibility instruction available for this purpose.
27137
27138      instruction = Identifiers.syntheticHostProperty;
27139    } else {
27140      instruction = Identifiers.hostProperty;
27141    }
27142  }
27143
27144  return {
27145    bindingName,
27146    instruction,
27147    isAttribute: !!attrMatches
27148  };
27149}
27150
27151function createHostListeners(eventBindings, name) {
27152  const listenerParams = [];
27153  const syntheticListenerParams = [];
27154  const instructions = [];
27155
27156  for (const binding of eventBindings) {
27157    let bindingName = binding.name && sanitizeIdentifier(binding.name);
27158    const bindingFnName = binding.type === 1
27159    /* ParsedEventType.Animation */
27160    ? prepareSyntheticListenerFunctionName(bindingName, binding.targetOrPhase) : bindingName;
27161    const handlerName = name && bindingName ? `${name}_${bindingFnName}_HostBindingHandler` : null;
27162    const params = prepareEventListenerParameters(BoundEvent.fromParsedEvent(binding), handlerName);
27163
27164    if (binding.type == 1
27165    /* ParsedEventType.Animation */
27166    ) {
27167      syntheticListenerParams.push(params);
27168    } else {
27169      listenerParams.push(params);
27170    }
27171  }
27172
27173  for (const params of syntheticListenerParams) {
27174    instructions.push({
27175      reference: Identifiers.syntheticHostListener,
27176      paramsOrFn: params,
27177      span: null
27178    });
27179  }
27180
27181  for (const params of listenerParams) {
27182    instructions.push({
27183      reference: Identifiers.listener,
27184      paramsOrFn: params,
27185      span: null
27186    });
27187  }
27188
27189  return instructions;
27190}
27191
27192const HOST_REG_EXP = /^(?:\[([^\]]+)\])|(?:\(([^\)]+)\))$/;
27193
27194function parseHostBindings(host) {
27195  const attributes = {};
27196  const listeners = {};
27197  const properties = {};
27198  const specialAttributes = {};
27199
27200  for (const key of Object.keys(host)) {
27201    const value = host[key];
27202    const matches = key.match(HOST_REG_EXP);
27203
27204    if (matches === null) {
27205      switch (key) {
27206        case 'class':
27207          if (typeof value !== 'string') {
27208            // TODO(alxhub): make this a diagnostic.
27209            throw new Error(`Class binding must be string`);
27210          }
27211
27212          specialAttributes.classAttr = value;
27213          break;
27214
27215        case 'style':
27216          if (typeof value !== 'string') {
27217            // TODO(alxhub): make this a diagnostic.
27218            throw new Error(`Style binding must be string`);
27219          }
27220
27221          specialAttributes.styleAttr = value;
27222          break;
27223
27224        default:
27225          if (typeof value === 'string') {
27226            attributes[key] = literal(value);
27227          } else {
27228            attributes[key] = value;
27229          }
27230
27231      }
27232    } else if (matches[1
27233    /* HostBindingGroup.Binding */
27234    ] != null) {
27235      if (typeof value !== 'string') {
27236        // TODO(alxhub): make this a diagnostic.
27237        throw new Error(`Property binding must be string`);
27238      } // synthetic properties (the ones that have a `@` as a prefix)
27239      // are still treated the same as regular properties. Therefore
27240      // there is no point in storing them in a separate map.
27241
27242
27243      properties[matches[1
27244      /* HostBindingGroup.Binding */
27245      ]] = value;
27246    } else if (matches[2
27247    /* HostBindingGroup.Event */
27248    ] != null) {
27249      if (typeof value !== 'string') {
27250        // TODO(alxhub): make this a diagnostic.
27251        throw new Error(`Event binding must be string`);
27252      }
27253
27254      listeners[matches[2
27255      /* HostBindingGroup.Event */
27256      ]] = value;
27257    }
27258  }
27259
27260  return {
27261    attributes,
27262    listeners,
27263    properties,
27264    specialAttributes
27265  };
27266}
27267/**
27268 * Verifies host bindings and returns the list of errors (if any). Empty array indicates that a
27269 * given set of host bindings has no errors.
27270 *
27271 * @param bindings set of host bindings to verify.
27272 * @param sourceSpan source span where host bindings were defined.
27273 * @returns array of errors associated with a given set of host bindings.
27274 */
27275
27276
27277function verifyHostBindings(bindings, sourceSpan) {
27278  // TODO: abstract out host bindings verification logic and use it instead of
27279  // creating events and properties ASTs to detect errors (FW-996)
27280  const bindingParser = makeBindingParser();
27281  bindingParser.createDirectiveHostEventAsts(bindings.listeners, sourceSpan);
27282  bindingParser.createBoundHostProperties(bindings.properties, sourceSpan);
27283  return bindingParser.errors;
27284}
27285
27286function compileStyles(styles, selector, hostSelector) {
27287  const shadowCss = new ShadowCss();
27288  return styles.map(style => {
27289    return shadowCss.shimCssText(style, selector, hostSelector);
27290  });
27291}
27292/**
27293 * @license
27294 * Copyright Google LLC All Rights Reserved.
27295 *
27296 * Use of this source code is governed by an MIT-style license that can be
27297 * found in the LICENSE file at https://angular.io/license
27298 */
27299
27300/**
27301 * An interface for retrieving documents by URL that the compiler uses to
27302 * load templates.
27303 *
27304 * This is an abstract class, rather than an interface, so that it can be used
27305 * as injection token.
27306 */
27307
27308
27309class ResourceLoader {}
27310/**
27311 * @license
27312 * Copyright Google LLC All Rights Reserved.
27313 *
27314 * Use of this source code is governed by an MIT-style license that can be
27315 * found in the LICENSE file at https://angular.io/license
27316 */
27317
27318
27319class CompilerFacadeImpl {
27320  constructor(jitEvaluator = new JitEvaluator()) {
27321    this.jitEvaluator = jitEvaluator;
27322    this.FactoryTarget = FactoryTarget$1;
27323    this.ResourceLoader = ResourceLoader;
27324    this.elementSchemaRegistry = new DomElementSchemaRegistry();
27325  }
27326
27327  compilePipe(angularCoreEnv, sourceMapUrl, facade) {
27328    const metadata = {
27329      name: facade.name,
27330      type: wrapReference(facade.type),
27331      internalType: new WrappedNodeExpr(facade.type),
27332      typeArgumentCount: 0,
27333      deps: null,
27334      pipeName: facade.pipeName,
27335      pure: facade.pure,
27336      isStandalone: facade.isStandalone
27337    };
27338    const res = compilePipeFromMetadata(metadata);
27339    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
27340  }
27341
27342  compilePipeDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
27343    const meta = convertDeclarePipeFacadeToMetadata(declaration);
27344    const res = compilePipeFromMetadata(meta);
27345    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
27346  }
27347
27348  compileInjectable(angularCoreEnv, sourceMapUrl, facade) {
27349    const {
27350      expression,
27351      statements
27352    } = compileInjectable({
27353      name: facade.name,
27354      type: wrapReference(facade.type),
27355      internalType: new WrappedNodeExpr(facade.type),
27356      typeArgumentCount: facade.typeArgumentCount,
27357      providedIn: computeProvidedIn(facade.providedIn),
27358      useClass: convertToProviderExpression(facade, 'useClass'),
27359      useFactory: wrapExpression(facade, 'useFactory'),
27360      useValue: convertToProviderExpression(facade, 'useValue'),
27361      useExisting: convertToProviderExpression(facade, 'useExisting'),
27362      deps: facade.deps?.map(convertR3DependencyMetadata)
27363    },
27364    /* resolveForwardRefs */
27365    true);
27366    return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
27367  }
27368
27369  compileInjectableDeclaration(angularCoreEnv, sourceMapUrl, facade) {
27370    const {
27371      expression,
27372      statements
27373    } = compileInjectable({
27374      name: facade.type.name,
27375      type: wrapReference(facade.type),
27376      internalType: new WrappedNodeExpr(facade.type),
27377      typeArgumentCount: 0,
27378      providedIn: computeProvidedIn(facade.providedIn),
27379      useClass: convertToProviderExpression(facade, 'useClass'),
27380      useFactory: wrapExpression(facade, 'useFactory'),
27381      useValue: convertToProviderExpression(facade, 'useValue'),
27382      useExisting: convertToProviderExpression(facade, 'useExisting'),
27383      deps: facade.deps?.map(convertR3DeclareDependencyMetadata)
27384    },
27385    /* resolveForwardRefs */
27386    true);
27387    return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
27388  }
27389
27390  compileInjector(angularCoreEnv, sourceMapUrl, facade) {
27391    const meta = {
27392      name: facade.name,
27393      type: wrapReference(facade.type),
27394      internalType: new WrappedNodeExpr(facade.type),
27395      providers: facade.providers && facade.providers.length > 0 ? new WrappedNodeExpr(facade.providers) : null,
27396      imports: facade.imports.map(i => new WrappedNodeExpr(i))
27397    };
27398    const res = compileInjector(meta);
27399    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
27400  }
27401
27402  compileInjectorDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
27403    const meta = convertDeclareInjectorFacadeToMetadata(declaration);
27404    const res = compileInjector(meta);
27405    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
27406  }
27407
27408  compileNgModule(angularCoreEnv, sourceMapUrl, facade) {
27409    const meta = {
27410      type: wrapReference(facade.type),
27411      internalType: new WrappedNodeExpr(facade.type),
27412      adjacentType: new WrappedNodeExpr(facade.type),
27413      bootstrap: facade.bootstrap.map(wrapReference),
27414      declarations: facade.declarations.map(wrapReference),
27415      publicDeclarationTypes: null,
27416      imports: facade.imports.map(wrapReference),
27417      includeImportTypes: true,
27418      exports: facade.exports.map(wrapReference),
27419      selectorScopeMode: R3SelectorScopeMode.Inline,
27420      containsForwardDecls: false,
27421      schemas: facade.schemas ? facade.schemas.map(wrapReference) : null,
27422      id: facade.id ? new WrappedNodeExpr(facade.id) : null
27423    };
27424    const res = compileNgModule(meta);
27425    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
27426  }
27427
27428  compileNgModuleDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
27429    const expression = compileNgModuleDeclarationExpression(declaration);
27430    return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, []);
27431  }
27432
27433  compileDirective(angularCoreEnv, sourceMapUrl, facade) {
27434    const meta = convertDirectiveFacadeToMetadata(facade);
27435    return this.compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta);
27436  }
27437
27438  compileDirectiveDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
27439    const typeSourceSpan = this.createParseSourceSpan('Directive', declaration.type.name, sourceMapUrl);
27440    const meta = convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan);
27441    return this.compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta);
27442  }
27443
27444  compileDirectiveFromMeta(angularCoreEnv, sourceMapUrl, meta) {
27445    const constantPool = new ConstantPool();
27446    const bindingParser = makeBindingParser();
27447    const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
27448    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements);
27449  }
27450
27451  compileComponent(angularCoreEnv, sourceMapUrl, facade) {
27452    // Parse the template and check for errors.
27453    const {
27454      template,
27455      interpolation
27456    } = parseJitTemplate(facade.template, facade.name, sourceMapUrl, facade.preserveWhitespace
27456s, facade.interpolation); // Compile the component metadata, including template, into an expression.
27457
27458    const meta = { ...facade,
27459      ...convertDirectiveFacadeToMetadata(facade),
27460      selector: facade.selector || this.elementSchemaRegistry.getDefaultComponentElementName(),
27461      template,
27462      declarations: facade.declarations.map(convertDeclarationFacadeToMetadata),
27463      declarationListEmitMode: 0
27464      /* DeclarationListEmitMode.Direct */
27465      ,
27466      styles: [...facade.styles, ...template.styles],
27467      encapsulation: facade.encapsulation,
27468      interpolation,
27469      changeDetection: facade.changeDetection,
27470      animations: facade.animations != null ? new WrappedNodeExpr(facade.animations) : null,
27471      viewProviders: facade.viewProviders != null ? new WrappedNodeExpr(facade.viewProviders) : null,
27472      relativeContextFilePath: '',
27473      i18nUseExternalIds: true
27474    };
27475    const jitExpressionSourceMap = `ng:///${facade.name}.js`;
27476    return this.compileComponentFromMeta(angularCoreEnv, jitExpressionSourceMap, meta);
27477  }
27478
27479  compileComponentDeclaration(angularCoreEnv, sourceMapUrl, declaration) {
27480    const typeSourceSpan = this.createParseSourceSpan('Component', declaration.type.name, sourceMapUrl);
27481    const meta = convertDeclareComponentFacadeToMetadata(declaration, typeSourceSpan, sourceMapUrl);
27482    return this.compileComponentFromMeta(angularCoreEnv, sourceMapUrl, meta);
27483  }
27484
27485  compileComponentFromMeta(angularCoreEnv, sourceMapUrl, meta) {
27486    const constantPool = new ConstantPool();
27487    const bindingParser = makeBindingParser(meta.interpolation);
27488    const res = compileComponentFromMetadata(meta, constantPool, bindingParser);
27489    return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, constantPool.statements);
27490  }
27491
27492  compileFactory(angularCoreEnv, sourceMapUrl, meta) {
27493    const factoryRes = compileFactoryFunction({
27494      name: meta.name,
27495      type: wrapReference(meta.type),
27496      internalType: new WrappedNodeExpr(meta.type),
27497      typeArgumentCount: meta.typeArgumentCount,
27498      deps: convertR3DependencyMetadataArray(meta.deps),
27499      target: meta.target
27500    });
27501    return this.jitExpression(factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements);
27502  }
27503
27504  compileFactoryDeclaration(angularCoreEnv, sourceMapUrl, meta) {
27505    const factoryRes = compileFactoryFunction({
27506      name: meta.type.name,
27507      type: wrapReference(meta.type),
27508      internalType: new WrappedNodeExpr(meta.type),
27509      typeArgumentCount: 0,
27510      deps: Array.isArray(meta.deps) ? meta.deps.map(convertR3DeclareDependencyMetadata) : meta.deps,
27511      target: meta.target
27512    });
27513    return this.jitExpression(factoryRes.expression, angularCoreEnv, sourceMapUrl, factoryRes.statements);
27514  }
27515
27516  createParseSourceSpan(kind, typeName, sourceUrl) {
27517    return r3JitTypeSourceSpan(kind, typeName, sourceUrl);
27518  }
27519  /**
27520   * JIT compiles an expression and returns the result of executing that expression.
27521   *
27522   * @param def the definition which will be compiled and executed to get the value to patch
27523   * @param context an object map of @angular/core symbol names to symbols which will be available
27524   * in the context of the compiled expression
27525   * @param sourceUrl a URL to use for the source map of the compiled expression
27526   * @param preStatements a collection of statements that should be evaluated before the expression.
27527   */
27528
27529
27530  jitExpression(def, context, sourceUrl, preStatements) {
27531    // The ConstantPool may contain Statements which declare variables used in the final expression.
27532    // Therefore, its statements need to precede the actual JIT operation. The final statement is a
27533    // declaration of $def which is set to the expression being compiled.
27534    const statements = [...preStatements, new DeclareVarStmt('$def', def, undefined, StmtModifier.Exported)];
27535    const res = this.jitEvaluator.evaluateStatements(sourceUrl, statements, new R3JitReflector(context),
27536    /* enableSourceMaps */
27537    true);
27538    return res['$def'];
27539  }
27540
27541}
27542
27543function convertToR3QueryMetadata(facade) {
27544  return { ...facade,
27545    predicate: convertQueryPredicate(facade.predicate),
27546    read: facade.read ? new WrappedNodeExpr(facade.read) : null,
27547    static: facade.static,
27548    emitDistinctChangesOnly: facade.emitDistinctChangesOnly
27549  };
27550}
27551
27552function convertQueryDeclarationToMetadata(declaration) {
27553  return {
27554    propertyName: declaration.propertyName,
27555    first: declaration.first ?? false,
27556    predicate: convertQueryPredicate(declaration.predicate),
27557    descendants: declaration.descendants ?? false,
27558    read: declaration.read ? new WrappedNodeExpr(declaration.read) : null,
27559    static: declaration.static ?? false,
27560    emitDistinctChangesOnly: declaration.emitDistinctChangesOnly ?? true
27561  };
27562}
27563
27564function convertQueryPredicate(predicate) {
27565  return Array.isArray(predicate) ? // The predicate is an array of str
27565ings so pass it through.
27566  predicate : // The predicate is a type - assume that we will need to unwrap any `forwardRef()` calls.
27567  createMayBeForwardRefExpression(new WrappedNodeExpr(predicate), 1
27568  /* ForwardRefHandling.Wrapped */
27569  );
27570}
27571
27572function convertDirectiveFacadeToMetadata(facade) {
27573  const inputsFromMetadata = parseInputOutputs(facade.inputs || []);
27574  const outputsFromMetadata = parseInputOutputs(facade.outputs || []);
27575  const propMetadata = facade.propMetadata;
27576  const inputsFromType = {};
27577  const outputsFromType = {};
27578
27579  for (const field in propMetadata) {
27580    if (propMetadata.hasOwnProperty(field)) {
27581      propMetadata[field].forEach(ann => {
27582        if (isInput(ann)) {
27583          inputsFromType[field] = ann.bindingPropertyName ? [ann.bindingPropertyName, field] : field;
27584        } else if (isOutput(ann)) {
27585          outputsFromType[field] = ann.bindingPropertyName || field;
27586        }
27587      });
27588    }
27589  }
27590
27591  return { ...facade,
27592    typeArgumentCount: 0,
27593    typeSourceSpan: facade.typeSourceSpan,
27594    type: wrapReference(facade.type),
27595    internalType: new WrappedNodeExpr(facade.type),
27596    deps: null,
27597    host: extractHostBindings(facade.propMetadata, facade.typeSourceSpan, facade.host),
27598    inputs: { ...inputsFromMetadata,
27599      ...inputsFromType
27600    },
27601    outputs: { ...outputsFromMetadata,
27602      ...outputsFromType
27603    },
27604    queries: facade.queries.map(convertToR3QueryMetadata),
27605    providers: facade.providers != null ? new WrappedNodeExpr(facade.providers) : null,
27606    viewQueries: facade.viewQueries.map(convertToR3QueryMetadata),
27607    fullInheritance: false
27608  };
27609}
27610
27611function convertDeclareDirectiveFacadeToMetadata(declaration, typeSourceSpan) {
27612  return {
27613    name: declaration.type.name,
27614    type: wrapReference(declaration.type),
27615    typeSourceSpan,
27616    internalType: new WrappedNodeExpr(declaration.type),
27617    selector: declaration.selector ?? null,
27618    inputs: declaration.inputs ?? {},
27619    outputs: declaration.outputs ?? {},
27620    host: convertHostDeclarationToMetadata(declaration.host),
27621    queries: (declaration.queries ?? []).map(convertQueryDeclarationToMetadata),
27622    viewQueries: (declaration.viewQueries ?? []).map(convertQueryDeclarationToMetadata),
27623    providers: declaration.providers !== undefined ? new WrappedNodeExpr(declaration.providers) : null,
27624    exportAs: declaration.exportAs ?? null,
27625    usesInheritance: declaration.usesInheritance ?? false,
27626    lifecycle: {
27627      usesOnChanges: declaration.usesOnChanges ?? false
27628    },
27629    deps: null,
27630    typeArgumentCount: 0,
27631    fullInheritance: false,
27632    isStandalone: declaration.isStandalone ?? false
27633  };
27634}
27635
27636function convertHostDeclarationToMetadata(host = {}) {
27637  return {
27638    attributes: convertOpaqueValuesToExpressions(host.attributes ?? {}),
27639    listeners: host.listeners ?? {},
27640    properties: host.properties ?? {},
27641    specialAttributes: {
27642      classAttr: host.classAttribute,
27643      styleAttr: host.styleAttribute
27644    }
27645  };
27646}
27647
27648function convertOpaqueValuesToExpressions(obj) {
27649  const result = {};
27650
27651  for (const key of Object.keys(obj)) {
27652    result[key] = new WrappedNodeExpr(obj[key]);
27653  }
27654
27655  return result;
27656}
27657
27658function convertDeclareComponentFacadeToMetadata(decl, typeSourceSpan, sourceMapUrl) {
27659  const {
27660    template,
27661    interpolation
27662  } = parseJitTemplate(decl.template, decl.type.name, sourceMapUrl, decl.preserveWhitespaces ?? false, decl.interpolation);
27663  const declarations = [];
27664
27665  if (decl.dependencies) {
27666    for (const innerDep of decl.dependencies) {
27667      switch (innerDep.kind) {
27668        case 'directive':
27669        case 'component':
27670          declarations.push(convertDirectiveDeclarationToMetadata(innerDep));
27671          break;
27672
27673        case 'pipe':
27674          declarations.push(convertPipeDeclarationToMetadata(innerDep));
27675          break;
27676      }
27677    }
27678  } else if (decl.components || decl.directives || decl.pipes) {
27679    // Existing declarations on NPM may not be using the new `dependencies` merged field, and may
27680    // have separate fields for dependencies instead. Unify them for JIT compilation.
27681    decl.components && declarations.push(...decl.components.map(dir => convertDirectiveDeclarationToMetadata(dir,
27682    /* isComponent */
27683    true)));
27684    decl.directives && declarations.push(...decl.directives.map(dir => convertDirectiveDeclarationToMetadata(dir)));
27685    decl.pipes && declarations.push(...convertPipeMapToMetadata(decl.pipes));
27686  }
27687
27688  return { ...convertDeclareDirectiveFacadeToMetadata(decl, typeSourceSpan),
27689    template,
27690    styles: decl.styles ?? [],
27691    declarations,
27692    viewProviders: decl.viewProviders !== undefined ? new WrappedNodeExpr(decl.viewProviders) : null,
27693    animations: decl.animations !== undefined ? new WrappedNodeExpr(decl.animations) : null,
27694    changeDetection: decl.changeDetection ?? ChangeDetectionStrategy.Default,
27695    encapsulation: decl.encapsulation ?? ViewEncapsulation.Emulated,
27696    interpolation,
27697    declarationListEmitMode: 2
27698    /* DeclarationListEmitMode.ClosureResolved */
27699    ,
27700    relativeContextFilePath: '',
27701    i18nUseExternalIds: true
27702  };
27703}
27704
27705function convertDeclarationFacadeToMetadata(declaration) {
27706  return { ...declaration,
27707    type: new WrappedNodeExpr(declaration.type)
27708  };
27709}
27710
27711function convertDirectiveDeclarationToMetadata(declaration, isComponent = null) {
27712  return {
27713    kind: R3TemplateDependencyKind.Directive,
27714    isComponent: isComponent || declaration.kind === 'component',
27715    selector: declaration.selector,
27716    type: new WrappedNodeExpr(declaration.type),
27717    inputs: declaration.inputs ?? [],
27718    outputs: declaration.outputs ?? [],
27719    exportAs: declaration.exportAs ?? null
27720  };
27721}
27722
27723function convertPipeMapToMetadata(pipes) {
27724  if (!pipes) {
27725    return [];
27726  }
27727
27728  return Object.keys(pipes).map(name => {
27729    return {
27730      kind: R3TemplateDependencyKind.Pipe,
27731      name,
27732      type: new WrappedNodeExpr(pipes[name])
27733    };
27734  });
27735}
27736
27737function convertPipeDeclarationToMetadata(pipe) {
27738  return {
27739    kind: R3TemplateDependencyKind.Pipe,
27740    name: pipe.name,
27741    type: new WrappedNodeExpr(pipe.type)
27742  };
27743}
27744
27745function parseJitTemplate(template, typeName, sourceMapUrl, preserveWhitespace
27745s, interpolation) {
27746  const interpolationConfig = interpolation ? InterpolationConfig.fromArray(interpolation) : DEFAULT_INTERPOLATION_CONFIG; // Parse the template and check for errors.
27747
27748  const parsed = parseTemplate(template, sourceMapUrl, {
27749    preserveWhitespaces,
27750    interpolationConfig
27751  });
27752
27753  if (parsed.errors !== null) {
27754    const errors = parsed.errors.map(err => err.toString()).join(', ');
27755    throw new Error(`Errors during JIT compilation of template for ${typeName}: ${errors}`);
27756  }
27757
27758  return {
27759    template: parsed,
27760    interpolation: interpolationConfig
27761  };
27762}
27763/**
27764 * Convert the expression, if present to an `R3ProviderExpression`.
27765 *
27766 * In JIT mode we do not want the compiler to wrap the expression in a `forwardRef()` call because,
27767 * if it is referencing a type that has not yet been defined, it will have already been wrapped in
27768 * a `forwardRef()` - either by the application developer or during partial-compilation. Thus we can
27769 * use `ForwardRefHandling.None`.
27770 */
27771
27772
27773function convertToProviderExpression(obj, property) {
27774  if (obj.hasOwnProperty(property)) {
27775    return createMayBeForwardRefExpression(new WrappedNodeExpr(obj[property]), 0
27776    /* ForwardRefHandling.None */
27777    );
27778  } else {
27779    return undefined;
27780  }
27781}
27782
27783function wrapExpression(obj, property) {
27784  if (obj.hasOwnProperty(property)) {
27785    return new WrappedNodeExpr(obj[property]);
27786  } else {
27787    return undefined;
27788  }
27789}
27790
27791function computeProvidedIn(providedIn) {
27792  const expression = typeof providedIn === 'function' ? new WrappedNodeExpr(providedIn) : new LiteralExpr(providedIn ?? null); // See `convertToProviderExpression()` for why this uses `ForwardRefHandling.None`.
27793
27794  return createMayBeForwardRefExpression(expression, 0
27795  /* ForwardRefHandling.None */
27796  );
27797}
27798
27799function convertR3DependencyMetadataArray(facades) {
27800  return facades == null ? null : facades.map(convertR3DependencyMetadata);
27801}
27802
27803function convertR3DependencyMetadata(facade) {
27804  const isAttributeDep = facade.attribute != null; // both `null` and `undefined`
27805
27806  const rawToken = facade.token === null ? null : new WrappedNodeExpr(facade.token); // In JIT mode, if the dep is an `@Attribute()` then we use the attribute name given in
27807  // `attribute` rather than the `token`.
27808
27809  const token = isAttributeDep ? new WrappedNodeExpr(facade.attribute) : rawToken;
27810  return createR3DependencyMetadata(token, isAttributeDep, facade.host, facade.optional, facade.self, facade.skipSelf);
27811}
27812
27813function convertR3DeclareDependencyMetadata(facade) {
27814  const isAttributeDep = facade.attribute ?? false;
27815  const token = facade.token === null ? null : new WrappedNodeExpr(facade.token);
27816  return createR3DependencyMetadata(token, isAttributeDep, facade.host ?? false, facade.optional ?? false, facade.self ?? false, facade.skipSelf ?? false);
27817}
27818
27819function createR3DependencyMetadata(token, isAttributeDep, host, optional, self, skipSelf) {
27820  // If the dep is an `@Attribute()` the `attributeNameType` ought to be the `unknown` type.
27821  // But types are not available at runtime so we just use a literal `"<unknown>"` string as a dummy
27822  // marker.
27823  const attributeNameType = isAttributeDep ? literal('unknown') : null;
27824  return {
27825    token,
27826    attributeNameType,
27827    host,
27828    optional,
27829    self,
27830    skipSelf
27831  };
27832}
27833
27834function extractHostBindings(propMetadata, sourceSpan, host) {
27835  // First parse the declarations from the metadata.
27836  const bindings = parseHostBindings(host || {}); // After that check host bindings for errors
27837
27838  const errors = verifyHostBindings(bindings, sourceSpan);
27839
27840  if (errors.length) {
27841    throw new Error(errors.map(error => error.msg).join('\n'));
27842  } // Next, loop over the properties of the object, looking for @HostBinding and @HostListener.
27843
27844
27845  for (const field in propMetadata) {
27846    if (propMetadata.hasOwnProperty(field)) {
27847      propMetadata[field].forEach(ann => {
27848        if (isHostBinding(ann)) {
27849          // Since this is a decorator, we know that the value is a class member. Always access it
27850          // through `this` so that further down the line it can't be confused for a literal value
27851          // (e.g. if there's a property called `true`).
27852          bindings.properties[ann.hostPropertyName || field] = getSafePropertyAccessString('this', field);
27853        } else if (isHostListener(ann)) {
27854          bindings.listeners[ann.eventName || field] = `${field}(${(ann.args || []).join(',')})`;
27855        }
27856      });
27857    }
27858  }
27859
27860  return bindings;
27861}
27862
27863function isHostBinding(value) {
27864  return value.ngMetadataName === 'HostBinding';
27865}
27866
27867function isHostListener(value) {
27868  return value.ngMetadataName === 'HostListener';
27869}
27870
27871function isInput(value) {
27872  return value.ngMetadataName === 'Input';
27873}
27874
27875function isOutput(value) {
27876  return value.ngMetadataName === 'Output';
27877}
27878
27879function parseInputOutputs(values) {
27880  return values.reduce((results, value) => {
27881    const [field, property] = value.split(':', 2).map(str => str.trim());
27882    results[field] = property || field;
27883    return results;
27884  }, {});
27885}
27886
27887function convertDeclarePipeFacadeToMetadata(declaration) {
27888  return {
27889    name: declaration.type.name,
27890    type: wrapReference(declaration.type),
27891    internalType: new WrappedNodeExpr(declaration.type),
27892    typeArgumentCount: 0,
27893    pipeName: declaration.name,
27894    deps: null,
27895    pure: declaration.pure ?? true,
27896    isStandalone: declaration.isStandalone ?? false
27897  };
27898}
27899
27900function convertDeclareInjectorFacadeToMetadata(declaration) {
27901  return {
27902    name: declaration.type.name,
27903    type: wrapReference(declaration.type),
27904    internalType: new WrappedNodeExpr(declaration.type),
27905    providers: declaration.providers !== undefined && declaration.providers.length > 0 ? new WrappedNodeExpr(declaration.providers) : null,
27906    imports: declaration.imports !== undefined ? declaration.imports.map(i => new WrappedNodeExpr(i)) : []
27907  };
27908}
27909
27910function publishFacade(global) {
27911  const ng = global.ng || (global.ng = {});
27912  ng.ɵcompilerFacade = new CompilerFacadeImpl();
27913}
27914/**
27915 * @license
27916 * Copyright Google LLC All Rights Reserved.
27917 *
27918 * Use of this source code is governed by an MIT-style license that can be
27919 * found in the LICENSE file at https://angular.io/license
27920 */
27921
27922
27923const VERSION = new Version('14.2.12');
27924/**
27925 * @license
27926 * Copyright Google LLC All Rights Reserved.
27927 *
27928 * Use of this source code is governed by an MIT-style license that can be
27929 * found in the LICENSE file at https://angular.io/license
27930 */
27931
27932class CompilerConfig {
27933  constructor({
27934    defaultEncapsulation = ViewEncapsulation.Emulated,
27935    useJit = true,
27936    jitDevMode = false,
27937    missingTranslation = null,
27938    preserveWhitespaces,
27939    strictInjectionParameters
27940  } = {}) {
27941    this.defaultEncapsulation = defaultEncapsulation;
27942    this.useJit = !!useJit;
27943    this.jitDevMode = !!jitDevMode;
27944    this.missingTranslation = missingTranslation;
27945    this.preserveWhitespaces = preserveWhitespacesDefault(noUndefined(preserveWhitespaces));
27946    this.strictInjectionParameters = strictInjectionParameters === true;
27947  }
27948
27949}
27950
27951function preserveWhitespacesDefault(preserveWhitespacesOption, defaultSetting = false) {
27952  return preserveWhitespacesOption === null ? defaultSetting : preserveWhitespacesOption;
27953}
27954/**
27955 * @license
27956 * Copyright Google LLC All Rights Reserved.
27957 *
27958 * Use of this source code is governed by an MIT-style license that can be
27959 * found in the LICENSE file at https://angular.io/license
27960 */
27961
27962
27963const _I18N_ATTR = 'i18n';
27964const _I18N_ATTR_PREFIX = 'i18n-';
27965const _I18N_COMMENT_PREFIX_REGEXP = /^i18n:?/;
27966const MEANING_SEPARATOR = '|';
27967const ID_SEPARATOR = '@@';
27968let i18nCommentsWarned = false;
27969/**
27970 * Extract translatable messages from an html AST
27971 */
27972
27973function extractMessages(nodes, interpolationConfig, implicitTags, implicitAttrs) {
27974  const visitor = new _Visitor(implicitTags, implicitAttrs);
27975  return visitor.extract(nodes, interpolationConfig);
27976}
27977
27978function mergeTranslations(nodes, translations, interpolationConfig, implicitTags, implicitAttrs) {
27979  const visitor = new _Visitor(implicitTags, implicitAttrs);
27980  return visitor.merge(nodes, translations, interpolationConfig);
27981}
27982
27983class ExtractionResult {
27984  constructor(messages, errors) {
27985    this.messages = messages;
27986    this.errors = errors;
27987  }
27988
27989}
27990
27991var _VisitorMode;
27992
27993(function (_VisitorMode) {
27994  _VisitorMode[_VisitorMode["Extract"] = 0] = "Extract";
27995  _VisitorMode[_VisitorMode["Merge"] = 1] = "Merge";
27996})(_VisitorMode || (_VisitorMode = {}));
27997/**
27998 * This Visitor is used:
27999 * 1. to extract all the translatable strings from an html AST (see `extract()`),
28000 * 2. to replace the translatable strings with the actual translations (see `merge()`)
28001 *
28002 * @internal
28003 */
28004
28005
28006class _Visitor {
28007  constructor(_implicitTags, _implicitAttrs) {
28008    this._implicitTags = _implicitTags;
28009    this._implicitAttrs = _implicitAttrs;
28010  }
28011  /**
28012   * Extracts the messages from the tree
28013   */
28014
28015
28016  extract(nodes, interpolationConfig) {
28017    this._init(_VisitorMode.Extract, interpolationConfig);
28018
28019    nodes.forEach(node => node.visit(this, null));
28020
28021    if (this._inI18nBlock) {
28022      this._reportError(nodes[nodes.length - 1], 'Unclosed block');
28023    }
28024
28025    return new ExtractionResult(this._messages, this._errors);
28026  }
28027  /**
28028   * Returns a tree where all translatable nodes are translated
28029   */
28030
28031
28032  merge(nodes, translations, interpolationConfig) {
28033    this._init(_VisitorMode.Merge, interpolationConfig);
28034
28035    this._translations = translations; // Construct a single fake root element
28036
28037    const wrapper = new Element('wrapper', [], nodes, undefined, undefined, undefined);
28038    const translatedNode = wrapper.visit(this, null);
28039
28040    if (this._inI18nBlock) {
28041      this._reportError(nodes[nodes.length - 1], 'Unclosed block');
28042    }
28043
28044    return new ParseTreeResult(translatedNode.children, this._errors);
28045  }
28046
28047  visitExpansionCase(icuCase, context) {
28048    // Parse cases for translatable html attributes
28049    const expression = visitAll(this, icuCase.expression, context);
28050
28051    if (this._mode === _VisitorMode.Merge) {
28052      return new ExpansionCase(icuCase.value, expression, icuCase.sourceSpan, icuCase.valueSourceSpan, icuCase.expSourceSpan);
28053    }
28054  }
28055
28056  visitExpansion(icu, context) {
28057    this._mayBeAddBlockChildren(icu);
28058
28059    const wasInIcu = this._inIcu;
28060
28061    if (!this._inIcu) {
28062      // nested ICU messages should not be extracted but top-level translated as a whole
28063      if (this._isInTranslatableSection) {
28064        this._addMessage([icu]);
28065      }
28066
28067      this._inIcu = true;
28068    }
28069
28070    const cases = visitAll(this, icu.cases, context);
28071
28072    if (this._mode === _VisitorMode.Merge) {
28073      icu = new Expansion(icu.switchValue, icu.type, cases, icu.sourceSpan, icu.switchValueSourceSpan);
28074    }
28075
28076    this._inIcu = wasInIcu;
28077    return icu;
28078  }
28079
28080  visitComment(comment, context) {
28081    const isOpening = _isOpeningComment(comment);
28082
28083    if (isOpening && this._isInTranslatableSection) {
28084      this._reportError(comment, 'Could not start a block inside a translatable section');
28085
28086      return;
28087    }
28088
28089    const isClosing = _isClosingComment(comment);
28090
28091    if (isClosing && !this._inI18nBlock) {
28092      this._reportError(comment, 'Trying to close an unopened block');
28093
28094      return;
28095    }
28096
28097    if (!this._inI18nNode && !this._inIcu) {
28098      if (!this._inI18nBlock) {
28099        if (isOpening) {
28100          // deprecated from v5 you should use <ng-container i18n> instead of i18n comments
28101          if (!i18nCommentsWarned && console && console.warn) {
28102            i18nCommentsWarned = true;
28103            const details = comment.sourceSpan.details ? `, ${comment.sourceSpan.details}` : ''; // TODO(ocombe): use a log service once there is a public one available
28104
28105            console.warn(`I18n comments are deprecated, use an <ng-container> element instead (${comment.sourceSpan.start}${details})`);
28106          }
28107
28108          this._inI18nBlock = true;
28109          this._blockStartDepth = this._depth;
28110          this._blockChildren = [];
28111          this._blockMeaningAndDesc = comment.value.replace(_I18N_COMMENT_PREFIX_REGEXP, '').trim();
28112
28113          this._openTranslatableSection(comment);
28114        }
28115      } else {
28116        if (isClosing) {
28117          if (this._depth == this._blockStartDepth) {
28118            this._closeTranslatableSection(comment, this._blockChildren);
28119
28120            this._inI18nBlock = false;
28121
28122            const message = this._addMessage(this._blockChildren, this._blockMeaningAndDesc); // merge attributes in sections
28123
28124
28125            const nodes = this._translateMessage(comment, message);
28126
28127            return visitAll(this, nodes);
28128          } else {
28129            this._reportError(comment, 'I18N blocks should not cross element boundaries');
28130
28131            return;
28132          }
28133        }
28134      }
28135    }
28136  }
28137
28138  visitText(text, context) {
28139    if (this._isInTranslatableSection) {
28140      this._mayBeAddBlockChildren(text);
28141    }
28142
28143    return text;
28144  }
28145
28146  visitElement(el, context) {
28147    this._mayBeAddBlockChildren(el);
28148
28149    this._depth++;
28150    const wasInI18nNode = this._inI18nNode;
28151    const wasInImplicitNode = this._inImplicitNode;
28152    let childNodes = [];
28153    let translatedChildNodes = undefined; // Extract:
28154    // - top level nodes with the (implicit) "i18n" attribute if not already in a section
28155    // - ICU messages
28156
28157    const i18nAttr = _getI18nAttr(el);
28158
28159    const i18nMeta = i18nAttr ? i18nAttr.value : '';
28160    const isImplicit = this._implicitTags.some(tag => el.name === tag) && !this._inIcu && !this._isInTranslatableSection;
28161    const isTopLevelImplicit = !wasInImplicitNode && isImplicit;
28162    this._inImplicitNode = wasInImplicitNode || isImplicit;
28163
28164    if (!this._isInTranslatableSection && !this._inIcu) {
28165      if (i18nAttr || isTopLevelImplicit) {
28166        this._inI18nNode = true;
28167
28168        const message = this._addMessage(el.children, i18nMeta);
28169
28170        translatedChildNodes = this._translateMessage(el, message);
28171      }
28172
28173      if (this._mode == _VisitorMode.Extract) {
28174        const isTranslatable = i18nAttr || isTopLevelImplicit;
28175        if (isTranslatable) this._openTranslatableSection(el);
28176        visitAll(this, el.children);
28177        if (isTranslatable) this._closeTranslatableSection(el, el.children);
28178      }
28179    } else {
28180      if (i18nAttr || isTopLevelImplicit) {
28181        this._reportError(el, 'Could not mark an element as translatable inside a translatable section');
28182      }
28183
28184      if (this._mode == _VisitorMode.Extract) {
28185        // Descend into child nodes for extraction
28186        visitAll(this, el.children);
28187      }
28188    }
28189
28190    if (this._mode === _VisitorMode.Merge) {
28191      const visitNodes = translatedChildNodes || el.children;
28192      visitNodes.forEach(child => {
28193        const visited = child.visit(this, context);
28194
28195        if (visited && !this._isInTranslatableSection) {
28196          // Do not add the children from translatable sections (= i18n blocks here)
28197          // They will be added later in this loop when the block closes (i.e. on `<!-- /i18n -->`)
28198          childNodes = childNodes.concat(visited);
28199        }
28200      });
28201    }
28202
28203    this._visitAttributesOf(el);
28204
28205    this._depth--;
28206    this._inI18nNode = wasInI18nNode;
28207    this._inImplicitNode = wasInImplicitNode;
28208
28209    if (this._mode === _VisitorMode.Merge) {
28210      const translatedAttrs = this._translateAttributes(el);
28211
28212      return new Element(el.name, translatedAttrs, childNodes, el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
28213    }
28214
28215    return null;
28216  }
28217
28218  visitAttribute(attribute, context) {
28219    throw new Error('unreachable code');
28220  }
28221
28222  _init(mode, interpolationConfig) {
28223    this._mode = mode;
28224    this._inI18nBlock = false;
28225    this._inI18nNode = false;
28226    this._depth = 0;
28227    this._inIcu = false;
28228    this._msgCountAtSectionStart = undefined;
28229    this._errors = [];
28230    this._messages = [];
28231    this._inImplicitNode = false;
28232    this._createI18nMessage = createI18nMessageFactory(interpolationConfig);
28233  } // looks for translatable attributes
28234
28235
28236  _visitAttributesOf(el) {
28237    const explicitAttrNameToValue = {};
28238    const implicitAttrNames = this._implicitAttrs[el.name] || [];
28239    el.attrs.filter(attr => attr.name.startsWith(_I18N_ATTR_PREFIX)).forEach(attr => explicitAttrNameToValue[attr.name.slice(_I18N_ATTR_PREFIX.length)] = attr.value);
28240    el.attrs.forEach(attr => {
28241      if (attr.name in explicitAttrNameToValue) {
28242        this._addMessage([attr], explicitAttrNameToValue[attr.name]);
28243      } else if (implicitAttrNames.some(name => attr.name === name)) {
28244        this._addMessage([attr]);
28245      }
28246    });
28247  } // add a translatable message
28248
28249
28250  _addMessage(ast, msgMeta) {
28251    if (ast.length == 0 || ast.length == 1 && ast[0] instanceof Attribute && !ast[0].value) {
28252      // Do not create empty messages
28253      return null;
28254    }
28255
28256    const {
28257      meaning,
28258      description,
28259      id
28260    } = _parseMessageMeta(msgMeta);
28261
28262    const message = this._createI18nMessage(ast, meaning, description, id);
28263
28264    this._messages.push(message);
28265
28266    return message;
28267  } // Translates the given message given the `TranslationBundle`
28268  // This is used for translating elements / blocks - see `_translateAttributes` for attributes
28269  // no-op when called in extraction mode (returns [])
28270
28271
28272  _translateMessage(el, message) {
28273    if (message && this._mode === _VisitorMode.Merge) {
28274      const nodes = this._translations.get(message);
28275
28276      if (nodes) {
28277        return nodes;
28278      }
28279
28280      this._reportError(el, `Translation unavailable for message id="${this._translations.digest(message)}"`);
28281    }
28282
28283    return [];
28284  } // translate the attributes of an element and remove i18n specific attributes
28285
28286
28287  _translateAttributes(el) {
28288    const attributes = el.attrs;
28289    const i18nParsedMessageMeta = {};
28290    attributes.forEach(attr => {
28291      if (attr.name.startsWith(_I18N_ATTR_PREFIX)) {
28292        i18nParsedMessageMeta[attr.name.slice(_I18N_ATTR_PREFIX.length)] = _parseMessageMeta(attr.value);
28293      }
28294    });
28295    const translatedAttributes = [];
28296    attributes.forEach(attr => {
28297      if (attr.name === _I18N_ATTR || attr.name.startsWith(_I18N_ATTR_PREFIX)) {
28298        // strip i18n specific attributes
28299        return;
28300      }
28301
28302      if (attr.value && attr.value != '' && i18nParsedMessageMeta.hasOwnProperty(attr.name)) {
28303        const {
28304          meaning,
28305          description,
28306          id
28307        } = i18nParsedMessageMeta[attr.name];
28308
28309        const message = this._createI18nMessage([attr], meaning, description, id);
28310
28311        const nodes = this._translations.get(message);
28312
28313        if (nodes) {
28314          if (nodes.length == 0) {
28315            translatedAttributes.push(new Attribute(attr.name, '', attr.sourceSpan, undefined
28316            /* keySpan */
28317            , undefined
28318            /* valueSpan */
28319            , undefined
28320            /* valueTokens */
28321            , undefined
28322            /* i18n */
28323            ));
28324          } else if (nodes[0] instanceof Text) {
28325            const value = nodes[0].value;
28326            translatedAttributes.push(new Attribute(attr.name, value, attr.sourceSpan, undefined
28327            /* keySpan */
28328            , undefined
28329            /* valueSpan */
28330            , undefined
28331            /* valueTokens */
28332            , undefined
28333            /* i18n */
28334            ));
28335          } else {
28336            this._reportError(el, `Unexpected translation for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
28337          }
28338        } else {
28339          this._reportError(el, `Translation unavailable for attribute "${attr.name}" (id="${id || this._translations.digest(message)}")`);
28340        }
28341      } else {
28342        translatedAttributes.push(attr);
28343      }
28344    });
28345    return translatedAttributes;
28346  }
28347  /**
28348   * Add the node as a child of the block when:
28349   * - we are in a block,
28350   * - we are not inside a ICU message (those are handled separately),
28351   * - the node is a "direct child" of the block
28352   */
28353
28354
28355  _mayBeAddBlockChildren(node) {
28356    if (this._inI18nBlock && !this._inIcu && this._depth == this._blockStartDepth) {
28357      this._blockChildren.push(node);
28358    }
28359  }
28360  /**
28361   * Marks the start of a section, see `_closeTranslatableSection`
28362   */
28363
28364
28365  _openTranslatableSection(node) {
28366    if (this._isInTranslatableSection) {
28367      this._reportError(node, 'Unexpected section start');
28368    } else {
28369      this._msgCountAtSectionStart = this._messages.length;
28370    }
28371  }
28372  /**
28373   * A translatable section could be:
28374   * - the content of translatable element,
28375   * - nodes between `<!-- i18n -->` and `<!-- /i18n -->` comments
28376   */
28377
28378
28379  get _isInTranslatableSection() {
28380    return this._msgCountAtSectionStart !== void 0;
28381  }
28382  /**
28383   * Terminates a section.
28384   *
28385   * If a section has only one significant children (comments not significant) then we should not
28386   * keep the message from this children:
28387   *
28388   * `<p i18n="meaning|description">{ICU message}</p>` would produce two messages:
28389   * - one for the <p> content with meaning and description,
28390   * - another one for the ICU message.
28391   *
28392   * In this case the last message is discarded as it contains less information (the AST is
28393   * otherwise identical).
28394   *
28395   * Note that we should still keep messages extracted from attributes inside the section (ie in the
28396   * ICU message here)
28397   */
28398
28399
28400  _closeTranslatableSection(node, directChildren) {
28401    if (!this._isInTranslatableSection) {
28402      this._reportError(node, 'Unexpected section end');
28403
28404      return;
28405    }
28406
28407    const startIndex = this._msgCountAtSectionStart;
28408    const significantChildren = directChildren.reduce((count, node) => count + (node instanceof Comment ? 0 : 1), 0);
28409
28410    if (significantChildren == 1) {
28411      for (let i = this._messages.length - 1; i >= startIndex; i--) {
28412        const ast = this._messages[i].nodes;
28413
28414        if (!(ast.length == 1 && ast[0] instanceof Text$2)) {
28415          this._messages.splice(i, 1);
28416
28417          break;
28418        }
28419      }
28420    }
28421
28422    this._msgCountAtSectionStart = undefined;
28423  }
28424
28425  _reportError(node, msg) {
28426    this._errors.push(new I18nError(node.sourceSpan, msg));
28427  }
28428
28429}
28430
28431function _isOpeningComment(n) {
28432  return !!(n instanceof Comment && n.value && n.value.startsWith('i18n'));
28433}
28434
28435function _isClosingComment(n) {
28436  return !!(n instanceof Comment && n.value && n.value === '/i18n');
28437}
28438
28439function _getI18nAttr(p) {
28440  return p.attrs.find(attr => attr.name === _I18N_ATTR) || null;
28441}
28442
28443function _parseMessageMeta(i18n) {
28444  if (!i18n) return {
28445    meaning: '',
28446    description: '',
28447    id: ''
28448  };
28449  const idIndex = i18n.indexOf(ID_SEPARATOR);
28450  const descIndex = i18n.indexOf(MEANING_SEPARATOR);
28451  const [meaningAndDesc, id] = idIndex > -1 ? [i18n.slice(0, idIndex), i18n.slice(idIndex + 2)] : [i18n, ''];
28452  const [meaning, description] = descIndex > -1 ? [meaningAndDesc.slice(0, descIndex), meaningAndDesc.slice(descIndex + 1)] : ['', meaningAndDesc];
28453  return {
28454    meaning,
28455    description,
28456    id: id.trim()
28457  };
28458}
28459/**
28460 * @license
28461 * Copyright Google LLC All Rights Reserved.
28462 *
28463 * Use of this source code is governed by an MIT-style license that can be
28464 * found in the LICENSE file at https://angular.io/license
28465 */
28466
28467
28468class XmlTagDefinition {
28469  constructor() {
28470    this.closedByParent = false;
28471    this.isVoid = false;
28472    this.ignoreFirstLf = false;
28473    this.canSelfClose = true;
28474    this.preventNamespaceInheritance = false;
28475  }
28476
28477  requireExtraParent(currentParent) {
28478    return false;
28479  }
28480
28481  isClosedByChild(name) {
28482    return false;
28483  }
28484
28485  getContentType() {
28486    return TagContentType.PARSABLE_DATA;
28487  }
28488
28489}
28490
28491const _TAG_DEFINITION = new XmlTagDefinition();
28492
28493function getXmlTagDefinition(tagName) {
28494  return _TAG_DEFINITION;
28495}
28496/**
28497 * @license
28498 * Copyright Google LLC All Rights Reserved.
28499 *
28500 * Use of this source code is governed by an MIT-style license that can be
28501 * found in the LICENSE file at https://angular.io/license
28502 */
28503
28504
28505class XmlParser extends Parser {
28506  constructor() {
28507    super(getXmlTagDefinition);
28508  }
28509
28510  parse(source, url, options) {
28511    return super.parse(source, url, options);
28512  }
28513
28514}
28515/**
28516 * @license
28517 * Copyright Google LLC All Rights Reserved.
28518 *
28519 * Use of this source code is governed by an MIT-style license that can be
28520 * found in the LICENSE file at https://angular.io/license
28521 */
28522
28523
28524const _VERSION$1 = '1.2';
28525const _XMLNS$1 = 'urn:oasis:names:tc:xliff:document:1.2'; // TODO(vicb): make this a param (s/_/-/)
28526
28527const _DEFAULT_SOURCE_LANG$1 = 'en';
28528const _PLACEHOLDER_TAG$2 = 'x';
28529const _MARKER_TAG$1 = 'mrk';
28530const _FILE_TAG = 'file';
28531const _SOURCE_TAG$1 = 'source';
28532const _SEGMENT_SOURCE_TAG = 'seg-source';
28533const _ALT_TRANS_TAG = 'alt-trans';
28534const _TARGET_TAG$1 = 'target';
28535const _UNIT_TAG$1 = 'trans-unit';
28536const _CONTEXT_GROUP_TAG = 'context-group';
28537const _CONTEXT_TAG = 'context'; // https://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html
28538// https://docs.oasis-open.org/xliff/v1.2/xliff-profile-html/xliff-profile-html-1.2.html
28539
28540class Xliff extends Serializer {
28541  write(messages, locale) {
28542    const visitor = new _WriteVisitor$1();
28543    const transUnits = [];
28544    messages.forEach(message => {
28545      let contextTags = [];
28546      message.sources.forEach(source => {
28547        let contextGroupTag = new Tag(_CONTEXT_GROUP_TAG, {
28548          purpose: 'location'
28549        });
28550        contextGroupTag.children.push(new CR(10), new Tag(_CONTEXT_TAG, {
28551          'context-type': 'sourcefile'
28552        }, [new Text$1(source.filePath)]), new CR(10), new Tag(_CONTEXT_TAG, {
28553          'context-type': 'linenumber'
28554        }, [new Text$1(`${source.startLine}`)]), new CR(8));
28555        contextTags.push(new CR(8), contextGroupTag);
28556      });
28557      const transUnit = new Tag(_UNIT_TAG$1, {
28558        id: message.id,
28559        datatype: 'html'
28560      });
28561      transUnit.children.push(new CR(8), new Tag(_SOURCE_TAG$1, {}, visitor.serialize(message.nodes)), ...contextTags);
28562
28563      if (message.description) {
28564        transUnit.children.push(new CR(8), new Tag('note', {
28565          priority: '1',
28566          from: 'description'
28567        }, [new Text$1(message.description)]));
28568      }
28569
28570      if (message.meaning) {
28571        transUnit.children.push(new CR(8), new Tag('note', {
28572          priority: '1',
28573          from: 'meaning'
28574        }, [new Text$1(message.meaning)]));
28575      }
28576
28577      transUnit.children.push(new CR(6));
28578      transUnits.push(new CR(6), transUnit);
28579    });
28580    const body = new Tag('body', {}, [...transUnits, new CR(4)]);
28581    const file = new Tag('file', {
28582      'source-language': locale || _DEFAULT_SOURCE_LANG$1,
28583      datatype: 'plaintext',
28584      original: 'ng2.template'
28585    }, [new CR(4), body, new CR(2)]);
28586    const xliff = new Tag('xliff', {
28587      version: _VERSION$1,
28588      xmlns: _XMLNS$1
28589    }, [new CR(2), file, new CR()]);
28590    return serialize([new Declaration({
28591      version: '1.0',
28592      encoding: 'UTF-8'
28593    }), new CR(), xliff, new CR()]);
28594  }
28595
28596  load(content, url) {
28597    // xliff to xml nodes
28598    const xliffParser = new XliffParser();
28599    const {
28600      locale,
28601      msgIdToHtml,
28602      errors
28603    } = xliffParser.parse(content, url); // xml nodes to i18n nodes
28604
28605    const i18nNodesByMsgId = {};
28606    const converter = new XmlToI18n$2();
28607    Object.keys(msgIdToHtml).forEach(msgId => {
28608      const {
28609        i18nNodes,
28610        errors: e
28611      } = converter.convert(msgIdToHtml[msgId], url);
28612      errors.push(...e);
28613      i18nNodesByMsgId[msgId] = i18nNodes;
28614    });
28615
28616    if (errors.length) {
28617      throw new Error(`xliff parse errors:\n${errors.join('\n')}`);
28618    }
28619
28620    return {
28621      locale: locale,
28622      i18nNodesByMsgId
28623    };
28624  }
28625
28626  digest(message) {
28627    return digest$1(message);
28628  }
28629
28630}
28631
28632class _WriteVisitor$1 {
28633  visitText(text, context) {
28634    return [new Text$1(text.value)];
28635  }
28636
28637  visitContainer(container, context) {
28638    const nodes = [];
28639    container.children.forEach(node => nodes.push(...node.visit(this)));
28640    return nodes;
28641  }
28642
28643  visitIcu(icu, context) {
28644    const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
28645    Object.keys(icu.cases).forEach(c => {
28646      nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `));
28647    });
28648    nodes.push(new Text$1(`}`));
28649    return nodes;
28650  }
28651
28652  visitTagPlaceholder(ph, context) {
28653    const ctype = getCtypeForTag(ph.tag);
28654
28655    if (ph.isVoid) {
28656      // void tags have no children nor closing tags
28657      return [new Tag(_PLACEHOLDER_TAG$2, {
28658        id: ph.startName,
28659        ctype,
28660        'equiv-text': `<${ph.tag}/>`
28661      })];
28662    }
28663
28664    const startTagPh = new Tag(_PLACEHOLDER_TAG$2, {
28665      id: ph.startName,
28666      ctype,
28667      'equiv-text': `<${ph.tag}>`
28668    });
28669    const closeTagPh = new Tag(_PLACEHOLDER_TAG$2, {
28670      id: ph.closeName,
28671      ctype,
28672      'equiv-text': `</${ph.tag}>`
28673    });
28674    return [startTagPh, ...this.serialize(ph.children), closeTagPh];
28675  }
28676
28677  visitPlaceholder(ph, context) {
28678    return [new Tag(_PLACEHOLDER_TAG$2, {
28679      id: ph.name,
28680      'equiv-text': `{{${ph.value}}}`
28681    })];
28682  }
28683
28684  visitIcuPlaceholder(ph, context) {
28685    const equivText = `{${ph.value.expression}, ${ph.value.type}, ${Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ')}}`;
28686    return [new Tag(_PLACEHOLDER_TAG$2, {
28687      id: ph.name,
28688      'equiv-text': equivText
28689    })];
28690  }
28691
28692  serialize(nodes) {
28693    return [].concat(...nodes.map(node => node.visit(this)));
28694  }
28695
28696} // TODO(vicb): add error management (structure)
28697// Extract messages as xml nodes from the xliff file
28698
28699
28700class XliffParser {
28701  constructor() {
28702    this._locale = null;
28703  }
28704
28705  parse(xliff, url) {
28706    this._unitMlString = null;
28707    this._msgIdToHtml = {};
28708    const xml = new XmlParser().parse(xliff, url);
28709    this._errors = xml.errors;
28710    visitAll(this, xml.rootNodes, null);
28711    return {
28712      msgIdToHtml: this._msgIdToHtml,
28713      errors: this._errors,
28714      locale: this._locale
28715    };
28716  }
28717
28718  visitElement(element, context) {
28719    switch (element.name) {
28720      case _UNIT_TAG$1:
28721        this._unitMlString = null;
28722        const idAttr = element.attrs.find(attr => attr.name === 'id');
28723
28724        if (!idAttr) {
28725          this._addError(element, `<${_UNIT_TAG$1}> misses the "id" attribute`);
28726        } else {
28727          const id = idAttr.value;
28728
28729          if (this._msgIdToHtml.hasOwnProperty(id)) {
28730            this._addError(element, `Duplicated translations for msg ${id}`);
28731          } else {
28732            visitAll(this, element.children, null);
28733
28734            if (typeof this._unitMlString === 'string') {
28735              this._msgIdToHtml[id] = this._unitMlString;
28736            } else {
28737              this._addError(element, `Message ${id} misses a translation`);
28738            }
28739          }
28740        }
28741
28742        break;
28743      // ignore those tags
28744
28745      case _SOURCE_TAG$1:
28746      case _SEGMENT_SOURCE_TAG:
28747      case _ALT_TRANS_TAG:
28748        break;
28749
28750      case _TARGET_TAG$1:
28751        const innerTextStart = element.startSourceSpan.end.offset;
28752        const innerTextEnd = element.endSourceSpan.start.offset;
28753        const content = element.startSourceSpan.start.file.content;
28754        const innerText = content.slice(innerTextStart, innerTextEnd);
28755        this._unitMlString = innerText;
28756        break;
28757
28758      case _FILE_TAG:
28759        const localeAttr = element.attrs.find(attr => attr.name === 'target-language');
28760
28761        if (localeAttr) {
28762          this._locale = localeAttr.value;
28763        }
28764
28765        visitAll(this, element.children, null);
28766        break;
28767
28768      default:
28769        // TODO(vicb): assert file structure, xliff version
28770        // For now only recurse on unhandled nodes
28771        visitAll(this, element.children, null);
28772    }
28773  }
28774
28775  visitAttribute(attribute, context) {}
28776
28777  visitText(text, context) {}
28778
28779  visitComment(comment, context) {}
28780
28781  visitExpansion(expansion, context) {}
28782
28783  visitExpansionCase(expansionCase, context) {}
28784
28785  _addError(node, message) {
28786    this._errors.push(new I18nError(node.sourceSpan, message));
28787  }
28788
28789} // Convert ml nodes (xliff syntax) to i18n nodes
28790
28791
28792class XmlToI18n$2 {
28793  convert(message, url) {
28794    const xmlIcu = new XmlParser().parse(message, url, {
28795      tokenizeExpansionForms: true
28796    });
28797    this._errors = xmlIcu.errors;
28798    const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : [].concat(...visitAll(this, xmlIcu.rootNodes));
28799    return {
28800      i18nNodes: i18nNodes,
28801      errors: this._errors
28802    };
28803  }
28804
28805  visitText(text, context) {
28806    return new Text$2(text.value, text.sourceSpan);
28807  }
28808
28809  visitElement(el, context) {
28810    if (el.name === _PLACEHOLDER_TAG$2) {
28811      const nameAttr = el.attrs.find(attr => attr.name === 'id');
28812
28813      if (nameAttr) {
28814        return new Placeholder('', nameAttr.value, el.sourceSpan);
28815      }
28816
28817      this._addError(el, `<${_PLACEHOLDER_TAG$2}> misses the "id" attribute`);
28818
28819      return null;
28820    }
28821
28822    if (el.name === _MARKER_TAG$1) {
28823      return [].concat(...visitAll(this, el.children));
28824    }
28825
28826    this._addError(el, `Unexpected tag`);
28827
28828    return null;
28829  }
28830
28831  visitExpansion(icu, context) {
28832    const caseMap = {};
28833    visitAll(this, icu.cases).forEach(c => {
28834      caseMap[c.value] = new Container(c.nodes, icu.sourceSpan);
28835    });
28836    return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan);
28837  }
28838
28839  visitExpansionCase(icuCase, context) {
28840    return {
28841      value: icuCase.value,
28842      nodes: visitAll(this, icuCase.expression)
28843    };
28844  }
28845
28846  visitComment(comment, context) {}
28847
28848  visitAttribute(attribute, context) {}
28849
28850  _addError(node, message) {
28851    this._errors.push(new I18nError(node.sourceSpan, message));
28852  }
28853
28854}
28855
28856function getCtypeForTag(tag) {
28857  switch (tag.toLowerCase()) {
28858    case 'br':
28859      return 'lb';
28860
28861    case 'img':
28862      return 'image';
28863
28864    default:
28865      return `x-${tag}`;
28866  }
28867}
28868/**
28869 * @license
28870 * Copyright Google LLC All Rights Reserved.
28871 *
28872 * Use of this source code is governed by an MIT-style license that can be
28873 * found in the LICENSE file at https://angular.io/license
28874 */
28875
28876
28877const _VERSION = '2.0';
28878const _XMLNS = 'urn:oasis:names:tc:xliff:document:2.0'; // TODO(vicb): make this a param (s/_/-/)
28879
28880const _DEFAULT_SOURCE_LANG = 'en';
28881const _PLACEHOLDER_TAG$1 = 'ph';
28882const _PLACEHOLDER_SPANNING_TAG = 'pc';
28883const _MARKER_TAG = 'mrk';
28884const _XLIFF_TAG = 'xliff';
28885const _SOURCE_TAG = 'source';
28886const _TARGET_TAG = 'target';
28887const _UNIT_TAG = 'unit'; // https://docs.oasis-open.org/xliff/xliff-core/v2.0/os/xliff-core-v2.0-os.html
28888
28889class Xliff2 extends Serializer {
28890  write(messages, locale) {
28891    const visitor = new _WriteVisitor();
28892    const units = [];
28893    messages.forEach(message => {
28894      const unit = new Tag(_UNIT_TAG, {
28895        id: message.id
28896      });
28897      const notes = new Tag('notes');
28898
28899      if (message.description || message.meaning) {
28900        if (message.description) {
28901          notes.children.push(new CR(8), new Tag('note', {
28902            category: 'description'
28903          }, [new Text$1(message.description)]));
28904        }
28905
28906        if (message.meaning) {
28907          notes.children.push(new CR(8), new Tag('note', {
28908            category: 'meaning'
28909          }, [new Text$1(message.meaning)]));
28910        }
28911      }
28912
28913      message.sources.forEach(source => {
28914        notes.children.push(new CR(8), new Tag('note', {
28915          category: 'location'
28916        }, [new Text$1(`${source.filePath}:${source.startLine}${source.endLine !== source.startLine ? ',' + source.endLine : ''}`)]));
28917      });
28918      notes.children.push(new CR(6));
28919      unit.children.push(new CR(6), notes);
28920      const segment = new Tag('segment');
28921      segment.children.push(new CR(8), new Tag(_SOURCE_TAG, {}, visitor.serialize(message.nodes)), new CR(6));
28922      unit.children.push(new CR(6), segment, new CR(4));
28923      units.push(new CR(4), unit);
28924    });
28925    const file = new Tag('file', {
28926      'original': 'ng.template',
28927      id: 'ngi18n'
28928    }, [...units, new CR(2)]);
28929    const xliff = new Tag(_XLIFF_TAG, {
28930      version: _VERSION,
28931      xmlns: _XMLNS,
28932      srcLang: locale || _DEFAULT_SOURCE_LANG
28933    }, [new CR(2), file, new CR()]);
28934    return serialize([new Declaration({
28935      version: '1.0',
28936      encoding: 'UTF-8'
28937    }), new CR(), xliff, new CR()]);
28938  }
28939
28940  load(content, url) {
28941    // xliff to xml nodes
28942    const xliff2Parser = new Xliff2Parser();
28943    const {
28944      locale,
28945      msgIdToHtml,
28946      errors
28947    } = xliff2Parser.parse(content, url); // xml nodes to i18n nodes
28948
28949    const i18nNodesByMsgId = {};
28950    const converter = new XmlToI18n$1();
28951    Object.keys(msgIdToHtml).forEach(msgId => {
28952      const {
28953        i18nNodes,
28954        errors: e
28955      } = converter.convert(msgIdToHtml[msgId], url);
28956      errors.push(...e);
28957      i18nNodesByMsgId[msgId] = i18nNodes;
28958    });
28959
28960    if (errors.length) {
28961      throw new Error(`xliff2 parse errors:\n${errors.join('\n')}`);
28962    }
28963
28964    return {
28965      locale: locale,
28966      i18nNodesByMsgId
28967    };
28968  }
28969
28970  digest(message) {
28971    return decimalDigest(message);
28972  }
28973
28974}
28975
28976class _WriteVisitor {
28977  visitText(text, context) {
28978    return [new Text$1(text.value)];
28979  }
28980
28981  visitContainer(container, context) {
28982    const nodes = [];
28983    container.children.forEach(node => nodes.push(...node.visit(this)));
28984    return nodes;
28985  }
28986
28987  visitIcu(icu, context) {
28988    const nodes = [new Text$1(`{${icu.expressionPlaceholder}, ${icu.type}, `)];
28989    Object.keys(icu.cases).forEach(c => {
28990      nodes.push(new Text$1(`${c} {`), ...icu.cases[c].visit(this), new Text$1(`} `));
28991    });
28992    nodes.push(new Text$1(`}`));
28993    return nodes;
28994  }
28995
28996  visitTagPlaceholder(ph, context) {
28997    const type = getTypeForTag(ph.tag);
28998
28999    if (ph.isVoid) {
29000      const tagPh = new Tag(_PLACEHOLDER_TAG$1, {
29001        id: (this._nextPlaceholderId++).toString(),
29002        equiv: ph.startName,
29003        type: type,
29004        disp: `<${ph.tag}/>`
29005      });
29006      return [tagPh];
29007    }
29008
29009    const tagPc = new Tag(_PLACEHOLDER_SPANNING_TAG, {
29010      id: (this._nextPlaceholderId++).toString(),
29011      equivStart: ph.startName,
29012      equivEnd: ph.closeName,
29013      type: type,
29014      dispStart: `<${ph.tag}>`,
29015      dispEnd: `</${ph.tag}>`
29016    });
29017    const nodes = [].concat(...ph.children.map(node => node.visit(this)));
29018
29019    if (nodes.length) {
29020      nodes.forEach(node => tagPc.children.push(node));
29021    } else {
29022      tagPc.children.push(new Text$1(''));
29023    }
29024
29025    return [tagPc];
29026  }
29027
29028  visitPlaceholder(ph, context) {
29029    const idStr = (this._nextPlaceholderId++).toString();
29030    return [new Tag(_PLACEHOLDER_TAG$1, {
29031      id: idStr,
29032      equiv: ph.name,
29033      disp: `{{${ph.value}}}`
29034    })];
29035  }
29036
29037  visitIcuPlaceholder(ph, context) {
29038    const cases = Object.keys(ph.value.cases).map(value => value + ' {...}').join(' ');
29039    const idStr = (this._nextPlaceholderId++).toString();
29040    return [new Tag(_PLACEHOLDER_TAG$1, {
29041      id: idStr,
29042      equiv: ph.name,
29043      disp: `{${ph.value.expression}, ${ph.value.type}, ${cases}}`
29044    })];
29045  }
29046
29047  serialize(nodes) {
29048    this._nextPlaceholderId = 0;
29049    return [].concat(...nodes.map(node => node.visit(this)));
29050  }
29051
29052} // Extract messages as xml nodes from the xliff file
29053
29054
29055class Xliff2Parser {
29056  constructor() {
29057    this._locale = null;
29058  }
29059
29060  parse(xliff, url) {
29061    this._unitMlString = null;
29062    this._msgIdToHtml = {};
29063    const xml = new XmlParser().parse(xliff, url);
29064    this._errors = xml.errors;
29065    visitAll(this, xml.rootNodes, null);
29066    return {
29067      msgIdToHtml: this._msgIdToHtml,
29068      errors: this._errors,
29069      locale: this._locale
29070    };
29071  }
29072
29073  visitElement(element, context) {
29074    switch (element.name) {
29075      case _UNIT_TAG:
29076        this._unitMlString = null;
29077        const idAttr = element.attrs.find(attr => attr.name === 'id');
29078
29079        if (!idAttr) {
29080          this._addError(element, `<${_UNIT_TAG}> misses the "id" attribute`);
29081        } else {
29082          const id = idAttr.value;
29083
29084          if (this._msgIdToHtml.hasOwnProperty(id)) {
29085            this._addError(element, `Duplicated translations for msg ${id}`);
29086          } else {
29087            visitAll(this, element.children, null);
29088
29089            if (typeof this._unitMlString === 'string') {
29090              this._msgIdToHtml[id] = this._unitMlString;
29091            } else {
29092              this._addError(element, `Message ${id} misses a translation`);
29093            }
29094          }
29095        }
29096
29097        break;
29098
29099      case _SOURCE_TAG:
29100        // ignore source message
29101        break;
29102
29103      case _TARGET_TAG:
29104        const innerTextStart = element.startSourceSpan.end.offset;
29105        const innerTextEnd = element.endSourceSpan.start.offset;
29106        const content = element.startSourceSpan.start.file.content;
29107        const innerText = content.slice(innerTextStart, innerTextEnd);
29108        this._unitMlString = innerText;
29109        break;
29110
29111      case _XLIFF_TAG:
29112        const localeAttr = element.attrs.find(attr => attr.name === 'trgLang');
29113
29114        if (localeAttr) {
29115          this._locale = localeAttr.value;
29116        }
29117
29118        const versionAttr = element.attrs.find(attr => attr.name === 'version');
29119
29120        if (versionAttr) {
29121          const version = versionAttr.value;
29122
29123          if (version !== '2.0') {
29124            this._addError(element, `The XLIFF file version ${version} is not compatible with XLIFF 2.0 serializer`);
29125          } else {
29126            visitAll(this, element.children, null);
29127          }
29128        }
29129
29130        break;
29131
29132      default:
29133        visitAll(this, element.children, null);
29134    }
29135  }
29136
29137  visitAttribute(attribute, context) {}
29138
29139  visitText(text, context) {}
29140
29141  visitComment(comment, context) {}
29142
29143  visitExpansion(expansion, context) {}
29144
29145  visitExpansionCase(expansionCase, context) {}
29146
29147  _addError(node, message) {
29148    this._errors.push(new I18nError(node.sourceSpan, message));
29149  }
29150
29151} // Convert ml nodes (xliff syntax) to i18n nodes
29152
29153
29154class XmlToI18n$1 {
29155  convert(message, url) {
29156    const xmlIcu = new XmlParser().parse(message, url, {
29157      tokenizeExpansionForms: true
29158    });
29159    this._errors = xmlIcu.errors;
29160    const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : [].concat(...visitAll(this, xmlIcu.rootNodes));
29161    return {
29162      i18nNodes,
29163      errors: this._errors
29164    };
29165  }
29166
29167  visitText(text, context) {
29168    return new Text$2(text.value, text.sourceSpan);
29169  }
29170
29171  visitElement(el, context) {
29172    switch (el.name) {
29173      case _PLACEHOLDER_TAG$1:
29174        const nameAttr = el.attrs.find(attr => attr.name === 'equiv');
29175
29176        if (nameAttr) {
29177          return [new Placeholder('', nameAttr.value, el.sourceSpan)];
29178        }
29179
29180        this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equiv" attribute`);
29181
29182        break;
29183
29184      case _PLACEHOLDER_SPANNING_TAG:
29185        const startAttr = el.attrs.find(attr => attr.name === 'equivStart');
29186        const endAttr = el.attrs.find(attr => attr.name === 'equivEnd');
29187
29188        if (!startAttr) {
29189          this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equivStart" attribute`);
29190        } else if (!endAttr) {
29191          this._addError(el, `<${_PLACEHOLDER_TAG$1}> misses the "equivEnd" attribute`);
29192        } else {
29193          const startId = startAttr.value;
29194          const endId = endAttr.value;
29195          const nodes = [];
29196          return nodes.concat(new Placeholder('', startId, el.sourceSpan), ...el.children.map(node =>
29196 node.visit(this, null)), new Placeholder('', endId, el.sourceSpan));
29197        }
29198
29199        break;
29200
29201      case _MARKER_TAG:
29202        return [].concat(...visitAll(this, el.children));
29203
29204      default:
29205        this._addError(el, `Unexpected tag`);
29206
29207    }
29208
29209    return null;
29210  }
29211
29212  visitExpansion(icu, context) {
29213    const caseMap = {};
29214    visitAll(this, icu.cases).forEach(c => {
29215      caseMap[c.value] = new Container(c.nodes, icu.sourceSpan);
29216    });
29217    return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan);
29218  }
29219
29220  visitExpansionCase(icuCase, context) {
29221    return {
29222      value: icuCase.value,
29223      nodes: [].concat(...visitAll(this, icuCase.expression))
29224    };
29225  }
29226
29227  visitComment(comment, context) {}
29228
29229  visitAttribute(attribute, context) {}
29230
29231  _addError(node, message) {
29232    this._errors.push(new I18nError(node.sourceSpan, message));
29233  }
29234
29235}
29236
29237function getTypeForTag(tag) {
29238  switch (tag.toLowerCase()) {
29239    case 'br':
29240    case 'b':
29241    case 'i':
29242    case 'u':
29243      return 'fmt';
29244
29245    case 'img':
29246      return 'image';
29247
29248    case 'a':
29249      return 'link';
29250
29251    default:
29252      return 'other';
29253  }
29254}
29255/**
29256 * @license
29257 * Copyright Google LLC All Rights Reserved.
29258 *
29259 * Use of this source code is governed by an MIT-style license that can be
29260 * found in the LICENSE file at https://angular.io/license
29261 */
29262
29263
29264const _TRANSLATIONS_TAG = 'translationbundle';
29265const _TRANSLATION_TAG = 'translation';
29266const _PLACEHOLDER_TAG = 'ph';
29267
29268class Xtb extends Serializer {
29269  write(messages, locale) {
29270    throw new Error('Unsupported');
29271  }
29272
29273  load(content, url) {
29274    // xtb to xml nodes
29275    const xtbParser = new XtbParser();
29276    const {
29277      locale,
29278      msgIdToHtml,
29279      errors
29280    } = xtbParser.parse(content, url); // xml nodes to i18n nodes
29281
29282    const i18nNodesByMsgId = {};
29283    const converter = new XmlToI18n(); // Because we should be able to load xtb files that rely on features not supported by angular,
29284    // we need to delay the conversion of html to i18n nodes so that non angular messages are not
29285    // converted
29286
29287    Object.keys(msgIdToHtml).forEach(msgId => {
29288      const valueFn = function () {
29289        const {
29290          i18nNodes,
29291          errors
29292        } = converter.convert(msgIdToHtml[msgId], url);
29293
29294        if (errors.length) {
29295          throw new Error(`xtb parse errors:\n${errors.join('\n')}`);
29296        }
29297
29298        return i18nNodes;
29299      };
29300
29301      createLazyProperty(i18nNodesByMsgId, msgId, valueFn);
29302    });
29303
29304    if (errors.length) {
29305      throw new Error(`xtb parse errors:\n${errors.join('\n')}`);
29306    }
29307
29308    return {
29309      locale: locale,
29310      i18nNodesByMsgId
29311    };
29312  }
29313
29314  digest(message) {
29315    return digest(message);
29316  }
29317
29318  createNameMapper(message) {
29319    return new SimplePlaceholderMapper(message, toPublicName);
29320  }
29321
29322}
29323
29324function createLazyProperty(messages, id, valueFn) {
29325  Object.defineProperty(messages, id, {
29326    configurable: true,
29327    enumerable: true,
29328    get: function () {
29329      const value = valueFn();
29330      Object.defineProperty(messages, id, {
29331        enumerable: true,
29332        value
29333      });
29334      return value;
29335    },
29336    set: _ => {
29337      throw new Error('Could not overwrite an XTB translation');
29338    }
29339  });
29340} // Extract messages as xml nodes from the xtb file
29341
29342
29343class XtbParser {
29344  constructor() {
29345    this._locale = null;
29346  }
29347
29348  parse(xtb, url) {
29349    this._bundleDepth = 0;
29350    this._msgIdToHtml = {}; // We can not parse the ICU messages at this point as some messages might not originate
29351    // from Angular that could not be lex'd.
29352
29353    const xml = new XmlParser().parse(xtb, url);
29354    this._errors = xml.errors;
29355    visitAll(this, xml.rootNodes);
29356    return {
29357      msgIdToHtml: this._msgIdToHtml,
29358      errors: this._errors,
29359      locale: this._locale
29360    };
29361  }
29362
29363  visitElement(element, context) {
29364    switch (element.name) {
29365      case _TRANSLATIONS_TAG:
29366        this._bundleDepth++;
29367
29368        if (this._bundleDepth > 1) {
29369          this._addError(element, `<${_TRANSLATIONS_TAG}> elements can not be nested`);
29370        }
29371
29372        const langAttr = element.attrs.find(attr => attr.name === 'lang');
29373
29374        if (langAttr) {
29375          this._locale = langAttr.value;
29376        }
29377
29378        visitAll(this, element.children, null);
29379        this._bundleDepth--;
29380        break;
29381
29382      case _TRANSLATION_TAG:
29383        const idAttr = element.attrs.find(attr => attr.name === 'id');
29384
29385        if (!idAttr) {
29386          this._addError(element, `<${_TRANSLATION_TAG}> misses the "id" attribute`);
29387        } else {
29388          const id = idAttr.value;
29389
29390          if (this._msgIdToHtml.hasOwnProperty(id)) {
29391            this._addError(element, `Duplicated translations for msg ${id}`);
29392          } else {
29393            const innerTextStart = element.startSourceSpan.end.offset;
29394            const innerTextEnd = element.endSourceSpan.start.offset;
29395            const content = element.startSourceSpan.start.file.content;
29396            const innerText = content.slice(innerTextStart, innerTextEnd);
29397            this._msgIdToHtml[id] = innerText;
29398          }
29399        }
29400
29401        break;
29402
29403      default:
29404        this._addError(element, 'Unexpected tag');
29405
29406    }
29407  }
29408
29409  visitAttribute(attribute, context) {}
29410
29411  visitText(text, context) {}
29412
29413  visitComment(comment, context) {}
29414
29415  visitExpansion(expansion, context) {}
29416
29417  visitExpansionCase(expansionCase, context) {}
29418
29419  _addError(node, message) {
29420    this._errors.push(new I18nError(node.sourceSpan, message));
29421  }
29422
29423} // Convert ml nodes (xtb syntax) to i18n nodes
29424
29425
29426class XmlToI18n {
29427  convert(message, url) {
29428    const xmlIcu = new XmlParser().parse(message, url, {
29429      tokenizeExpansionForms: true
29430    });
29431    this._errors = xmlIcu.errors;
29432    const i18nNodes = this._errors.length > 0 || xmlIcu.rootNodes.length == 0 ? [] : visitAll(this, xmlIcu.rootNodes);
29433    return {
29434      i18nNodes,
29435      errors: this._errors
29436    };
29437  }
29438
29439  visitText(text, context) {
29440    return new Text$2(text.value, text.sourceSpan);
29441  }
29442
29443  visitExpansion(icu, context) {
29444    const caseMap = {};
29445    visitAll(this, icu.cases).forEach(c => {
29446      caseMap[c.value] = new Container(c.nodes, icu.sourceSpan);
29447    });
29448    return new Icu(icu.switchValue, icu.type, caseMap, icu.sourceSpan);
29449  }
29450
29451  visitExpansionCase(icuCase, context) {
29452    return {
29453      value: icuCase.value,
29454      nodes: visitAll(this, icuCase.expression)
29455    };
29456  }
29457
29458  visitElement(el, context) {
29459    if (el.name === _PLACEHOLDER_TAG) {
29460      const nameAttr = el.attrs.find(attr => attr.name === 'name');
29461
29462      if (nameAttr) {
29463        return new Placeholder('', nameAttr.value, el.sourceSpan);
29464      }
29465
29466      this._addError(el, `<${_PLACEHOLDER_TAG}> misses the "name" attribute`);
29467    } else {
29468      this._addError(el, `Unexpected tag`);
29469    }
29470
29471    return null;
29472  }
29473
29474  visitComment(comment, context) {}
29475
29476  visitAttribute(attribute, context) {}
29477
29478  _addError(node, message) {
29479    this._errors.push(new I18nError(node.sourceSpan, message));
29480  }
29481
29482}
29483/**
29484 * @license
29485 * Copyright Google LLC All Rights Reserved.
29486 *
29487 * Use of this source code is governed by an MIT-style license that can be
29488 * found in the LICENSE file at https://angular.io/license
29489 */
29490
29491/**
29492 * A container for translated messages
29493 */
29494
29495
29496class TranslationBundle {
29497  constructor(_i18nNodesByMsgId = {}, locale, digest, mapperFactory, missingTranslationStrategy = MissingTranslationStrategy.Warning, console) {
29498    this._i18nNodesByMsgId = _i18nNodesByMsgId;
29499    this.digest = digest;
29500    this.mapperFactory = mapperFactory;
29501    this._i18nToHtml = new I18nToHtmlVisitor(_i18nNodesByMsgId, locale, digest, mapperFactory, missingTranslationStrategy, console);
29502  } // Creates a `TranslationBundle` by parsing the given `content` with the `serializer`.
29503
29504
29505  static load(content, url, serializer, missingTranslationStrategy, console) {
29506    const {
29507      locale,
29508      i18nNodesByMsgId
29509    } = serializer.load(content, url);
29510
29511    const digestFn = m => serializer.digest(m);
29512
29513    const mapperFactory = m => serializer.createNameMapper(m);
29514
29515    return new TranslationBundle(i18nNodesByMsgId, locale, digestFn, mapperFactory, missingTranslationStrategy, console);
29516  } // Returns the translation as HTML nodes from the given source message.
29517
29518
29519  get(srcMsg) {
29520    const html = this._i18nToHtml.convert(srcMsg);
29521
29522    if (html.errors.length) {
29523      throw new Error(html.errors.join('\n'));
29524    }
29525
29526    return html.nodes;
29527  }
29528
29529  has(srcMsg) {
29530    return this.digest(srcMsg) in this._i18nNodesByMsgId;
29531  }
29532
29533}
29534
29535class I18nToHtmlVisitor {
29536  constructor(_i18nNodesByMsgId = {}, _locale, _digest, _mapperFactory, _missingTranslationStrategy, _console) {
29537    this._i18nNodesByMsgId = _i18nNodesByMsgId;
29538    this._locale = _locale;
29539    this._digest = _digest;
29540    this._mapperFactory = _mapperFactory;
29541    this._missingTranslationStrategy = _missingTranslationStrategy;
29542    this._console = _console;
29543    this._contextStack = [];
29544    this._errors = [];
29545  }
29546
29547  convert(srcMsg) {
29548    this._contextStack.length = 0;
29549    this._errors.length = 0; // i18n to text
29550
29551    const text = this._convertToText(srcMsg); // text to html
29552
29553
29554    const url = srcMsg.nodes[0].sourceSpan.start.file.url;
29555    const html = new HtmlParser().parse(text, url, {
29556      tokenizeExpansionForms: true
29557    });
29558    return {
29559      nodes: html.rootNodes,
29560      errors: [...this._errors, ...html.errors]
29561    };
29562  }
29563
29564  visitText(text, context) {
29565    // `convert()` uses an `HtmlParser` to return `html.Node`s
29566    // we should then make sure that any special characters are escaped
29567    return escapeXml(text.value);
29568  }
29569
29570  visitContainer(container, context) {
29571    return container.children.map(n => n.visit(this)).join('');
29572  }
29573
29574  visitIcu(icu, context) {
29575    const cases = Object.keys(icu.cases).map(k => `${k} {${icu.cases[k].visit(this)}}`); // TODO(vicb): Once all format switch to using expression placeholders
29576    // we should throw when the placeholder is not in the source message
29577
29578    const exp = this._srcMsg.placeholders.hasOwnProperty(icu.expression) ? this._srcMsg.placeholders[icu.expression].text : icu.expression;
29579    return `{${exp}, ${icu.type}, ${cases.join(' ')}}`;
29580  }
29581
29582  visitPlaceholder(ph, context) {
29583    const phName = this._mapper(ph.name);
29584
29585    if (this._srcMsg.placeholders.hasOwnProperty(phName)) {
29586      return this._srcMsg.placeholders[phName].text;
29587    }
29588
29589    if (this._srcMsg.placeholderToMessage.hasOwnProperty(phName)) {
29590      return this._convertToText(this._srcMsg.placeholderToMessage[phName]);
29591    }
29592
29593    this._addError(ph, `Unknown placeholder "${ph.name}"`);
29594
29595    return '';
29596  } // Loaded message contains only placeholders (vs tag and icu placeholders).
29597  // However when a translation can not be found, we need to serialize the source message
29598  // which can contain tag placeholders
29599
29600
29601  visitTagPlaceholder(ph, context) {
29602    const tag = `${ph.tag}`;
29603    const attrs = Object.keys(ph.attrs).map(name => `${name}="${ph.attrs[name]}"`).join(' ');
29604
29605    if (ph.isVoid) {
29606      return `<${tag} ${attrs}/>`;
29607    }
29608
29609    const children = ph.children.map(c => c.visit(this)).join('');
29610    return `<${tag} ${attrs}>${children}</${tag}>`;
29611  } // Loaded message contains only placeholders (vs tag and icu placeholders).
29612  // However when a translation can not be found, we need to serialize the source message
29613  // which can contain tag placeholders
29614
29615
29616  visitIcuPlaceholder(ph, context) {
29617    // An ICU placeholder references the source message to be serialized
29618    return this._convertToText(this._srcMsg.placeholderToMessage[ph.name]);
29619  }
29620  /**
29621   * Convert a source message to a translated text string:
29622   * - text nodes are replaced with their translation,
29623   * - placeholders are replaced with their content,
29624   * - ICU nodes are converted to ICU expressions.
29625   */
29626
29627
29628  _convertToText(srcMsg) {
29629    const id = this._digest(srcMsg);
29630
29631    const mapper = this._mapperFactory ? this._mapperFactory(srcMsg) : null;
29632    let nodes;
29633
29634    this._contextStack.push({
29635      msg: this._srcMsg,
29636      mapper: this._mapper
29637    });
29638
29639    this._srcMsg = srcMsg;
29640
29641    if (this._i18nNodesByMsgId.hasOwnProperty(id)) {
29642      // When there is a translation use its nodes as the source
29643      // And create a mapper to convert serialized placeholder names to internal names
29644      nodes = this._i18nNodesByMsgId[id];
29645
29646      this._mapper = name => mapper ? mapper.toInternalName(name) : name;
29647    } else {
29648      // When no translation has been found
29649      // - report an error / a warning / nothing,
29650      // - use the nodes from the original message
29651      // - placeholders are already internal and need no mapper
29652      if (this._missingTranslationStrategy === MissingTranslationStrategy.Error) {
29653        const ctx = this._locale ? ` for locale "${this._locale}"` : '';
29654
29655        this._addError(srcMsg.nodes[0], `Missing translation for message "${id}"${ctx}`);
29656      } else if (this._console && this._missingTranslationStrategy === MissingTranslationStrategy.Warning) {
29657        const ctx = this._locale ? ` for locale "${this._locale}"` : '';
29658
29659        this._console.warn(`Missing translation for message "${id}"${ctx}`);
29660      }
29661
29662      nodes = srcMsg.nodes;
29663
29664      this._mapper = name => name;
29665    }
29666
29667    const text = nodes.map(node => node.visit(this)).join('');
29668
29669    const context = this._contextStack.pop();
29670
29671    this._srcMsg = context.msg;
29672    this._mapper = context.mapper;
29673    return text;
29674  }
29675
29676  _addError(el, msg) {
29677    this._errors.push(new I18nError(el.sourceSpan, msg));
29678  }
29679
29680}
29681/**
29682 * @license
29683 * Copyright Google LLC All Rights Reserved.
29684 *
29685 * Use of this source code is governed by an MIT-style license that can be
29686 * found in the LICENSE file at https://angular.io/license
29687 */
29688
29689
29690class I18NHtmlParser {
29691  constructor(_htmlParser, translations, translationsFormat, missingTranslation = MissingTranslationStrategy.Warning, console) {
29692    this._htmlParser = _htmlParser;
29693
29694    if (translations) {
29695      const serializer = createSerializer(translationsFormat);
29696      this._translationBundle = TranslationBundle.load(translations, 'i18n', serializer, missingTranslation, console);
29697    } else {
29698      this._translationBundle = new TranslationBundle({}, null, digest$1, undefined, missingTranslation, console);
29699    }
29700  }
29701
29702  parse(source, url, options = {}) {
29703    const interpolationConfig = options.interpolationConfig || DEFAULT_INTERPOLATION_CONFIG;
29704
29705    const parseResult = this._htmlParser.parse(source, url, {
29706      interpolationConfig,
29707      ...options
29708    });
29709
29710    if (parseResult.errors.length) {
29711      return new ParseTreeResult(parseResult.rootNodes, parseResult.errors);
29712    }
29713
29714    return mergeTranslations(parseResult.rootNodes, this._translationBundle, interpolationConfig, [], {});
29715  }
29716
29717}
29718
29719function createSerializer(format) {
29720  format = (format || 'xlf').toLowerCase();
29721
29722  switch (format) {
29723    case 'xmb':
29724      return new Xmb();
29725
29726    case 'xtb':
29727      return new Xtb();
29728
29729    case 'xliff2':
29730    case 'xlf2':
29731      return new Xliff2();
29732
29733    case 'xliff':
29734    case 'xlf':
29735    default:
29736      return new Xliff();
29737  }
29738}
29739/**
29740 * @license
29741 * Copyright Google LLC All Rights Reserved.
29742 *
29743 * Use of this source code is governed by an MIT-style license that can be
29744 * found in the LICENSE file at https://angular.io/license
29745 */
29746
29747/**
29748 * A container for message extracted from the templates.
29749 */
29750
29751
29752class MessageBundle {
29753  constructor(_htmlParser, _implicitTags, _implicitAttrs, _locale = null) {
29754    this._htmlParser = _htmlParser;
29755    this._implicitTags = _implicitTags;
29756    this._implicitAttrs = _implicitAttrs;
29757    this._locale = _locale;
29758    this._messages = [];
29759  }
29760
29761  updateFromTemplate(html, url, interpolationConfig) {
29762    const htmlParserResult = this._htmlParser.parse(html, url, {
29763      tokenizeExpansionForms: true,
29764      interpolationConfig
29765    });
29766
29767    if (htmlParserResult.errors.length) {
29768      return htmlParserResult.errors;
29769    }
29770
29771    const i18nParserResult = extractMessages(htmlParserResult.rootNodes, interpolationConfig, this._implicitTags, this._implicitAttrs);
29772
29773    if (i18nParserResult.errors.length) {
29774      return i18nParserResult.errors;
29775    }
29776
29777    this._messages.push(...i18nParserResult.messages);
29778
29779    return [];
29780  } // Return the message in the internal format
29781  // The public (serialized) format might be different, see the `write` method.
29782
29783
29784  getMessages() {
29785    return this._messages;
29786  }
29787
29788  write(serializer, filterSources) {
29789    const messages = {};
29790    const mapperVisitor = new MapPlaceholderNames(); // Deduplicate messages based on their ID
29791
29792    this._messages.forEach(message => {
29793      const id = serializer.digest(message);
29794
29795      if (!messages.hasOwnProperty(id)) {
29796        messages[id] = message;
29797      } else {
29798        messages[id].sources.push(...message.sources);
29799      }
29800    }); // Transform placeholder names using the serializer mapping
29801
29802
29803    const msgList = Object.keys(messages).map(id => {
29804      const mapper = serializer.createNameMapper(messages[id]);
29805      const src = messages[id];
29806      const nodes = mapper ? mapperVisitor.convert(src.nodes, mapper) : src.nodes;
29807      let transformedMessage = new Message(nodes, {}, {}, src.meaning, src.description, id);
29808      transformedMessage.sources = src.sources;
29809
29810      if (filterSources) {
29811        transformedMessage.sources.forEach(source => source.filePath = filterSources(source.filePath));
29812      }
29813
29814      return transformedMessage;
29815    });
29816    return serializer.write(msgList, this._locale);
29817  }
29818
29819} // Transform an i18n AST by renaming the placeholder nodes with the given mapper
29820
29821
29822class MapPlaceholderNames extends CloneVisitor {
29823  convert(nodes, mapper) {
29824    return mapper ? nodes.map(n => n.visit(this, mapper)) : nodes;
29825  }
29826
29827  visitTagPlaceholder(ph, mapper) {
29828    const startName = mapper.toPublicName(ph.startName);
29829    const closeName = ph.closeName ? mapper.toPublicName(ph.closeName) : ph.closeName;
29830    const children = ph.children.map(n => n.visit(this, mapper));
29831    return new TagPlaceholder(ph.tag, ph.attrs, startName, closeName, children, ph.isVoid, ph.sourceSpan, ph.startSourceSpan, ph.endSourceSpan);
29832  }
29833
29834  visitPlaceholder(ph, mapper) {
29835    return new Placeholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan);
29836  }
29837
29838  visitIcuPlaceholder(ph, mapper) {
29839    return new IcuPlaceholder(ph.value, mapper.toPublicName(ph.name), ph.sourceSpan);
29840  }
29841
29842}
29843/**
29844 * @license
29845 * Copyright Google LLC All Rights Reserved.
29846 *
29847 * Use of this source code is governed by an MIT-style license that can be
29848 * found in the LICENSE file at https://angular.io/license
29849 */
29850
29851
29852var FactoryTarget;
29853
29854(function (FactoryTarget) {
29855  FactoryTarget[FactoryTarget["Directive"] = 0] = "Directive";
29856  FactoryTarget[FactoryTarget["Component"] = 1] = "Component";
29857  FactoryTarget[FactoryTarget["Injectable"] = 2] = "Injectable";
29858  FactoryTarget[FactoryTarget["Pipe"] = 3] = "Pipe";
29859  FactoryTarget[FactoryTarget["NgModule"] = 4] = "NgModule";
29860})(FactoryTarget || (FactoryTarget = {}));
29861/**
29862 * @license
29863 * Copyright Google LLC All Rights Reserved.
29864 *
29865 * Use of this source code is governed by an MIT-style license that can be
29866 * found in the LICENSE file at https://angular.io/license
29867 */
29868
29869/**
29870 * @license
29871 * Copyright Google LLC All Rights Reserved.
29872 *
29873 * Use of this source code is governed by an MIT-style license that can be
29874 * found in the LICENSE file at https://angular.io/license
29875 */
29876
29877/**
29878 * Processes `Target`s with a given set of directives and performs a binding operation, which
29879 * returns an object similar to TypeScript's `ts.TypeChecker` that contains knowledge about the
29880 * target.
29881 */
29882
29883
29884class R3TargetBinder {
29885  constructor(directiveMatcher) {
29886    this.directiveMatcher = directiveMatcher;
29887  }
29888  /**
29889   * Perform a binding operation on the given `Target` and return a `BoundTarget` which contains
29890   * metadata about the types referenced in the template.
29891   */
29892
29893
29894  bind(target) {
29895    if (!target.template) {
29896      // TODO(alxhub): handle targets which contain things like HostBindings, etc.
29897      throw new Error('Binding without a template not yet supported');
29898    } // First, parse the template into a `Scope` structure. This operation captures the syntactic
29899    // scopes in the template and makes them available for later use.
29900
29901
29902    const scope = Scope.apply(target.template); // Use the `Scope` to extract the entities present at every level of the template.
29903
29904    const templateEntities = extractTemplateEntities(scope); // Next, perform directive matching on the template using the `DirectiveBinder`. This returns:
29905    //   - directives: Map of nodes (elements & ng-templates) to the directives on them.
29906    //   - bindings: Map of inputs, outputs, and attributes to the directive/element that claims
29907    //     them. TODO(alxhub): handle multiple directives claiming an input/output/etc.
29908    //   - references: Map of #references to their targets.
29909
29910    const {
29911      directives,
29912      bindings,
29913      references
29914    } = DirectiveBinder.apply(target.template, this.directiveMatcher); // Finally, run the TemplateBinder to bind references, variables, and other entities within the
29915    // template. This extracts all the metadata that doesn't depend on directive matching.
29916
29917    const {
29918      expressions,
29919      symbols,
29920      nestingLevel,
29921      usedPipes
29922    } = TemplateBinder.applyWithScope(target.template, scope);
29923    return new R3BoundTarget(target, directives, bindings, references, expressions, symbols, nestingLevel, templateEntities, usedPipes);
29924  }
29925
29926}
29927/**
29928 * Represents a binding scope within a template.
29929 *
29930 * Any variables, references, or other named entities declared within the template will
29931 * be captured and available by name in `namedEntities`. Additionally, child templates will
29932 * be analyzed and have their child `Scope`s available in `childScopes`.
29933 */
29934
29935
29936class Scope {
29937  constructor(parentScope, template) {
29938    this.parentScope = parentScope;
29939    this.template = template;
29940    /**
29941     * Named members of the `Scope`, such as `Reference`s or `Variable`s.
29942     */
29943
29944    this.namedEntities = new Map();
29945    /**
29946     * Child `Scope`s for immediately nested `Template`s.
29947     */
29948
29949    this.childScopes = new Map();
29950  }
29951
29952  static newRootScope() {
29953    return new Scope(null, null);
29954  }
29955  /**
29956   * Process a template (either as a `Template` sub-template with variables, or a plain array of
29957   * template `Node`s) and construct its `Scope`.
29958   */
29959
29960
29961  static apply(template) {
29962    const scope = Scope.newRootScope();
29963    scope.ingest(template);
29964    return scope;
29965  }
29966  /**
29967   * Internal method to process the template and populate the `Scope`.
29968   */
29969
29970
29971  ingest(template) {
29972    if (template instanceof Template) {
29973      // Variables on an <ng-template> are defined in the inner scope.
29974      template.variables.forEach(node => this.visitVariable(node)); // Process the nodes of the template.
29975
29976      template.children.forEach(node => node.visit(this));
29977    } else {
29978      // No overarching `Template` instance, so process the nodes directly.
29979      template.forEach(node => node.visit(this));
29980    }
29981  }
29982
29983  visitElement(element) {
29984    // `Element`s in the template may have `Reference`s which are captured in the scope.
29985    element.references.forEach(node => this.visitReference(node)); // Recurse into the `Element`'s children.
29986
29987    element.children.forEach(node => node.visit(this));
29988  }
29989
29990  visitTemplate(template) {
29991    // References on a <ng-template> are defined in the outer scope, so capture them before
29992    // processing the template's child scope.
29993    template.references.forEach(node => this.visitReference(node)); // Next, create an inner scope and process the template within it.
29994
29995    const scope = new Scope(this, template);
29996    scope.ingest(template);
29997    this.childScopes.set(template, scope);
29998  }
29999
30000  visitVariable(variable) {
30001    // Declare the variable if it's not already.
30002    this.maybeDeclare(variable);
30003  }
30004
30005  visitReference(reference) {
30006    // Declare the variable if it's not already.
30007    this.maybeDeclare(reference);
30008  } // Unused visitors.
30009
30010
30011  visitContent(content) {}
30012
30013  visitBoundAttribute(attr) {}
30014
30015  visitBoundEvent(event) {}
30016
30017  visitBoundText(text) {}
30018
30019  visitText(text) {}
30020
30021  visitTextAttribute(attr) {}
30022
30023  visitIcu(icu) {}
30024
30025  maybeDeclare(thing) {
30026    // Declare something with a name, as long as that name isn't taken.
30027    if (!this.namedEntities.has(thing.name)) {
30028      this.namedEntities.set(thing.name, thing);
30029    }
30030  }
30031  /**
30032   * Look up a variable within this `Scope`.
30033   *
30034   * This can recurse into a parent `Scope` if it's available.
30035   */
30036
30037
30038  lookup(name) {
30039    if (this.namedEntities.has(name)) {
30040      // Found in the local scope.
30041      return this.namedEntities.get(name);
30042    } else if (this.parentScope !== null) {
30043      // Not in the local scope, but there's a parent scope so check there.
30044      return this.parentScope.lookup(name);
30045    } else {
30046      // At the top level and it wasn't found.
30047      return null;
30048    }
30049  }
30050  /**
30051   * Get the child scope for a `Template`.
30052   *
30053   * This should always be defined.
30054   */
30055
30056
30057  getChildScope(template) {
30058    const res = this.childScopes.get(template);
30059
30060    if (res === undefined) {
30061      throw new Error(`Assertion error: child scope for ${template} not found`);
30062    }
30063
30064    return res;
30065  }
30066
30067}
30068/**
30069 * Processes a template and matches directives on nodes (elements and templates).
30070 *
30071 * Usually used via the static `apply()` method.
30072 */
30073
30074
30075class DirectiveBinder {
30076  constructor(matcher, directives, bindings, references) {
30077    this.matcher = matcher;
30078    this.directives = directives;
30079    this.bindings = bindings;
30080    this.references = references;
30081  }
30082  /**
30083   * Process a template (list of `Node`s) and perform directive matching against each node.
30084   *
30085   * @param template the list of template `Node`s to match (recursively).
30086   * @param selectorMatcher a `SelectorMatcher` containing the directives that are in scope for
30087   * this template.
30088   * @returns three maps which contain information about directives in the template: the
30089   * `directives` map which lists directives matched on each node, the `bindings` map which
30090   * indicates which directives claimed which bindings (inputs, outputs, etc), and the `references`
30091   * map which resolves #references (`Reference`s) within the template to the named directive or
30092   * template node.
30093   */
30094
30095
30096  static apply(template, selectorMatcher) {
30097    const directives = new Map();
30098    const bindings = new Map();
30099    const references = new Map();
30100    const matcher = new DirectiveBinder(selectorMatcher, directives, bindings, references);
30101    matcher.ingest(template);
30102    return {
30103      directives,
30104      bindings,
30105      references
30106    };
30107  }
30108
30109  ingest(template) {
30110    template.forEach(node =>
30110 node.visit(this));
30111  }
30112
30113  visitElement(element) {
30114    this.visitElementOrTemplate(element.name, element);
30115  }
30116
30117  visitTemplate(template) {
30118    this.visitElementOrTemplate('ng-template', template);
30119  }
30120
30121  visitElementOrTemplate(elementName, node) {
30122    // First, determine the HTML shape of the node for the purpose of directive matching.
30123    // Do this by building up a `CssSelector` for the node.
30124    const cssSelector = createCssSelector(elementName, getAttrsForDirectiveMatching(node)); // Next, use the `SelectorMatcher` to get the list of directives on the node.
30125
30126    const directives = [];
30127    this.matcher.match(cssSelector, (_, directive) => directives.push(directive));
30128
30129    if (directives.length > 0) {
30130      this.directives.set(node, directives);
30131    } // Resolve any references that are created on this node.
30132
30133
30134    node.references.forEach(ref => {
30135      let dirTarget = null; // If the reference expression is empty, then it matches the "primary" directive on the node
30136      // (if there is one). Otherwise it matches the host node itself (either an element or
30137      // <ng-template> node).
30138
30139      if (ref.value.trim() === '') {
30140        // This could be a reference to a component if there is one.
30141        dirTarget = directives.find(dir => dir.isComponent) || null;
30142      } else {
30143        // This should be a reference to a directive exported via exportAs.
30144        dirTarget = directives.find(dir => dir.exportAs !== null && dir.exportAs.some(value => value === ref.value)) || null; // Check if a matching directive was found.
30145
30146        if (dirTarget === null) {
30147          // No matching directive was found - this reference points to an unknown target. Leave it
30148          // unmapped.
30149          return;
30150        }
30151      }
30152
30153      if (dirTarget !== null) {
30154        // This reference points to a directive.
30155        this.references.set(ref, {
30156          directive: dirTarget,
30157          node
30158        });
30159      } else {
30160        // This reference points to the node itself.
30161        this.references.set(ref, node);
30162      }
30163    });
30164
30165    const setAttributeBinding = (attribute, ioType) => {
30166      const dir = directives.find(dir => dir[ioType].hasBindingPropertyName(attribute.name));
30167      const binding = dir !== undefined ? dir : node;
30168      this.bindings.set(attribute, binding);
30169    }; // Node inputs (bound attributes) and text attributes can be bound to an
30170    // input on a directive.
30171
30172
30173    node.inputs.forEach(input => setAttributeBinding(input, 'inputs'));
30174    node.attributes.forEach(attr => setAttributeBinding(attr, 'inputs'));
30175
30176    if (node instanceof Template) {
30177      node.templateAttrs.forEach(attr => setAttributeBinding(attr, 'inputs'));
30178    } // Node outputs (bound events) can be bound to an output on a directive.
30179
30180
30181    node.outputs.forEach(output => setAttributeBinding(output, 'outputs')); // Recurse into the node's children.
30182
30183    node.children.forEach(child => child.visit(this));
30184  } // Unused visitors.
30185
30186
30187  visitContent(content) {}
30188
30189  visitVariable(variable) {}
30190
30191  visitReference(reference) {}
30192
30193  visitTextAttribute(attribute) {}
30194
30195  visitBoundAttribute(attribute) {}
30196
30197  visitBoundEvent(attribute) {}
30198
30199  visitBoundAttributeOrEvent(node) {}
30200
30201  visitText(text) {}
30202
30203  visitBoundText(text) {}
30204
30205  visitIcu(icu) {}
30206
30207}
30208/**
30209 * Processes a template and extract metadata about expressions and symbols within.
30210 *
30211 * This is a companion to the `DirectiveBinder` that doesn't require knowledge of directives matched
30212 * within the template in order to operate.
30213 *
30214 * Expressions are visited by the superclass `RecursiveAstVisitor`, with custom logic provided
30215 * by overridden methods from that visitor.
30216 */
30217
30218
30219class TemplateBinder extends RecursiveAstVisitor {
30220  constructor(bindings, symbols, usedPipes, nestingLevel, scope, template, level) {
30221    super();
30222    this.bindings = bindings;
30223    this.symbols = symbols;
30224    this.usedPipes = usedPipes;
30225    this.nestingLevel = nestingLevel;
30226    this.scope = scope;
30227    this.template = template;
30228    this.level = level;
30229    this.pipesUsed = []; // Save a bit of processing time by constructing this closure in advance.
30230
30231    this.visitNode = node =>
30231 node.visit(this);
30232  } // This method is defined to reconcile the type of TemplateBinder since both
30233  // RecursiveAstVisitor and Visitor define the visit() method in their
30234  // interfaces.
30235
30236
30237  visit(node, context) {
30238    if (node instanceof AST) {
30239      node.visit(this, context);
30240    } else {
30241      node.visit(this);
30242    }
30243  }
30244  /**
30245   * Process a template and extract metadata about expressions and symbols within.
30246   *
30247   * @param template the nodes of the template to process
30248   * @param scope the `Scope` of the template being processed.
30249   * @returns three maps which contain metadata about the template: `expressions` which interprets
30250   * special `AST` nodes in expressions as pointing to references or variables declared within the
30251   * template, `symbols` which maps those variables and references to the nested `Template` which
30252   * declares them, if any, and `nestingLevel` which associates each `Template` with a integer
30253   * nesting level (how many levels deep within the template structure the `Template` is), starting
30254   * at 1.
30255   */
30256
30257
30258  static applyWithScope(template, scope) {
30259    const expressions = new Map();
30260    const symbols = new Map();
30261    const nestingLevel = new Map();
30262    const usedPipes = new Set(); // The top-level template has nesting level 0.
30263
30264    const binder = new TemplateBinder(expressions, symbols, usedPipes, nestingLevel, scope, template instanceof Template ? template : null, 0);
30265    binder.ingest(template);
30266    return {
30267      expressions,
30268      symbols,
30269      nestingLevel,
30270      usedPipes
30271    };
30272  }
30273
30274  ingest(template) {
30275    if (template instanceof Template) {
30276      // For <ng-template>s, process only variables and child nodes. Inputs, outputs, templateAttrs,
30277      // and references were all processed in the scope of the containing template.
30278      template.variables.forEach(this.visitNode);
30279      template.children.forEach(this.visitNode); // Set the nesting level.
30280
30281      this.nestingLevel.set(template, this.level);
30282    } else {
30283      // Visit each node from the top-level template.
30284      template.forEach(this.visitNode);
30285    }
30286  }
30287
30288  visitElement(element) {
30289    // Visit the inputs, outputs, and children of the element.
30290    element.inputs.forEach(this.visitNode);
30291    element.outputs.forEach(this.visitNode);
30292    element.children.forEach(this.visitNode);
30293  }
30294
30295  visitTemplate(template) {
30296    // First, visit inputs, outputs and template attributes of the template node.
30297    template.inputs.forEach(this.visitNode);
30298    template.outputs.forEach(this.visitNode);
30299    template.templateAttrs.forEach(this.visitNode); // References are also evaluated in the outer context.
30300
30301    template.references.forEach(this.visitNode); // Next, recurse into the template using its scope, and bumping the nesting level up by one.
30302
30303    const childScope = this.scope.getChildScope(template);
30304    const binder = new TemplateBinder(this.bindings, this.symbols, this.usedPipes, this.nestingLevel, childScope, template, this.level + 1);
30305    binder.ingest(template);
30306  }
30307
30308  visitVariable(variable) {
30309    // Register the `Variable` as a symbol in the current `Template`.
30310    if (this.template !== null) {
30311      this.symbols.set(variable, this.template);
30312    }
30313  }
30314
30315  visitReference(reference) {
30316    // Register the `Reference` as a symbol in the current `Template`.
30317    if (this.template !== null) {
30318      this.symbols.set(reference, this.template);
30319    }
30320  } // Unused template visitors
30321
30322
30323  visitText(text) {}
30324
30325  visitContent(content) {}
30326
30327  visitTextAttribute(attribute) {}
30328
30329  visitIcu(icu) {
30330    Object.keys(icu.vars).forEach(key => icu.vars[key].visit(this));
30331    Object.keys(icu.placeholders).forEach(key => icu.placeholders[key].visit(this));
30332  } // The remaining visitors are concerned with processing AST expressions within template bindings
30333
30334
30335  visitBoundAttribute(attribute) {
30336    attribute.value.visit(this);
30337  }
30338
30339  visitBoundEvent(event) {
30340    event.handler.visit(this);
30341  }
30342
30343  visitBoundText(text) {
30344    text.value.visit(this);
30345  }
30346
30347  visitPipe(ast, context) {
30348    this.usedPipes.add(ast.name);
30349    return super.visitPipe(ast, context);
30350  } // These five types of AST expressions can refer to expression roots, which could be variables
30351  // or references in the current scope.
30352
30353
30354  visitPropertyRead(ast, context) {
30355    this.maybeMap(context, ast, ast.name);
30356    return super.visitPropertyRead(ast, context);
30357  }
30358
30359  visitSafePropertyRead(ast, context) {
30360    this.maybeMap(context, ast, ast.name);
30361    return super.visitSafePropertyRead(ast, context);
30362  }
30363
30364  visitPropertyWrite(ast, context) {
30365    this.maybeMap(context, ast, ast.name);
30366    return super.visitPropertyWrite(ast, context);
30367  }
30368
30369  maybeMap(scope, ast, name) {
30370    // If the receiver of the expression isn't the `ImplicitReceiver`, this isn't the root of an
30371    // `AST` expression that maps to a `Variable` or `Reference`.
30372    if (!(ast.receiver instanceof ImplicitReceiver)) {
30373      return;
30374    } // Check whether the name exists in the current scope. If so, map it. Otherwise, the name is
30375    // probably a property on the top-level component context.
30376
30377
30378    let target = this.scope.lookup(name);
30379
30380    if (target !== null) {
30381      this.bindings.set(ast, target);
30382    }
30383  }
30384
30385}
30386/**
30387 * Metadata container for a `Target` that allows queries for specific bits of metadata.
30388 *
30389 * See `BoundTarget` for documentation on the individual methods.
30390 */
30391
30392
30393class R3BoundTarget {
30394  constructor(target, directives, bindings, references, exprTargets, symbols, nestingLevel, templateEntities, usedPipes) {
30395    this.target = target;
30396    this.directives = directives;
30397    this.bindings = bindings;
30398    this.references = references;
30399    this.exprTargets = exprTargets;
30400    this.symbols = symbols;
30401    this.nestingLevel = nestingLevel;
30402    this.templateEntities = templateEntities;
30403    this.usedPipes = usedPipes;
30404  }
30405
30406  getEntitiesInTemplateScope(template) {
30407    return this.templateEntities.get(template) ?? new Set();
30408  }
30409
30410  getDirectivesOfNode(node) {
30411    return this.directives.get(node) || null;
30412  }
30413
30414  getReferenceTarget(ref) {
30415    return this.references.get(ref) || null;
30416  }
30417
30418  getConsumerOfBinding(binding) {
30419    return this.bindings.get(binding) || null;
30420  }
30421
30422  getExpressionTarget(expr) {
30423    return this.exprTargets.get(expr) || null;
30424  }
30425
30426  getTemplateOfSymbol(symbol) {
30427    return this.symbols.get(symbol) || null;
30428  }
30429
30430  getNestingLevel(template) {
30431    return this.nestingLevel.get(template) || 0;
30432  }
30433
30434  getUsedDirectives() {
30435    const set = new Set();
30436    this.directives.forEach(dirs => dirs.forEach(dir => set.add(dir)));
30437    return Array.from(set.values());
30438  }
30439
30440  getUsedPipes() {
30441    return Array.from(this.usedPipes);
30442  }
30443
30444}
30445
30446function extractTemplateEntities(rootScope) {
30447  const entityMap = new Map();
30448
30449  function extractScopeEntities(scope) {
30450    if (entityMap.has(scope.template)) {
30451      return entityMap.get(scope.template);
30452    }
30453
30454    const currentEntities = scope.namedEntities;
30455    let templateEntities;
30456
30457    if (scope.parentScope !== null) {
30458      templateEntities = new Map([...extractScopeEntities(scope.parentScope), ...currentEntities]);
30459    } else {
30460      templateEntities = new Map(currentEntities);
30461    }
30462
30463    entityMap.set(scope.template, templateEntities);
30464    return templateEntities;
30465  }
30466
30467  const scopesToProcess = [rootScope];
30468
30469  while (scopesToProcess.length > 0) {
30470    const scope = scopesToProcess.pop();
30471
30472    for (const childScope of scope.childScopes.values()) {
30473      scopesToProcess.push(childScope);
30474    }
30475
30476    extractScopeEntities(scope);
30477  }
30478
30479  const templateEntities = new Map();
30480
30481  for (const [template, entities] of entityMap) {
30482    templateEntities.set(template, new Set(entities.values()));
30483  }
30484
30485  return templateEntities;
30486}
30487/**
30488 * @license
30489 * Copyright Google LLC All Rights Reserved.
30490 *
30491 * Use of this source code is governed by an MIT-style license that can be
30492 * found in the LICENSE file at https://angular.io/license
30493 */
30494
30495
30496function compileClassMetadata(metadata) {
30497  // Generate an ngDevMode guarded call to setClassMetadata with the class identifier and its
30498  // metadata.
30499  const fnCall = importExpr(Identifiers.setClassMetadata).callFn([metadata.type, metadata.decorators, metadata.ctorParameters ?? literal(null), metadata.propDecorators ?? literal(null)]);
30500  const iife = fn([], [devOnlyGuardedExpression(fnCall).toStmt()]);
30501  return iife.callFn([]);
30502}
30503/**
30504 * @license
30505 * Copyright Google LLC All Rights Reserved.
30506 *
30507 * Use of this source code is governed by an MIT-style license that can be
30508 * found in the LICENSE file at https://angular.io/license
30509 */
30510
30511/**
30512 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
30513 * must update this constant to prevent old partial-linkers from incorrectly processing the
30514 * declaration.
30515 *
30516 * Do not include any prerelease in these versions as they are ignored.
30517 */
30518
30519
30520const MINIMUM_PARTIAL_LINKER_VERSION$6 = '12.0.0';
30521
30522function compileDeclareClassMetadata(metadata) {
30523  const definitionMap = new DefinitionMap();
30524  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$6));
30525  definitionMap.set('version', literal('14.2.12'));
30526  definitionMap.set('ngImport', importExpr(Identifiers.core));
30527  definitionMap.set('type', metadata.type);
30528  definitionMap.set('decorators', metadata.decorators);
30529  definitionMap.set('ctorParameters', metadata.ctorParameters);
30530  definitionMap.set('propDecorators', metadata.propDecorators);
30531  return importExpr(Identifiers.declareClassMetadata).callFn([definitionMap.toLiteralMap()]);
30532}
30533/**
30534 * @license
30535 * Copyright Google LLC All Rights Reserved.
30536 *
30537 * Use of this source code is governed by an MIT-style license that can be
30538 * found in the LICENSE file at https://angular.io/license
30539 */
30540
30541/**
30542 * Creates an array literal expression from the given array, mapping all values to an expression
30543 * using the provided mapping function. If the array is empty or null, then null is returned.
30544 *
30545 * @param values The array to transfer into literal array expression.
30546 * @param mapper The logic to use for creating an expression for the array's values.
30547 * @returns An array literal expression representing `values`, or null if `values` is empty or
30548 * is itself null.
30549 */
30550
30551
30552function toOptionalLiteralArray(values, mapper) {
30553  if (values === null || values.length === 0) {
30554    return null;
30555  }
30556
30557  return literalArr(values.map(value => mapper(value)));
30558}
30559/**
30560 * Creates an object literal expression from the given object, mapping all values to an expression
30561 * using the provided mapping function. If the object has no keys, then null is returned.
30562 *
30563 * @param object The object to transfer into an object literal expression.
30564 * @param mapper The logic to use for creating an expression for the object's values.
30565 * @returns An object literal expression representing `object`, or null if `object` does not have
30566 * any keys.
30567 */
30568
30569
30570function toOptionalLiteralMap(object, mapper) {
30571  const entries = Object.keys(object).map(key => {
30572    const value = object[key];
30573    return {
30574      key,
30575      value: mapper(value),
30576      quoted: true
30577    };
30578  });
30579
30580  if (entries.length > 0) {
30581    return literalMap(entries);
30582  } else {
30583    return null;
30584  }
30585}
30586
30587function compileDependencies(deps) {
30588  if (deps === 'invalid') {
30589    // The `deps` can be set to the string "invalid"  by the `unwrapConstructorDependencies()`
30590    // function, which tries to convert `ConstructorDeps` into `R3DependencyMetadata[]`.
30591    return literal('invalid');
30592  } else if (deps === null) {
30593    return literal(null);
30594  } else {
30595    return literalArr(deps.map(compileDependency));
30596  }
30597}
30598
30599function compileDependency(dep) {
30600  const depMeta = new DefinitionMap();
30601  depMeta.set('token', dep.token);
30602
30603  if (dep.attributeNameType !== null) {
30604    depMeta.set('attribute', literal(true));
30605  }
30606
30607  if (dep.host) {
30608    depMeta.set('host', literal(true));
30609  }
30610
30611  if (dep.optional) {
30612    depMeta.set('optional', literal(true));
30613  }
30614
30615  if (dep.self) {
30616    depMeta.set('self', literal(true));
30617  }
30618
30619  if (dep.skipSelf) {
30620    depMeta.set('skipSelf', literal(true));
30621  }
30622
30623  return depMeta.toLiteralMap();
30624}
30625/**
30626 * @license
30627 * Copyright Google LLC All Rights Reserved.
30628 *
30629 * Use of this source code is governed by an MIT-style license that can be
30630 * found in the LICENSE file at https://angular.io/license
30631 */
30632
30633/**
30634 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
30635 * must update this constant to prevent old partial-linkers from incorrectly processing the
30636 * declaration.
30637 *
30638 * Do not include any prerelease in these versions as they are ignored.
30639 */
30640
30641
30642const MINIMUM_PARTIAL_LINKER_VERSION$5 = '14.0.0';
30643/**
30644 * Compile a directive declaration defined by the `R3DirectiveMetadata`.
30645 */
30646
30647function compileDeclareDirectiveFromMetadata(meta) {
30648  const definitionMap = createDirectiveDefinitionMap(meta);
30649  const expression = importExpr(Identifiers.declareDirective).callFn([definitionMap.toLiteralMap()]);
30650  const type = createDirectiveType(meta);
30651  return {
30652    expression,
30653    type,
30654    statements: []
30655  };
30656}
30657/**
30658 * Gathers the declaration fields for a directive into a `DefinitionMap`. This allows for reusing
30659 * this logic for components, as they extend the directive metadata.
30660 */
30661
30662
30663function createDirectiveDefinitionMap(meta) {
30664  const definitionMap = new DefinitionMap();
30665  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$5));
30666  definitionMap.set('version', literal('14.2.12')); // e.g. `type: MyDirective`
30667
30668  definitionMap.set('type', meta.internalType);
30669
30670  if (meta.isStandalone) {
30671    definitionMap.set('isStandalone', literal(meta.isStandalone));
30672  } // e.g. `selector: 'some-dir'`
30673
30674
30675  if (meta.selector !== null) {
30676    definitionMap.set('selector', literal(meta.selector));
30677  }
30678
30679  definitionMap.set('inputs', conditionallyCreateMapObjectLiteral(meta.inputs, true));
30680  definitionMap.set('outputs', conditionallyCreateMapObjectLiteral(meta.outputs));
30681  definitionMap.set('host', compileHostMetadata(meta.host));
30682  definitionMap.set('providers', meta.providers);
30683
30684  if (meta.queries.length > 0) {
30685    definitionMap.set('queries', literalArr(meta.queries.map(compileQuery)));
30686  }
30687
30688  if (meta.viewQueries.length > 0) {
30689    definitionMap.set('viewQueries', literalArr(meta.viewQueries.map(compileQuery)));
30690  }
30691
30692  if (meta.exportAs !== null) {
30693    definitionMap.set('exportAs', asLiteral(meta.exportAs));
30694  }
30695
30696  if (meta.usesInheritance) {
30697    definitionMap.set('usesInheritance', literal(true));
30698  }
30699
30700  if (meta.lifecycle.usesOnChanges) {
30701    definitionMap.set('usesOnChanges', literal(true));
30702  }
30703
30704  definitionMap.set('ngImport', importExpr(Identifiers.core));
30705  return definitionMap;
30706}
30707/**
30708 * Compiles the metadata of a single query into its partial declaration form as declared
30709 * by `R3DeclareQueryMetadata`.
30710 */
30711
30712
30713function compileQuery(query) {
30714  const meta = new DefinitionMap();
30715  meta.set('propertyName', literal(query.propertyName));
30716
30717  if (query.first) {
30718    meta.set('first', literal(true));
30719  }
30720
30721  meta.set('predicate', Array.isArray(query.predicate) ? asLiteral(query.predicate) : convertFromMaybeForwardRefExpression(query.predicate));
30722
30723  if (!query.emitDistinctChangesOnly) {
30724    // `emitDistinctChangesOnly` is special because we expect it to be `true`.
30725    // Therefore we explicitly emit the field, and explicitly place it only when it's `false`.
30726    meta.set('emitDistinctChangesOnly', literal(false));
30727  } else {// The linker will assume that an absent `emitDistinctChangesOnly` flag is by default `true`.
30728  }
30729
30730  if (query.descendants) {
30731    meta.set('descendants', literal(true));
30732  }
30733
30734  meta.set('read', query.read);
30735
30736  if (query.static) {
30737    meta.set('static', literal(true));
30738  }
30739
30740  return meta.toLiteralMap();
30741}
30742/**
30743 * Compiles the host metadata into its partial declaration form as declared
30744 * in `R3DeclareDirectiveMetadata['host']`
30745 */
30746
30747
30748function compileHostMetadata(meta) {
30749  const hostMetadata = new DefinitionMap();
30750  hostMetadata.set('attributes', toOptionalLiteralMap(meta.attributes, expression => expression));
30751  hostMetadata.set('listeners', toOptionalLiteralMap(meta.listeners, literal));
30752  hostMetadata.set('properties', toOptionalLiteralMap(meta.properties, literal));
30753
30754  if (meta.specialAttributes.styleAttr) {
30755    hostMetadata.set('styleAttribute', literal(meta.specialAttributes.styleAttr));
30756  }
30757
30758  if (meta.specialAttributes.classAttr) {
30759    hostMetadata.set('classAttribute', literal(meta.specialAttributes.classAttr));
30760  }
30761
30762  if (hostMetadata.values.length > 0) {
30763    return hostMetadata.toLiteralMap();
30764  } else {
30765    return null;
30766  }
30767}
30768/**
30769 * @license
30770 * Copyright Google LLC All Rights Reserved.
30771 *
30772 * Use of this source code is governed by an MIT-style license that can be
30773 * found in the LICENSE file at https://angular.io/license
30774 */
30775
30776/**
30777 * Compile a component declaration defined by the `R3ComponentMetadata`.
30778 */
30779
30780
30781function compileDeclareComponentFromMetadata(meta, template, additionalTemplateInfo) {
30782  const definitionMap = createComponentDefinitionMap(meta, template, additionalTemplateInfo);
30783  const expression = importExpr(Identifiers.declareComponent).callFn([definitionMap.toLiteralMap()]);
30784  const type = createComponentType(meta);
30785  return {
30786    expression,
30787    type,
30788    statements: []
30789  };
30790}
30791/**
30792 * Gathers the declaration fields for a component into a `DefinitionMap`.
30793 */
30794
30795
30796function createComponentDefinitionMap(meta, template, templateInfo) {
30797  const definitionMap = createDirectiveDefinitionMap(meta);
30798  definitionMap.set('template', getTemplateExpression(template, templateInfo));
30799
30800  if (templateInfo.isInline) {
30801    definitionMap.set('isInline', literal(true));
30802  }
30803
30804  definitionMap.set('styles', toOptionalLiteralArray(meta.styles, literal));
30805  definitionMap.set('dependencies', compileUsedDependenciesMetadata(meta));
30806  definitionMap.set('viewProviders', meta.viewProviders);
30807  definitionMap.set('animations', meta.animations);
30808
30809  if (meta.changeDetection !== undefined) {
30810    definitionMap.set('changeDetection', importExpr(Identifiers.ChangeDetectionStrategy).prop(ChangeDetectionStrategy[meta.changeDetection]));
30811  }
30812
30813  if (meta.encapsulation !== ViewEncapsulation.Emulated) {
30814    definitionMap.set('encapsulation', importExpr(Identifiers.ViewEncapsulation).prop(ViewEncapsulation[meta.encapsulation]));
30815  }
30816
30817  if (meta.interpolation !== DEFAULT_INTERPOLATION_CONFIG) {
30818    definitionMap.set('interpolation', literalArr([literal(meta.interpolation.start), literal(meta.interpolation.end)]));
30819  }
30820
30821  if (template.preserveWhitespaces === true) {
30822    definitionMap.set('preserveWhitespaces', literal(true));
30823  }
30824
30825  return definitionMap;
30826}
30827
30828function getTemplateExpression(template, templateInfo) {
30829  // If the template has been defined using a direct literal, we use that expression directly
30830  // without any modifications. This is ensures proper source mapping from the partially
30831  // compiled code to the source file declaring the template. Note that this does not capture
30832  // template literals referenced indirectly through an identifier.
30833  if (templateInfo.inlineTemplateLiteralExpression !== null) {
30834    return templateInfo.inlineTemplateLiteralExpression;
30835  } // If the template is defined inline but not through a literal, the template has been resolved
30836  // through static interpretation. We create a literal but cannot provide any source span. Note
30837  // that we cannot use the expression defining the template because the linker expects the template
30838  // to be defined as a literal in the declaration.
30839
30840
30841  if (templateInfo.isInline) {
30842    return literal(templateInfo.content, null, null);
30843  } // The template is external so we must synthesize an expression node with
30844  // the appropriate source-span.
30845
30846
30847  const contents = templateInfo.content;
30848  const file = new ParseSourceFile(contents, templateInfo.sourceUrl);
30849  const start = new ParseLocation(file, 0, 0, 0);
30850  const end = computeEndLocation(file, contents);
30851  const span = new ParseSourceSpan(start, end);
30852  return literal(contents, null, span);
30853}
30854
30855function computeEndLocation(file, contents) {
30856  const length = contents.length;
30857  let lineStart = 0;
30858  let lastLineStart = 0;
30859  let line = 0;
30860
30861  do {
30862    lineStart = contents.indexOf('\n', lastLineStart);
30863
30864    if (lineStart !== -1) {
30865      lastLineStart = lineStart + 1;
30866      line++;
30867    }
30868  } while (lineStart !== -1);
30869
30870  return new ParseLocation(file, length, line, length - lastLineStart);
30871}
30872
30873function compileUsedDependenciesMetadata(meta) {
30874  const wrapType = meta.declarationListEmitMode !== 0
30875  /* DeclarationListEmitMode.Direct */
30876  ? generateForwardRef : expr => expr;
30877  return toOptionalLiteralArray(meta.declarations, decl => {
30878    switch (decl.kind) {
30879      case R3TemplateDependencyKind.Directive:
30880        const dirMeta = new DefinitionMap();
30881        dirMeta.set('kind', literal(decl.isComponent ? 'component' : 'directive'));
30882        dirMeta.set('type', wrapType(decl.type));
30883        dirMeta.set('selector', literal(decl.selector));
30884        dirMeta.set('inputs', toOptionalLiteralArray(decl.inputs, literal));
30885        dirMeta.set('outputs', toOptionalLiteralArray(decl.outputs, literal));
30886        dirMeta.set('exportAs', toOptionalLiteralArray(decl.exportAs, literal));
30887        return dirMeta.toLiteralMap();
30888
30889      case R3TemplateDependencyKind.Pipe:
30890        const pipeMeta = new DefinitionMap();
30891        pipeMeta.set('kind', literal('pipe'));
30892        pipeMeta.set('type', wrapType(decl.type));
30893        pipeMeta.set('name', literal(decl.name));
30894        return pipeMeta.toLiteralMap();
30895
30896      case R3TemplateDependencyKind.NgModule:
30897        const ngModuleMeta = new DefinitionMap();
30898        ngModuleMeta.set('kind', literal('ngmodule'));
30899        ngModuleMeta.set('type', wrapType(decl.type));
30900        return ngModuleMeta.toLiteralMap();
30901    }
30902  });
30903}
30904/**
30905 * @license
30906 * Copyright Google LLC All Rights Reserved.
30907 *
30908 * Use of this source code is governed by an MIT-style license that can be
30909 * found in the LICENSE file at https://angular.io/license
30910 */
30911
30912/**
30913 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
30914 * must update this constant to prevent old partial-linkers from incorrectly processing the
30915 * declaration.
30916 *
30917 * Do not include any prerelease in these versions as they are ignored.
30918 */
30919
30920
30921const MINIMUM_PARTIAL_LINKER_VERSION$4 = '12.0.0';
30922
30923function compileDeclareFactoryFunction(meta) {
30924  const definitionMap = new DefinitionMap();
30925  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$4));
30926  definitionMap.set('version', literal('14.2.12'));
30927  definitionMap.set('ngImport', importExpr(Identifiers.core));
30928  definitionMap.set('type', meta.internalType);
30929  definitionMap.set('deps', compileDependencies(meta.deps));
30930  definitionMap.set('target', importExpr(Identifiers.FactoryTarget).prop(FactoryTarget$1[meta.target]));
30931  return {
30932    expression: importExpr(Identifiers.declareFactory).callFn([definitionMap.toLiteralMap()]),
30933    statements: [],
30934    type: createFactoryType(meta)
30935  };
30936}
30937/**
30938 * @license
30939 * Copyright Google LLC All Rights Reserved.
30940 *
30941 * Use of this source code is governed by an MIT-style license that can be
30942 * found in the LICENSE file at https://angular.io/license
30943 */
30944
30945/**
30946 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
30947 * must update this constant to prevent old partial-linkers from incorrectly processing the
30948 * declaration.
30949 *
30950 * Do not include any prerelease in these versions as they are ignored.
30951 */
30952
30953
30954const MINIMUM_PARTIAL_LINKER_VERSION$3 = '12.0.0';
30955/**
30956 * Compile a Injectable declaration defined by the `R3InjectableMetadata`.
30957 */
30958
30959function compileDeclareInjectableFromMetadata(meta) {
30960  const definitionMap = createInjectableDefinitionMap(meta);
30961  const expression = importExpr(Identifiers.declareInjectable).callFn([definitionMap.toLiteralMap()]);
30962  const type = createInjectableType(meta);
30963  return {
30964    expression,
30965    type,
30966    statements: []
30967  };
30968}
30969/**
30970 * Gathers the declaration fields for a Injectable into a `DefinitionMap`.
30971 */
30972
30973
30974function createInjectableDefinitionMap(meta) {
30975  const definitionMap = new DefinitionMap();
30976  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$3));
30977  definitionMap.set('version', literal('14.2.12'));
30978  definitionMap.set('ngImport', importExpr(Identifiers.core));
30979  definitionMap.set('type', meta.internalType); // Only generate providedIn property if it has a non-null value
30980
30981  if (meta.providedIn !== undefined) {
30982    const providedIn = convertFromMaybeForwardRefExpression(meta.providedIn);
30983
30984    if (providedIn.value !== null) {
30985      definitionMap.set('providedIn', providedIn);
30986    }
30987  }
30988
30989  if (meta.useClass !== undefined) {
30990    definitionMap.set('useClass', convertFromMaybeForwardRefExpression(meta.useClass));
30991  }
30992
30993  if (meta.useExisting !== undefined) {
30994    definitionMap.set('useExisting', convertFromMaybeForwardRefExpression(meta.useExisting));
30995  }
30996
30997  if (meta.useValue !== undefined) {
30998    definitionMap.set('useValue', convertFromMaybeForwardRefExpression(meta.useValue));
30999  } // Factories do not contain `ForwardRef`s since any types are already wrapped in a function call
31000  // so the types will not be eagerly evaluated. Therefore we do not need to process this expression
31001  // with `convertFromProviderExpression()`.
31002
31003
31004  if (meta.useFactory !== undefined) {
31005    definitionMap.set('useFactory', meta.useFactory);
31006  }
31007
31008  if (meta.deps !== undefined) {
31009    definitionMap.set('deps', literalArr(meta.deps.map(compileDependency)));
31010  }
31011
31012  return definitionMap;
31013}
31014/**
31015 * @license
31016 * Copyright Google LLC All Rights Reserved.
31017 *
31018 * Use of this source code is governed by an MIT-style license that can be
31019 * found in the LICENSE file at https://angular.io/license
31020 */
31021
31022/**
31023 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
31024 * must update this constant to prevent old partial-linkers from incorrectly processing the
31025 * declaration.
31026 *
31027 * Do not include any prerelease in these versions as they are ignored.
31028 */
31029
31030
31031const MINIMUM_PARTIAL_LINKER_VERSION$2 = '12.0.0';
31032
31033function compileDeclareInjectorFromMetadata(meta) {
31034  const definitionMap = createInjectorDefinitionMap(meta);
31035  const expression = importExpr(Identifiers.declareInjector).callFn([definitionMap.toLiteralMap()]);
31036  const type = createInjectorType(meta);
31037  return {
31038    expression,
31039    type,
31040    statements: []
31041  };
31042}
31043/**
31044 * Gathers the declaration fields for an Injector into a `DefinitionMap`.
31045 */
31046
31047
31048function createInjectorDefinitionMap(meta) {
31049  const definitionMap = new DefinitionMap();
31050  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$2));
31051  definitionMap.set('version', literal('14.2.12'));
31052  definitionMap.set('ngImport', importExpr(Identifiers.core));
31053  definitionMap.set('type', meta.internalType);
31054  definitionMap.set('providers', meta.providers);
31055
31056  if (meta.imports.length > 0) {
31057    definitionMap.set('imports', literalArr(meta.imports));
31058  }
31059
31060  return definitionMap;
31061}
31062/**
31063 * @license
31064 * Copyright Google LLC All Rights Reserved.
31065 *
31066 * Use of this source code is governed by an MIT-style license that can be
31067 * found in the LICENSE file at https://angular.io/license
31068 */
31069
31070/**
31071 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
31072 * must update this constant to prevent old partial-linkers from incorrectly processing the
31073 * declaration.
31074 *
31075 * Do not include any prerelease in these versions as they are ignored.
31076 */
31077
31078
31079const MINIMUM_PARTIAL_LINKER_VERSION$1 = '14.0.0';
31080
31081function compileDeclareNgModuleFromMetadata(meta) {
31082  const definitionMap = createNgModuleDefinitionMap(meta);
31083  const expression = importExpr(Identifiers.declareNgModule).callFn([definitionMap.toLiteralMap()]);
31084  const type = createNgModuleType(meta);
31085  return {
31086    expression,
31087    type,
31088    statements: []
31089  };
31090}
31091/**
31092 * Gathers the declaration fields for an NgModule into a `DefinitionMap`.
31093 */
31094
31095
31096function createNgModuleDefinitionMap(meta) {
31097  const definitionMap = new DefinitionMap();
31098  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION$1));
31099  definitionMap.set('version', literal('14.2.12'));
31100  definitionMap.set('ngImport', importExpr(Identifiers.core));
31101  definitionMap.set('type', meta.internalType); // We only generate the keys in the metadata if the arrays contain values.
31102  // We must wrap the arrays inside a function if any of the values are a forward reference to a
31103  // not-yet-declared class. This is to support JIT execution of the `ɵɵngDeclareNgModule(
31103)` call.
31104  // In the linker these wrappers are stripped and then reapplied for the `ɵɵdefineNgModule()` call.
31105
31106  if (meta.bootstrap.length > 0) {
31107    definitionMap.set('bootstrap', refsToArray(meta.bootstrap, meta.containsForwardDecls));
31108  }
31109
31110  if (meta.declarations.length > 0) {
31111    definitionMap.set('declarations', refsToArray(meta.declarations, meta.containsForwardDecls));
31112  }
31113
31114  if (meta.imports.length > 0) {
31115    definitionMap.set('imports', refsToArray(meta.imports, meta.containsForwardDecls));
31116  }
31117
31118  if (meta.exports.length > 0) {
31119    definitionMap.set('exports', refsToArray(meta.exports, meta.containsForwardDecls));
31120  }
31121
31122  if (meta.schemas !== null && meta.schemas.length > 0) {
31123    definitionMap.set('schemas', literalArr(meta.schemas.map(ref => ref.value)));
31124  }
31125
31126  if (meta.id !== null) {
31127    definitionMap.set('id', meta.id);
31128  }
31129
31130  return definitionMap;
31131}
31132/**
31133 * @license
31134 * Copyright Google LLC All Rights Reserved.
31135 *
31136 * Use of this source code is governed by an MIT-style license that can be
31137 * found in the LICENSE file at https://angular.io/license
31138 */
31139
31140/**
31141 * Every time we make a breaking change to the declaration interface or partial-linker behavior, we
31142 * must update this constant to prevent old partial-linkers from incorrectly processing the
31143 * declaration.
31144 *
31145 * Do not include any prerelease in these versions as they are ignored.
31146 */
31147
31148
31149const MINIMUM_PARTIAL_LINKER_VERSION = '14.0.0';
31150/**
31151 * Compile a Pipe declaration defined by the `R3PipeMetadata`.
31152 */
31153
31154function compileDeclarePipeFromMetadata(meta) {
31155  const definitionMap = createPipeDefinitionMap(meta);
31156  const expression = importExpr(Identifiers.declarePipe).callFn([definitionMap.toLiteralMap()]);
31157  const type = createPipeType(meta);
31158  return {
31159    expression,
31160    type,
31161    statements: []
31162  };
31163}
31164/**
31165 * Gathers the declaration fields for a Pipe into a `DefinitionMap`.
31166 */
31167
31168
31169function createPipeDefinitionMap(meta) {
31170  const definitionMap = new DefinitionMap();
31171  definitionMap.set('minVersion', literal(MINIMUM_PARTIAL_LINKER_VERSION));
31172  definitionMap.set('version', literal('14.2.12'));
31173  definitionMap.set('ngImport', importExpr(Identifiers.core)); // e.g. `type: MyPipe`
31174
31175  definitionMap.set('type', meta.internalType);
31176
31177  if (meta.isStandalone) {
31178    definitionMap.set('isStandalone', literal(meta.isStandalone));
31179  } // e.g. `name: "myPipe"`
31180
31181
31182  definitionMap.set('name', literal(meta.pipeName));
31183
31184  if (meta.pure === false) {
31185    // e.g. `pure: false`
31186    definitionMap.set('pure', literal(meta.pure));
31187  }
31188
31189  return definitionMap;
31190}
31191/**
31192 * @license
31193 * Copyright Google LLC All Rights Reserved.
31194 *
31195 * Use of this source code is governed by an MIT-style license that can be
31196 * found in the LICENSE file at https://angular.io/license
31197 */
31198// This file only reexports content of the `src` folder. Keep it that way.
31199// This function call has a global side effects and publishes the compiler into global namespace for
31200// the late binding of the Compiler to the @angular/core for jit compilation.
31201
31202
31203publishFacade(_global);
31204/**
31205 * @license
31206 * Copyright Google LLC All Rights Reserved.
31207 *
31208 * Use of this source code is governed by an MIT-style license that can be
31209 * found in the LICENSE file at https://angular.io/license
31210 */
31211// This file only reexports content of the `src` folder. Keep it that way.
31212
31213/**
31214 * @license
31215 * Copyright Google LLC All Rights Reserved.
31216 *
31217 * Use of this source code is governed by an MIT-style license that can be
31218 * found in the LICENSE file at https://angular.io/license
31219 */
31220
31221/**
31222 * @license
31223 * Copyright Google LLC All Rights Reserved.
31224 *
31225 * Use of this source code is governed by an MIT-style license that can be
31226 * found in the LICENSE file at https://angular.io/license
31227 */
31228
31229
31230
31231/***/ }),
31232
31233/***/ 6344:
31234/*!**********************************************************!*\
31235  !*** ./node_modules/@angular/localize/fesm2020/init.mjs ***!
31236  \**********************************************************/
31237/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
31238
31239__webpack_require__.r(__webpack_exports__);
31240/* harmony export */ __webpack_require__.d(__webpack_exports__, {
31241/* harmony export */   "$localize": () => (/* reexport safe */ _angular_localize__WEBPACK_IMPORTED_MODULE_0__["ɵ$localize"])
31242/* harmony export */ });
31243/* harmony import */ var _angular_localize__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/localize */ 9321);
31244/**
31245 * @license Angular v14.2.12
31246 * (c) 2010-2022 Google LLC. https://angular.io/
31247 * License: MIT
31248 */
31249
31250
31251/**
31252 * @license
31253 * Copyright Google LLC All Rights Reserved.
31254 *
31255 * Use of this source code is governed by an MIT-style license that can be
31256 * found in the LICENSE file at https://angular.io/license
31257 */
31258// Attach $localize to the global context, as a side-effect of this module.
31259
31260_angular_localize__WEBPACK_IMPORTED_MODULE_0__["ɵ_global"].$localize = _angular_localize__WEBPACK_IMPORTED_MODULE_0__["ɵ$localize"];
31261
31262/***/ }),
31263
31264/***/ 9321:
31265/*!**************************************************************!*\
31266  !*** ./node_modules/@angular/localize/fesm2020/localize.mjs ***!
31267  \**************************************************************/
31268/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
31269
31270__webpack_require__.r(__webpack_exports__);
31271/* harmony export */ __webpack_require__.d(__webpack_exports__, {
31272/* harmony export */   "clearTranslations": () => (/* binding */ clearTranslations),
31273/* harmony export */   "loadTranslations": () => (/* binding */ loadTranslations),
31274/* harmony export */   "ɵ$localize": () => (/* binding */ $localize$1),
31275/* harmony export */   "ɵMissingTranslationError": () => (/* binding */ MissingTranslationError),
31276/* harmony export */   "ɵ_global": () => (/* binding */ _global),
31277/* harmony export */   "ɵcomputeMsgId": () => (/* reexport safe */ _angular_compiler__WEBPACK_IMPORTED_MODULE_0__.computeMsgId),
31278/* harmony export */   "ɵfindEndOfBlock": () =>
31278 (/* binding */ findEndOfBlock),
31279/* harmony export */   "ɵisMissingTranslationError": () => (/* binding */ isMissingTranslationError),
31280/* harmony export */   "ɵmakeParsedTranslation": () => (/* binding */ makeParsedTranslation),
31281/* harmony export */   "ɵmakeTemplateObject": () => (/* binding */ makeTemplateObject),
31282/* harmony export */   "ɵparseMessage": () => (/* binding */ parseMessage),
31283/* harmony export */   "ɵparseMetadata": () => (/* binding */ parseMetadata),
31284/* harmony export */   "ɵparseTranslation": () => (/* binding */ parseTranslation),
31285/* harmony export */   "ɵsplitBlock": () => (/* binding */ splitBlock),
31286/* harmony export */   "ɵtranslate": () => (/* binding */ translate$1)
31287/* harmony export */ });
31288/* harmony import */ var _angular_compiler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @angular/compiler */ 8781);
31289/**
31290 * @license Angular v14.2.12
31291 * (c) 2010-2022 Google LLC. https://angular.io/
31292 * License: MIT
31293 */
31294
31295
31296/**
31297 * @license
31298 * Copyright Google LLC All Rights Reserved.
31299 *
31300 * Use of this source code is governed by an MIT-style license that can be
31301 * found in the LICENSE file at https://angular.io/license
31302 */
31303
31304/**
31305 * The character used to mark the start and end of a "block" in a `$localize` tagged string.
31306 * A block can indicate metadata about the message or specify a name of a placeholder for a
31307 * substitution expressions.
31308 *
31309 * For example:
31310 *
31311 * ```ts
31312 * $localize`Hello, ${title}:title:!`;
31313 * $localize`:meaning|description@@id:source message text`;
31314 * ```
31315 */
31316
31317const BLOCK_MARKER$1 = ':';
31318/**
31319 * The marker used to separate a message's "meaning" from its "description" in a metadata block.
31320 *
31321 * For example:
31322 *
31323 * ```ts
31324 * $localize `:correct|Indicates that the user got the answer correct: Right!`;
31325 * $localize `:movement|Button label for moving to the right: Right!`;
31326 * ```
31327 */
31328
31329const MEANING_SEPARATOR = '|';
31330/**
31331 * The marker used to separate a message's custom "id" from its "description" in a metadata block.
31332 *
31333 * For example:
31334 *
31335 * ```ts
31336 * $localize `:A welcome message on the home page@@myApp-homepage-welcome: Welcome!`;
31337 * ```
31338 */
31339
31340const ID_SEPARATOR = '@@';
31341/**
31342 * The marker used to separate legacy message ids from the rest of a metadata block.
31343 *
31344 * For example:
31345 *
31346 * ```ts
31347 * $localize `:@@custom-id␟2df64767cd895a8fabe3e18b94b5b6b6f9e2e3f0: Welcome!`;
31348 * ```
31349 *
31350 * Note that this character is the "symbol for the unit separator" (␟) not the "unit separator
31351 * character" itself, since that has no visual representation. See https://graphemica.com/%E2%90%9F.
31352 *
31353 * Here is some background for the original "unit separator character":
31354 * https://stackoverflow.com/questions/8695118/whats-the-file-group-record-unit-separator-control-characters-and-its-usage
31355 */
31356
31357const LEGACY_ID_INDICATOR = '\u241F';
31358/**
31359 * @license
31360 * Copyright Google LLC All Rights Reserved.
31361 *
31362 * Use of this source code is governed by an MIT-style license that can be
31363 * found in the LICENSE file at https://angular.io/license
31364 */
31365
31366/**
31367 * Parse a `$localize` tagged string into a structure that can be used for translation or
31368 * extraction.
31369 *
31370 * See `ParsedMessage` for an example.
31371 */
31372
31373function parseMessage(messageParts, expressions, location, messagePartLocations, expressionLocations = []) {
31374  const substitutions = {};
31375  const substitutionLocations = {};
31376  const associatedMessageIds = {};
31377  const metadata = parseMetadata(messageParts[0], messageParts.raw[0]);
31378  const cleanedMessageParts = [metadata.text];
31379  const placeholderNames = [];
31380  let messageString = metadata.text;
31381
31382  for (let i = 1; i < messageParts.length; i++) {
31383    const {
31384      messagePart,
31385      placeholderName = computePlaceholderName(i),
31386      associatedMessageId
31387    } = parsePlaceholder(messageParts[i], messageParts.raw[i]);
31388    messageString += `{$${placeholderName}}${messagePart}`;
31389
31390    if (expressions !== undefined) {
31391      substitutions[placeholderName] = expressions[i - 1];
31392      substitutionLocations[placeholderName] = expressionLocations[i - 1];
31393    }
31394
31395    placeholderNames.push(placeholderName);
31396
31397    if (associatedMessageId !== undefined) {
31398      associatedMessageIds[placeholderName] = associatedMessageId;
31399    }
31400
31401    cleanedMessageParts.push(messagePart);
31402  }
31403
31404  const messageId = metadata.customId || (0,_angular_compiler__WEBPACK_IMPORTED_MODULE_0__.computeMsgId)(messageString, metadata.meaning || '');
31405  const legacyIds = metadata.legacyIds ? metadata.legacyIds.filter(id => id !== messageId) : [];
31406  return {
31407    id: messageId,
31408    legacyIds,
31409    substitutions,
31410    substitutionLocations,
31411    text: messageString,
31412    customId: metadata.customId,
31413    meaning: metadata.meaning || '',
31414    description: metadata.description || '',
31415    messageParts: cleanedMessageParts,
31416    messagePartLocations,
31417    placeholderNames,
31418    associatedMessageIds,
31419    location
31420  };
31421}
31422/**
31423 * Parse the given message part (`cooked` + `raw`) to extract the message metadata from the text.
31424 *
31425 * If the message part has a metadata block this function will extract the `meaning`,
31426 * `description`, `customId` and `legacyId` (if provided) from the block. These metadata properties
31427 * are serialized in the string delimited by `|`, `@@` and `␟` respectively.
31428 *
31429 * (Note that `␟` is the `LEGACY_ID_INDICATOR` - see `constants.ts`.)
31430 *
31431 * For example:
31432 *
31433 * ```ts
31434 * `:meaning|description@@custom-id:`
31435 * `:meaning|@@custom-id:`
31436 * `:meaning|description:`
31437 * `:description@@custom-id:`
31438 * `:meaning|:`
31439 * `:description:`
31440 * `:@@custom-id:`
31441 * `:meaning|description@@custom-id␟legacy-id-1␟legacy-id-2:`
31442 * ```
31443 *
31444 * @param cooked The cooked version of the message part to parse.
31445 * @param raw The raw version of the message part to parse.
31446 * @returns A object containing any metadata that was parsed from the message part.
31447 */
31448
31449
31450function parseMetadata(cooked, raw) {
31451  const {
31452    text: messageString,
31453    block
31454  } = splitBlock(cooked, raw);
31455
31456  if (block === undefined) {
31457    return {
31458      text: messageString
31459    };
31460  } else {
31461    const [meaningDescAndId, ...legacyIds] = block.split(LEGACY_ID_INDICATOR);
31462    const [meaningAndDesc, customId] = meaningDescAndId.split(ID_SEPARATOR, 2);
31463    let [meaning, description] = meaningAndDesc.split(MEANING_SEPARATOR, 2);
31464
31465    if (description === undefined) {
31466      description = meaning;
31467      meaning = undefined;
31468    }
31469
31470    if (description === '') {
31471      description = undefined;
31472    }
31473
31474    return {
31475      text: messageString,
31476      meaning,
31477      description,
31478      customId,
31479      legacyIds
31480    };
31481  }
31482}
31483/**
31484 * Parse the given message part (`cooked` + `raw`) to extract any placeholder metadata from the
31485 * text.
31486 *
31487 * If the message part has a metadata block this function will extract the `placeholderName` and
31488 * `associatedMessageId` (if provided) from the block.
31489 *
31490 * These metadata properties are serialized in the string delimited by `@@`.
31491 *
31492 * For example:
31493 *
31494 * ```ts
31495 * `:placeholder-name@@associated-id:`
31496 * ```
31497 *
31498 * @param cooked The cooked version of the message part to parse.
31499 * @param raw The raw version of the message part to parse.
31500 * @returns A object containing the metadata (`placeholderName` and `associatedMessageId`) of the
31501 *     preceding placeholder, along with the static text that follows.
31502 */
31503
31504
31505function parsePlaceholder(cooked, raw) {
31506  const {
31507    text: messagePart,
31508    block
31509  } = splitBlock(cooked, raw);
31510
31511  if (block === undefined) {
31512    return {
31513      messagePart
31514    };
31515  } else {
31516    const [placeholderName, associatedMessageId] = block.split(ID_SEPARATOR);
31517    return {
31518      messagePart,
31519      placeholderName,
31520      associatedMessageId
31521    };
31522  }
31523}
31524/**
31525 * Split a message part (`cooked` + `raw`) into an optional delimited "block" off the front and the
31526 * rest of the text of the message part.
31527 *
31528 * Blocks appear at the start of message parts. They are delimited by a colon `:` character at the
31529 * start and end of the block.
31530 *
31531 * If the block is in the first message part then it will be metadata about the whole message:
31532 * meaning, description, id.  Otherwise it will be metadata about the immediately preceding
31533 * substitution: placeholder name.
31534 *
31535 * Since blocks are optional, it is possible that the content of a message block actually starts
31536 * with a block marker. In this case the marker must be escaped `\:`.
31537 *
31538 * @param cooked The cooked version of the message part to parse.
31539 * @param raw The raw version of the message part to parse.
31540 * @returns An object containing the `text` of the message part and the text of the `block`, if it
31541 * exists.
31542 * @throws an error if the `block` is unterminated
31543 */
31544
31545
31546function splitBlock(cooked, raw) {
31547  if (raw.charAt(0) !== BLOCK_MARKER$1) {
31548    return {
31549      text: cooked
31550    };
31551  } else {
31552    const endOfBlock = findEndOfBlock(cooked, raw);
31553    return {
31554      block: cooked.substring(1, endOfBlock),
31555      text: cooked.substring(endOfBlock + 1)
31556    };
31557  }
31558}
31559
31560function computePlaceholderName(index) {
31561  return index === 1 ? 'PH' : `PH_${index - 1}`;
31562}
31563/**
31564 * Find the end of a "marked block" indicated by the first non-e
31564scaped colon.
31565 *
31566 * @param cooked The cooked string (where escaped chars have been processed)
31567 * @param raw The raw string (where escape sequences are still in place)
31568 *
31569 * @returns the index of the end of block marker
31570 * @throws an error if the block is unterminated
31571 */
31572
31573
31574function findEndOfBlock(cooked, raw) {
31575  for (let cookedIndex = 1, rawIndex = 1; cookedIndex < cooked.length; cookedIndex++, rawIndex++) {
31576    if (raw[rawIndex] === '\\') {
31577      rawIndex++;
31578    } else if (cooked[cookedIndex] === BLOCK_MARKER$1) {
31579      return cookedIndex;
31580    }
31581  }
31582
31583  throw new Error(`Unterminated $localize metadata block in "${raw}".`);
31584}
31585/**
31586 * @license
31587 * Copyright Google LLC All Rights Reserved.
31588 *
31589 * Use of this source code is governed by an MIT-style license that can be
31590 * found in the LICENSE file at https://angular.io/license
31591 */
31592
31593
31594class MissingTranslationError extends Error {
31595  constructor(parsedMessage) {
31596    super(`No translation found for ${describeMessage(parsedMessage)}.`);
31597    this.parsedMessage = parsedMessage;
31598    this.type = 'MissingTranslationError';
31599  }
31600
31601}
31602
31603function isMissingTranslationError(e) {
31604  return e.type === 'MissingTranslationError';
31605}
31606/**
31607 * Translate the text of the `$localize` tagged-string (i.e. `messageParts` and
31608 * `substitutions`) using the given `translations`.
31609 *
31610 * The tagged-string is parsed to extract its `messageId` which is used to find an appropriate
31611 * `ParsedTranslation`. If this doesn't match and there are legacy ids then try matching a
31612 * translation using those.
31613 *
31614 * If one is found then it is used to translate the message into a new set of `messageParts` and
31615 * `substitutions`.
31616 * The translation may reorder (or remove) substitutions as appropriate.
31617 *
31618 * If there is no translation with a matching message id then an error is thrown.
31619 * If a translation contains a placeholder that is not found in the message being translated then an
31620 * error is thrown.
31621 */
31622
31623
31624function translate$1(translations, messageParts, substitutions) {
31625  const message = parseMessage(messageParts, substitutions); // Look up the translation using the messageId, and then the legacyId if available.
31626
31627  let translation = translations[message.id]; // If the messageId did not match a translation, try matching the legacy ids instead
31628
31629  if (message.legacyIds !== undefined) {
31630    for (let i = 0; i < message.legacyIds.length && translation === undefined; i++) {
31631      translation = translations[message.legacyIds[i]];
31632    }
31633  }
31634
31635  if (translation === undefined) {
31636    throw new MissingTranslationError(message);
31637  }
31638
31639  return [translation.messageParts, translation.placeholderNames.map(placeholder => {
31640    if (message.substitutions.hasOwnProperty(placeholder)) {
31641      return message.substitutions[placeholder];
31642    } else {
31643      throw new Error(`There is a placeholder name mismatch with the translation provided for the message ${describeMessage(message)}.\n` + `The translation contains a placeholder with name ${placeholder}, which does not exist in the message.`);
31644    }
31645  })];
31646}
31647/**
31648 * Parse the `messageParts` and `placeholderNames` out of a target `message`.
31649 *
31650 * Used by `loadTranslations()` to convert target message strings into a structure that is more
31651 * appropriate for doing translation.
31652 *
31653 * @param message the message to be parsed.
31654 */
31655
31656
31657function parseTranslation(messageString) {
31658  const parts = messageString.split(/{\$([^}]*)}/);
31659  const messageParts = [parts[0]];
31660  const placeholderNames = [];
31661
31662  for (let i = 1; i < parts.length - 1; i += 2) {
31663    placeholderNames.push(parts[i]);
31664    messageParts.push(`${parts[i + 1]}`);
31665  }
31666
31667  const rawMessageParts = messageParts.map(part => part.charAt(0) === BLOCK_MARKER$1 ? '\\' + part : part);
31668  return {
31669    text: messageString,
31670    messageParts: makeTemplateObject(messageParts, rawMessageParts),
31671    placeholderNames
31672  };
31673}
31674/**
31675 * Create a `ParsedTranslation` from a set of `messageParts` and `placeholderNames`.
31676 *
31677 * @param messageParts The message parts to appear in the ParsedTranslation.
31678 * @param placeholderNames The names of the placeholders to intersperse between the `messageParts`.
31679 */
31680
31681
31682function makeParsedTranslation(messageParts, placeholderNames = []) {
31683  let messageString = messageParts[0];
31684
31685  for (let i = 0; i < placeholderNames.length; i++) {
31686    messageString += `{$${placeholderNames[i]}}${messageParts[i + 1]}`;
31687  }
31688
31689  return {
31690    text: messageString,
31691    messageParts: makeTemplateObject(messageParts, messageParts),
31692    placeholderNames
31693  };
31694}
31695/**
31696 * Create the specialized array that is passed to tagged-string tag functions.
31697 *
31698 * @param cooked The message parts with their escape codes processed.
31699 * @param raw The message parts with their escaped codes as-is.
31700 */
31701
31702
31703function makeTemplateObject(cooked, raw) {
31704  Object.defineProperty(cooked, 'raw', {
31705    value: raw
31706  });
31707  return cooked;
31708}
31709
31710function describeMessage(message) {
31711  const meaningString = message.meaning && ` - "${message.meaning}"`;
31712  const legacy = message.legacyIds && message.legacyIds.length > 0 ? ` [${message.legacyIds.map(l => `"${l}"`).join(', ')}]` : '';
31713  return `"${message.id}"${legacy} ("${message.text}"${meaningString})`;
31714}
31715/**
31716 * @license
31717 * Copyright Google LLC All Rights Reserved.
31718 *
31719 * Use of this source code is governed by an MIT-style license that can be
31720 * found in the LICENSE file at https://angular.io/license
31721 */
31722
31723/**
31724 * Load translations for use by `$localize`, if doing runtime translation.
31725 *
31726 * If the `$localize` tagged strings are not going to be replaced at compiled time, it is possible
31727 * to load a set of translations that will be applied to the `$localize` tagged strings at runtime,
31728 * in the browser.
31729 *
31730 * Loading a new translation will overwrite a previous translation if it has the same `MessageId`.
31731 *
31732 * Note that `$localize` messages are only processed once, when the tagged string is first
31733 * encountered, and does not provide dynamic language changing without refreshing the browser.
31734 * Loading new translations later in the application life-cycle will not change the translated text
31735 * of messages that have already been translated.
31736 *
31737 * The message IDs and translations are in the same format as that rendered to "simple JSON"
31738 * translation files when extracting messages. In particular, placeholders in messages are rendered
31739 * using the `{$PLACEHOLDER_NAME}` syntax. For example the message from the following template:
31740 *
31741 * ```html
31742 * <div i18n>pre<span>inner-pre<b>bold</b>inner-post</span>post</div>
31743 * ```
31744 *
31745 * would have the following form in the `translations` map:
31746 *
31747 * ```ts
31748 * {
31749 *   "2932901491976224757":
31750 *      "pre{$START_TAG_SPAN}inner-pre{$START_BOLD_TEXT}bold{$CLOSE_BOLD_TEXT}inner-post{$CLOSE_TAG_SPAN}post"
31751 * }
31752 * ```
31753 *
31754 * @param translations A map from message ID to translated message.
31755 *
31756 * These messages are processed and added to a lookup based on their `MessageId`.
31757 *
31758 * @see `clearTranslations()` for removing translations loaded using this function.
31759 * @see `$localize` for tagging messages as needing to be translated.
31760 * @publicApi
31761 */
31762
31763
31764function loadTranslations(translations) {
31765  // Ensure the translate function exists
31766  if (!$localize.translate) {
31767    $localize.translate = translate;
31768  }
31769
31770  if (!$localize.TRANSLATIONS) {
31771    $localize.TRANSLATIONS = {};
31772  }
31773
31774  Object.keys(translations).forEach(key => {
31775    $localize.TRANSLATIONS[key] = parseTranslation(translations[key]);
31776  });
31777}
31778/**
31779 * Remove all translations for `$localize`, if doing runtime translation.
31780 *
31781 * All translations that had been loading into memory using `loadTranslations()` will be removed.
31782 *
31783 * @see `loadTranslations()` for loading translations at runtime.
31784 * @see `$localize` for tagging messages as needing to be translated.
31785 *
31786 * @publicApi
31787 */
31788
31789
31790function clearTranslations() {
31791  $localize.translate = undefined;
31792  $localize.TRANSLATIONS = {};
31793}
31794/**
31795 * Translate the text of the given message, using the loaded translations.
31796 *
31797 * This function may reorder (or remove) substitutions as indicated in the matching translation.
31798 */
31799
31800
31801function translate(messageParts, substitutions) {
31802  try {
31803    return translate$1($localize.TRANSLATIONS, messageParts, substitutions);
31804  } catch (e) {
31805    console.warn(e.message);
31806    return [messageParts, substitutions];
31807  }
31808}
31809/**
31810 * @license
31811 * Copyright Google LLC All Rights Reserved.
31812 *
31813 * Use of this source code is governed by an MIT-style license that can be
31814 * found in the LICENSE file at https://angular.io/license
31815 */
31816// Always use __globalThis if available, which is the spec-defined global variable across all
31817// environments, then fallback to __global first, because in Node tests both __global and
31818// __window may be defined and _global should be __global in that case. Note: Typeof/Instanceof
31819// checks are considered side-effects in Terser. We explicitly mark this as side-effect free:
31820// https://github.com/terser/terser/issues/250.
31821
31822
31823const _global = /* @__PURE__ */(() => typeof globalThis !== 'undefined' && globalThis || typeof global !== 'undefined' && global || typeof window !== 'undefined' && window || typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope && self)();
31824/**
31825 * @license
31826 * Copyright Google LLC All Rights Reserved.
31827 *
31828 * Use of this source code is governed by an MIT-style license that can be
31829 * found in the LICENSE file at https://angular.io/license
31830 */
31831
31832/**
31833 * Tag a template literal string for localization.
31834 *
31835 * For example:
31836 *
31837 * ```ts
31838 * $localize `some string to localize`
31839 * ```
31840 *
31841 * **Providing meaning, description and id**
31842 *
31843 * You can optionally specify one or more of `meaning`, `description` and `id` for a localized
31844 * string by pre-pending it with a colon delimited block of the form:
31845 *
31846 * ```ts
31847 * $localize`:meaning|description@@id:source message text`;
31848 *
31849 * $localize`:meaning|:source message text`;
31850 * $localize`:description:source message text`;
31851 * $localize`:@@id:source message text`;
31852 * ```
31853 *
31854 * This format is the same as that used for `i18n` markers in Angular templates. See the
31855 * [Angular i18n guide](guide/i18n-common-prepare#mark-text-in-component-template).
31856 *
31857 * **Naming placeholders**
31858 *
31859 * If the template literal string contains expressions, then the expressions will be automatically
31860 * associated with placeholder names for you.
31861 *
31862 * For example:
31863 *
31864 * ```ts
31865 * $localize `Hi ${name}! There are ${items.length} items.`;
31866 * ```
31867 *
31868 * will generate a message-source of `Hi {$PH}! There are {$PH_1} items`.
31869 *
31870 * The recommended practice is to name the placeholder associated with each expression though.
31871 *
31872 * Do this by providing the placeholder name wrapped in `:` characters directly after the
31873 * expression. These placeholder names are stripped out of the rendered localized string.
31874 *
31875 * For example, to name the `items.length` expression placeholder `itemCount` you write:
31876 *
31877 * ```ts
31878 * $localize `There are ${items.length}:itemCount: items`;
31879 * ```
31880 *
31881 * **Escaping colon markers**
31882 *
31883 * If you need to use a `:` character directly at the start of a tagged string that has no
31884 * metadata block, or directly after a substitution expression that has no name you must escape
31885 * the `:` by preceding it with a backslash:
31886 *
31887 * For example:
31888 *
31889 * ```ts
31890 * // message has a metadata block so no need to escape colon
31891 * $localize `:some description::this message starts with a colon (:)`;
31892 * // no metadata block so the colon must be escaped
31893 * $localize `\:this message starts with a colon (:)`;
31894 * ```
31895 *
31896 * ```ts
31897 * // named substitution so no need to escape colon
31898 * $localize `${label}:label:: ${}`
31899 * // anonymous substitution so colon must be escaped
31900 * $localize `${label}\: ${}`
31901 * ```
31902 *
31903 * **Processing localized strings:**
31904 *
31905 * There are three scenarios:
31906 *
31907 * * **compile-time inlining**: the `$localize` tag is transformed at compile time by a
31908 * transpiler, removing the tag and replacing the template literal string with a translated
31909 * literal string from a collection of translations provided to the transpilation tool.
31910 *
31911 * * **run-time evaluation**: the `$localize` tag is a run-time function that replaces and
31912 * reorders the parts (static strings and expressions) of the template literal string with strings
31913 * from a collection of translations loaded at run-time.
31914 *
31915 * * **pass-through evaluation**: the `$localize` tag is a run-time function that simply evaluates
31916 * the original template literal string without applying any translations to the parts. This
31917 * version is used during development or where there is no need to translate the localized
31918 * template literals.
31919 *
31920 * @param messageParts a collection of the static parts of the template string.
31921 * @param expressions a collection of the values of each placeholder in the template string.
31922 * @returns the translated string, with the `messageParts` and `expressions` interleaved together.
31923 *
31924 * @globalApi
31925 * @publicApi
31926 */
31927
31928
31929const $localize$1 = function (messageParts, ...expressions) {
31930  if ($localize$1.translate) {
31931    // Don't use array expansion here to avoid the compiler adding `__read()` helper unnecessarily.
31932    const translation = $localize$1.translate(messageParts, expressions);
31933    messageParts = translation[0];
31934    expressions = translation[1];
31935  }
31936
31937  let message = stripBlock(messageParts[0], messageParts.raw[0]);
31938
31939  for (let i = 1; i < messageParts.length; i++) {
31940    message += expressions[i - 1] + stripBlock(messageParts[i], messageParts.raw[i]);
31941  }
31942
31943  return message;
31944};
31945
31946const BLOCK_MARKER = ':';
31947/**
31948 * Strip a delimited "block" from the start of the `messagePart`, if it is found.
31949 *
31950 * If a marker character (:) actually appears in the content at the start of a tagged string or
31951 * after a substitution expression, where a block has not been provided the character must be
31952 * escaped with a backslash, `\:`. This function checks for this by looking at the `raw`
31953 * messagePart, which should still contain the backslash.
31954 *
31955 * @param messagePart The cooked message part to process.
31956 * @param rawMessagePart The raw message part to check.
31957 * @returns the message part with the placeholder name stripped, if found.
31958 * @throws an error if the block is unterminated
31959 */
31960
31961function stripBlock(messagePart, rawMessagePart) {
31962  return rawMessagePart.charAt(0) === BLOCK_MARKER ? messagePart.substring(findEndOfBlock(messagePart, rawMessagePart) + 1) : messagePart;
31963}
31964/**
31965 * @license
31966 * Copyright Google LLC All Rights Reserved.
31967 *
31968 * Use of this source code is governed by an MIT-style license that can be
31969 * found in the LICENSE file at https://angular.io/license
31970 */
31971
31972/**
31973 * @license
31974 * Copyright Google LLC All Rights Reserved.
31975 *
31976 * Use of this source code is governed by an MIT-style license that can be
31977 * found in the LICENSE file at https://angular.io/license
31978 */
31979
31980/**
31981 * @license
31982 * Copyright Google LLC All Rights Reserved.
31983 *
31984 * Use of this source code is governed by an MIT-style license that can be
31985 * found in the LICENSE file at https://angular.io/license
31986 */
31987
31988/**
31989 * @license
31990 * Copyright Google LLC All Rights Reserved.
31991 *
31992 * Use of this source code is governed by an MIT-style license that can be
31993 * found in the LICENSE file at https://angular.io/license
31994 */
31995
31996
31997
31998
31999/***/ })
32000
32001},
32002/******/ __webpack_require__ => { // webpackRuntimeModules
32003/******/ var __webpack_exec__ = (moduleId) => (__webpack_require__(__webpack_require__.s = moduleId))
32004/******/ var __webpack_exports__ = (__webpack_exec__(7435));
32005/******/ }
32006]);
32007//# sourceMappingURL=polyfills.js.map

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.